Temperature, top-p és a determinizmus, ami nincs a kezedben
A temperature a softmax előtt osztja a logit értékeket: ez megöli a kreativitás-tárcsa mítoszát. Két azonos greedy hívás, két válasz.
Ezen az oldalon
Íme ugyanaz a kérés, ugyanannak a modellnek elküldve ötször. Ugyanazok a súlyok, ugyanaz a prompt, ugyanaz a gép, ugyanaz a random seed. Csak egyetlen szám változik.
prompt: "Q: What is the capital of France?\nA:"
T = 0.0 " Paris\nWhat is the question and does the answer answer it? The
question is: What is the capital of France?..."
T = 0.7 " Paris\nWhat is the question: Which city is the capital of
France?..."
T = 1.0 " Paris\nWhat is a good geographical qualifier for describing
Paris concerning its location?\nA: Near the Mediterranean Sea..."
T = 1.5 " Paris\nWhat clue from premise allows we to conclude that Godwin
was &, He chose Healing Crimson Colour No:white flour Pure..."
T = 2.0 "安全感金华.ITEMT]]];\naims assume parental.st-importe.valtermination
Screens قطر_Zeroหมายเลข-zA ('$ספטמבר..."Semmi nem romlott el. Az utolsó sor minden token eleme szabályosan a modell saját, 151 936 elemű szótárára adott valószínűségi eloszlásából lett kihúzva. A megváltoztatott szám neve temperature; a legtöbb dokumentáció kreativitás-tárcsaként írja le, és ez a leírás olyan módon téves, amit ez a fejezet nem állítani, hanem megmutatni fog.
Ez az a fejezet is, ahol három korábbi ígéret esedékessé válik. A 4. fejezet definiálta a logit fogalmát, de igazán nem költötte el. A 2. fejezet lebegőpontos doboza egy utasítással zárult — emlékezz erre, amikor a 17. fejezet azt kérdezi, miért adhat ugyanaz a prompt, modell és seed különböző token értékeket. A 9. fejezet mixture-of-experts doboza pedig a nemdeterminizmus négy okának katalógusát ígérte. Mindhárom alább érkezik.
Az egyetlen sor, amelyen az egész fejezet függ
Link a szakaszhoz: Az egyetlen sor, amelyen az egész fejezet függA 4. fejezet a logit értéket normalizálatlan, valós számú pontszámként vezette be, osztályonként egyet. A 8. fejezet elérte, hogy egy nyelvi modell minden szótárelemhez ilyet állítson elő. A softmax ezt a vektort valószínűségekké alakítja:
A temperature itt lép be — a név a statisztikus fizikából származik, ahol ugyanez a paraméter szabályozza, milyen élesen koncentrálódik egy Boltzmann-eloszlás az alacsony energiájú állapotaira1 — és az exponenciálás előtt osztja el a logit értékeket:
Ez az elhelyezés a teljes mechanizmus, és két sornyi algebra megéri, hogy látszódjon, miért nem lehetne máshol. Tegyük fel, hogy a temperature értéket inkább a valószínűségekre próbálnád alkalmazni — megszoroznád őket értékkel, majd újranormalizálnád. Ezt kapnád:
A konstans kiesik. A valószínűségek skálázása semmit nem csinál; az eloszlás változatlanul visszatér. A temperature csak azért hat, mert az exponensen működik: értékkel osztani az exponenciálás előtt ugyanaz, mint minden valószínűséget hatványra emelni — ez egy nemlineáris átformálás, amely az elemek közötti arányokat változtatja meg, nem a közös skálájukat.
Ebből az elhelyezésből mindkét határérték minden további munka nélkül következik. Ahogy , a legnagyobb logit elszökik a többitől, és rázuhan az egyetlen legmagasabb pontszámú token elemre: ez a greedy decoding. Ahogy nő, minden nullához tart, minden exponenciális tag 1-hez tart, és az eloszlás a teljes szótáron egyenleteshez lapul. Pontosan esetén a képlet nullával oszt, ezért minden implementáció külön kezeli, és az aritmetikai maximumra vált — beleértve az alábbi widgetet is, amely esetén argmaxra kapcsol.
Egy figyelmeztetés, mert a névütközés valódi zavart okoz. Van a gépi tanulásban egy másik, ettől független dolog is, amelyet temperature néven emlegetnek: temperature scaling, egy kalibrációs módszer, amely egy validációs halmazon illeszt egy értéket, hogy egy osztályozó magabiztossága megfeleljen a pontosságának.2 Ugyanaz a képlet, semmi köze a generáláshoz. Amikor cikkek „temperature” értéket mondanak, gyakran erre gondolnak; ez a fejezet soha nem.
Íme az eloszlás, az aritmetikával a szemed előtt. A logit értékek rögzítettek és hihetőek, így az alábbi próza számai ellenőrizhetők azzal, amit látsz:
A temperature nem kreativitás-tárcsa
Link a szakaszhoz: A temperature nem kreativitás-tárcsaA ␣banana szám miniatűrben az egész érv: a temperature emelése nem adhat a modellnek olyan ötletet, amely korábban nem volt meg benne. A logit értékek már ki vannak számolva, a rangsor már rögzített, és a temperature pontosan megőrzi — semennyi hő nem emel egy alacsonyabb pontszámú token elemet egy magasabb pontszámú fölé. Csak újraosztja a tömeget a modell saját maga által létrehozott rangsorában lefelé. A magas temperature nem teszi találékonyabbá a modellt; csak valószínűbbé teszi, hogy olyan token értékeket adjon ki, amelyeket rossznak pontozott.
Valódi szótáron ez már nem érdekesség, hanem annak az oka, hogy a magas temperature kimenet használhatatlan. Qwen/Qwen2.5-0.5B-Instruct modellen mérve, egy forward pass, a fenti prompt mellett, azt számolva, hány token kell a valószínűségi tömeg adott részének összegyűjtéséhez:
| temperature | top-1 probability | entropy | tokens holding 80 % | 90 % | 95 % | 99 % |
|---|---|---|---|---|---|---|
| 0.5 | 99.98 % | 0.00 nats | 1 | 1 | 1 | 1 |
| 0.7 | 99.65 % | 0.03 nats | 1 | 1 | 1 | 1 |
| 1.0 | 96.01 % | 0.30 nats | 1 | 1 | 1 | 14 |
| 1.2 | 88.20 % | 0.88 nats | 1 | 2 | 13 | 252 |
| 1.5 | 62.83 % | 3.07 nats | 29 | 353 | 2,672 | 26,787 |
| 2.0 | 16.62 % | 8.19 nats | 13,516 | 32,966 | 55,231 | 101,205 |
Olvasd lassan az alsó sort. mellett, egy pontosan egy helyes válasszal rendelkező kérdésnél 32 966 különböző token osztozik a valószínűségi tömeg felső 90 %-án. Ez nem szélesebb kreatív tér. Ez egy modell, amelynek az aritmetika azt mondta, hogy egy koreai partikula és egy C++ azonosító is élő opció a A: utáni szóként. A nyitó blokk szemete ennek a közvetlen következménye, és nem hiba a modellben vagy a könyvtárban — pontosan ezt kérte a hívás.
A hasznos tartomány szűk, és a feladattól függ, nem ízléstől. Egy tényszerű kérdésnél a válasz egy token, és nagyjából 1,2 fölött minden hő csak hibát injektál a semmiért. Egy nyílt végűnél valóban több jó folytatás létezik, és némi hő olyan változatosságot vásárol, amely folyékony marad:
"Write a two-sentence story about a lighthouse."
T = 0.0 "The lighthouse stood tall and proud, its beacon illuminating the
night sky above. A lone sailor, his eyes fixed on the distant
horizon..."
T = 0.7 "In the quiet, stormy waters of the sea, a lighthouse stood
sentinel over the horizon, its golden dome casting a warm glow
on the fog-shrouded streets below..."
T = 1.0 "In the quiet night, a lone lighthouse stood sentinel over the
sea, its shining beacon a beacon of hope and solace for sailors
and fishermen across the vast and endless ocean..."
T = 1.3 "In the gentle sunlight, now reflecting upon the opening of Jack's
lighthouse, Jim Trahan, a small-time individual difficult to
define in paperwork, wondered about a career where simplicity
reigns..."1,3-nál a modell kitalált egy tulajdonnevet és egy mondatot, amely nem parse-olható. Az „minden alkalommal azonos” és az „inkoherens” közti sáv ennél a modellnél, ezen a feladaton nagyjából 0,6 és 1,1 között van, és az őszinte tanács az, hogy a saját feladatodon méréssel találd meg, ne egy blogposztból másolj át egy számot.
Miért rossz szöveg a legvalószínűbb szöveg
Link a szakaszhoz: Miért rossz szöveg a legvalószínűbb szövegEgy nyilvánvaló kérdés bújik meg mindez alatt: ha a modellnek van valószínűségi eloszlása, és egy token a legvalószínűbb, miért ne vennénk mindig azt? A greedy decoding ingyenes, reprodukálható, és nem igényel paramétereket.
Mert az eredmény ez:
prompt: "In a shocking finding, scientists discovered a herd of unicorns
living in a remote valley."
greedy: " The unicorns were so rare that they were not even recognized by
the local people. The unicorns were so rare that they were not
even recognized by the local people. The unicorns were so rare
that they were not even recognized by the local people. ..."
repeated 4-grams: 87.6 %Nyolc mondat, egy mondat. A négy-token ablakok közel kilencven százaléka már korábban is megjelent ugyanabban a kimenetben. Ez a neural text degeneration, amelyet Holtzman és szerzőtársai neveztek el és magyaráztak meg abban a cikkben, amely bevezette a top-p módszert.3 A modell nem romlott el; a szekvenciavalószínűség maximalizálása egyszerűen rossz célfüggvény nyílt végű szöveghez. Az emberi írás nem a szavak legvalószínűbb sorozata — hordoz meglepetést, a tokenenkénti valószínűsége vándorol, süllyed és helyreáll — miközben a maximális valószínűségű út egy fixpont, amelynek belépés után nincs oka kilépni.
Ezért létezik egyáltalán sampling. És ugyanakkor — ez az a rész, amely gyakran kimarad — ez nem univerzális törvény. A 12. fejezet kétlépéses szófeladatokon 24-ből 24 helyes választ mért egyszerű greedy decoding mellett, a 0,8-as temperature sampling pedig ezt 81 %-ra ejtette; a self-consistency ezután hatszor annyi token elköltésével mászott vissza oda, ahol a greedy már eleve volt. Mindkét tény egyszerre igaz:
Nyílt végű generálás. Nincs egyetlen helyes folytatás, ezért a legvalószínűbb egy csapda — loopol, és 87,6 %-át saját magából másolja. Sample.
Egy helyes válasszal rendelkező feladatok. Van egyetlen helyes folytatás, ezért bármi más kihúzása hiba kihúzása. A 12. fejezet 100 %-a pontosan emiatt lett 81 %. Ne sample-elj.
A legtöbb production prompt a második típus, mégis az elsőhöz hasonlóan konfigurálják, mert a temperature ott maradt azon, amit a példakód használt.
Kétféle vágás, és csak az egyik alkalmazkodik
Link a szakaszhoz: Kétféle vágás, és csak az egyik alkalmazkodikA teljes eloszlásból samplingolni valójában senki nem szokott, mert a farok óriási és tele van értelmetlenséggel. Valamit le kell vágni. Két klasszikus válasz van, és egyetlen tekintetben különböznek, amely mindent eldönt.
Top-k fix számú jelöltet tart meg. Valószínűség szerint rendezz, tartsd meg az első elemet, dobd el a többit, normalizálj újra.4 Top-p, más néven nucleus sampling, fix mennyiségű tömeget tart meg: csökkenő sorrendben veszi a token értékeket, amíg az összesített valószínűség el nem éri értéket, majd megáll.3 Formálisan a nucleus a legkisebb halmaz, amelyre
A különbség kozmetikainak hangzik, de nem az, mert két, ugyanabban a percben elküldött prompt teljesen különböző eloszlásalakot kaphat. Mindkettő ugyanaz a modell, 1-es temperature mellett:
Q: What is the capital of France?\nA: | Once upon a time, | |
|---|---|---|
| top-1 probability | 96.01 % | 25.39 % |
| tokens holding 90 % of the mass | 1 | 467 |
| top-k = 40 keeps | 99.61 % of the mass | 78.87 % of the mass |
| mass in ranks 2 to 40 | 3.61 % | 53.48 % |
| token at rank 40 | ␣Av, 0.0093 % | ␣Dr, 0.128 % |
Egy fix , két ellentétes irányú kudarc. A tényszerű prompt esetén beenged 39 token elemet, amelyek együtt 3,6 %-ot érnek — átengedi a szemetet, köztük egy ezredszázalékos nagyságrendű jelöltet, mert a szabály helyeket számol, nem bizonyítékot. A történetes prompt esetén ugyanaz a kidobja a tömeg 21 %-át, amelyet a modell valóban kiosztott, mert ott az igazi nucleus 467 token széles.
A top-p pontosan egy számmal végzi el mindkét feladatot. Állítsd be értékre, és az első promptnál 1 token marad, a másodiknál 467, mert az eloszlásról tesz fel kérdést, nem darabszámot kényszerít rá. Nézd meg közvetlenül ezt az alkalmazkodást — ugyanaz a vágás, négy temperature:
Ez a widget egy olyan tévhitet is eldönt, amelyet érdemes néven nevezni, mert valódi pénzbe kerül. Magabiztos eloszlásnál top_p = 0.9 nem „egy kis változatosság”. Hanem greedy. 1-es temperature mellett a vezető token itt 96,90 %-ot tart, ami már 0,9 fölött van, ezért a nucleus egy token széles, és semmi más nem húzható ki. Csapatok top_p értékre állítják 0,9-et abban a hitben, hogy lazítottak valamin, aztán csodálkoznak, miért azonos minden válasz.
Ha ehelyett top-k értéket állítasz, az ellenkező kudarc ugyanilyen jól látható:
A büntetések, képletekkel, mert összekeverésük népbetegség
Link a szakaszhoz: A büntetések, képletekkel, mert összekeverésük népbetegségHárom különböző mechanizmus utazik hasonló neveken, más dolgokat csinálnak, és a különbség mérhető. Legyen annak száma, hányszor jelent már meg a token.
Presence penalty
Link a szakaszhoz: Presence penaltyVonj le egy konstanst minden olyan token értékből, amely egyáltalán megjelent. Egyszer megjelenni és negyvenszer megjelenni ugyanakkora büntetést kap. Ez kapcsoló, nem tárcsa.
Frequency penalty
Link a szakaszhoz: Frequency penaltyVonj le a darabszámmal arányosan. Egy négyszer használt token négyszer akkora büntetést kap, mint egy egyszer használt token, és a nyomás a szöveg növekedésével halmozódik.
Repetition penalty (CTRL)
Link a szakaszhoz: Repetition penalty (CTRL)Az eredeti, a CTRL cikkből.7 Oszt, nem kivon; az előjelkezelés azért kell, mert egy negatív logit elosztása nagyobbá tenné. Erőssége ezért a logit nagyságától függ, ami azt jelenti, hogy ugyanaz a a mondat különböző pontjain másként üt.
Ugyanaz a korábbi degenerált folytatás, mindegyik alkalmazásával. A „megváltoztatott lépések” azt számolja, a 120 generálási lépésből hány választott más token elemet, mint amit a büntetés nélküli modell választott volna. A futás itt 120 lépés, szemben a fenti blokk 140 lépésével, ezért a büntetés nélküli baseline 87,6 % helyett 85,5 %-ot mutat:
| setting | repeated 4-grams | steps altered |
|---|---|---|
| nothing | 85.5 % | 0 / 120 |
| presence 0.5 | 65.0 % | 3 / 120 |
| presence 1.0 | 3.4 % | 11 / 120 |
| frequency 0.5 | 6.0 % | 12 / 120 |
| frequency 1.0 | 0.0 % | 20 / 120 |
| repetition 1.2 (CTRL) | 0.0 % | 35 / 120 |
Három dolog következik. A 0,5-ös presence 120-ból három döntést változtatott meg, és negyedével vágta le az ismétlést — a loopot néhány token tartotta össze. A 0,5-ös frequency négyszer annyi döntést változtatott meg, sokkal nagyobb hatással, mert a darabszám-szorzó tovább nő, a presence konstans viszont nem. A széles körben másolt 1,2-es CTRL penalty pedig 120-ból 35 döntést írt át, ami nem finom lökés; ez egy másik modell.
Ez az utolsó szám készíti elő azt a hibát, amelyre senki nem figyelmeztet.
Mit tesznek a büntetések azzal a szöveggel, amelynek ismétlődnie kell
Link a szakaszhoz: Mit tesznek a büntetések azzal a szöveggel, amelynek ismétlődnie kellA kód ismétel. A táblák ismételnek. A listák ismételnek. A strukturált kimenet definíció szerint ismétel — ettől struktúra. Egy penalty nem tud különbséget tenni aközött, hogy a modell loopba ragadt, vagy helyesen kibocsátja egy tábla negyedik sorát, mert mindkettő úgy néz ki, mint egy token újbóli megjelenése.
Ugyanaz a három feladat, háromféleképpen generálva:
| task | nothing | frequency 0.5 | repetition 1.2 |
|---|---|---|---|
| markdown table, 6 rows | 0 / 56 steps altered | 0 / 56 | 2 / 62 |
| Python function | 0 / 93 | 0 / 93 | 10 / 110 |
| bulleted list, 1 to 12 | 0 / 50 | 0 / 50 | 0 / 50 |
A 0,5-ös frequency penalty mindháromnál ártalmatlannak bizonyult, ami hasznos és kissé meglepő eredmény, és valami pontosat mond: mivel egyetlen döntés sem változott, a strukturális token elemeknek a pozíciójukban többel kellett nyerniük, mint amennyit a penalty levont, még öt-hat megjelenés után is. A CTRL penalty, amely viszont oszt, már kimozdítja őket, és ezt állította elő:
repetition 1.2, markdown table:
| n | 2^n |
| --- | --- |
| 0 | 1 |
| 1 | 2 |
| 2 | 4 |Az igazítás szétesik: az egyes cellákon belüli kitöltés mennyisége sorról sorra változik, mert a záró pipe előtti szóközsorozat pontosan az a fajta ismétlés, amelyet a penalty szét akar törni. Kozmetikai hiba, és hat extra tokenbe került. A Python eset nem kozmetikai:
nothing / frequency 0.5:
total = 0
for i in range(1, n + 1):
total += i ** 2
return total
repetition 1.2:
# Initialize total_sum with 0
total_sum = 0
# Loop through numbers from 1 to n, incrementing by 2 each time
for i in range(1, n + 1,A penalty letolta a modellt total értékről — amelyet már használt a docstringben — total_sum értékre, kitalált kommentekkel tömte ki a kimenetet, hogy a költségkeretét fel nem használt token értékekre költse, majd besétált egy háromargumentumos range hívásba stride-dal. A komment azt mondja: incrementing by 2 each time, ami rossz 1-től -ig vett négyzetösszegre. Egy repetition penalty helytelen kódot állított elő egy promptból, amelyre nélküle helyes válasz született.
Az ebből következő szabály rövid: a büntetések nyílt végű prózához valók, és ki kell kapcsolni őket kódnál, strukturált kimenetnél, táblázatos adatnál és bárminél, aminek schema-ja van. A 18. fejezet pontosan erről a második kategóriáról szól.
Az alkalmazás sorrendje, és miért változtatja meg a választ
Link a szakaszhoz: Az alkalmazás sorrendje, és miért változtatja meg a választMinden valódi implementáció ezeket egy konkrét sorrendben alkalmazza:
penalties → temperature → top-k → top-p → sample
Ez nem önkényes könyvelés, és két lépés felcserélése ténylegesen más eloszlásokat eredményez. Két mérés, mindkettő a tényszerű prompton.
Vágás a temperature előtt vagy után. A nucleus azon az eloszláson számolódik, amelyet kap, és a temperature radikálisan megváltoztatja ezt az eloszlást:
| top-p 0.9 after temperature | top-p 0.9 before temperature | |
|---|---|---|
| 1 token | 1 token | |
| 353 tokens | 1 token | |
| 32,966 tokens | 1 token |
mellett ugyanaz a névleges beállítás 32 966-os vagy 1-es jelölthalmazt ad, kizárólag attól függően, melyik lépés fut előbb. Ha valaha elgondolkodtál, miért „nem csinál semmit” a temperature emelése az egyik provider esetén, és miért teszi tönkre a kimenetet egy másiknál ugyanazzal a két számmal, ez a táblázat hihető válasz.
Büntetés a temperature előtt vagy után. Ha levonsz egy penalty értéket, majd osztasz értékkel, az effektív penalty lesz; ha előbb osztasz, majd utána vonsz le, akkor . A vezető token elemre alkalmazott 1,0-s presence penalty mellett:
| temperature | penalise, then temper | temper, then penalise |
|---|---|---|
| 0.5 | 99.858 % | 99.948 % |
| 1.0 | 89.839 % | 89.839 % |
| 2.0 | 10.783 % | 6.830 % |
mellett azonosak, ahogy annak lennie kell. mellett 1,58-szoros különbség. A „presence penalty 1.0” nem jól definiált büntetésmennyiség, hacsak azt is nem tudod, hol alkalmazzák a temperature értéket, és ezt egyetlen API sem dokumentálja.
Részletek megjelenítése
Opcionális: az egész pipeline a fenti sorrendben.
Tizenhat sor, és ebben benne van minden, amiről ez a fejezet szól. Ugyanaz a számítás, amelyet a widget végez, csak tíz fix szám helyett valódi logit vektoron.
def sample(logits, counts, presence=0.0, frequency=0.0,
temperature=1.0, top_k=0, top_p=1.0, generator=None):
z = logits.clone()
idx = torch.tensor(list(counts)) # 1. penalties
if len(idx):
z[idx] -= presence
z[idx] -= frequency * torch.tensor([float(c) for c in counts.values()])
if temperature <= 0: # 2. temperature
return int(z.argmax()) # T=0 is argmax
p = torch.softmax(z / temperature, -1)
p, order = p.sort(descending=True)
if top_k: # 3. top-k
p[top_k:] = 0
p = p * ((p.cumsum(0) - p) < top_p) # 4. top-p
p = p / p.sum() # 5. renormalise
return int(order[torch.multinomial(p, 1, generator=generator)])A top-p sorban lévő cumsum(0) - p az összesített tömeg az aktuális token nélkül, és ettől kerül be a nucleusba az a token is, amely átlépi a küszöböt, nem áll meg közvetlenül előtte. Ha ezt eggyel elrontod, a top_p = 0.9 csendben kicsit szűkebb vágássá válik, mint minden más implementációban.
Ez a kurzus második felének kevés olyan pontja közé tartozik, ahol a Python a megfelelő nyelv, és az ok strukturális, nem stilisztikai: a fenti minden sorhoz a teljes logit vektornak a kezedben kell lennie, HTTP API felett pedig ez a vektor nem létezik. Elküldheted temperature és top_p értékeket egy providernek; nem implementálhatod őket, és nem láthatod, mit csináltak.
Nincs univerzális sampling API
Link a szakaszhoz: Nincs univerzális sampling APIMinden provider ezeknek a vezérlőknek más részhalmazát fogadja, eltérő tartományokkal, és a többit csendben figyelmen kívül hagyja. Ez nem absztrakt panasz. Minden alkalmazásnak, amely modellválasztást kínál, valahol le kell írnia a különbségeket, és az a fájl, ahol ezt megteszi, az inkompatibilitás térképe. Íme, mit deklarál egy ilyen katalógus egyetlen paraméterre azon a kilenc szövegforráson át, amelyet támogat:
| declared temperature range | sources |
|---|---|
| 0 to 1 | Anthropic, Google, Meta, Cerebras, PaLM |
| 0 to 1.5 | Mistral |
| 0 to 2 | OpenAI, DeepSeek, xAI |
A szó ugyanaz; a skála nem. Az „1-es temperature” az egyiknél a módosítatlan eloszlás, a másiknál a maximálisan engedélyezett hő, és a katalógus fele nem tudja kifejezni azt az értéket, amelyet a másik fele semleges-plusz-egy-kicsinek kezel. A többi gomb ugyanilyen egyenetlen: az OpenAI, DeepSeek és xAI bejegyzések presence és frequency penalty értékeket fogadnak, topK nélkül; a Google, Meta, Cerebras és PaLM bejegyzések topK értéket fogadnak, penalty nélkül; az Anthropic topK, topP és stop sequences értékeket fogad, penalty nélkül; és a kilencből pontosan egy — a Mistral — fogad seed értéket. Ha olyan paramétert küldesz, amelyet egy provider nem implementál, általában semmilyen hiba nem keletkezik: a kérés sikerül, a gomb nem csinál semmit, te pedig arra következtetsz, hogy a beállításnak nincs hatása.
És vedd észre, mi egy ilyen fájl: egy állítás valaki más API-járól, egy konkrét napon leírva, amelyet utólag semmi nem ellenőriz. Egy katalógus, amely 0-tól 1-ig tartományt mond egy olyan providerre, amely már 0-tól 2-ig fogad, csendben levág minden kérést.
Két további vezérlő ugyanabba a családba tartozik. logprobs, ahol elérhető, visszaadja a kiválasztott token log-valószínűségeit és gyakran a néhány legjobb alternatívát — ez az egyetlen ablakod arra az eloszlásra, amelyről ez a fejezet szól, és minden zárt modellre épített confidence heurisztika alapja. A maximum tokens és a stop sequences pedig a valószínűségtől teljesen függetlenül állítják meg a generálást: egy kemény plafon és egy string-illesztés. Mindkettő a 14. fejezet finish_reason értékeként jelenik meg, ahol length azt jelenti, hogy a válaszodat egy keret vágta félbe a mondat közepén, nem a modell fejezte be.
A seed és a determinizmus, ami nincs a kezedben
Link a szakaszhoz: A seed és a determinizmus, ami nincs a kezedbenÁllíts be seed értéket, és a sampling reprodukálhatóvá válik. Ez a rész valódi, és könnyű ellenőrizni:
seed = 1234 " Paris\nWhat is a good geographical qualifier for describing
Paris concerning its location?\nA: Near the Mediterranean Sea"
seed = 1234 " Paris\nWhat is a good geographical qualifier for describing
Paris concerning its location?\nA: Near the Mediterranean Sea"
seed = 7 " Paris is the capital of France. The appellation of Paris is
\"Île de Paris\"."
seed = 7 " Paris is the capital of France. The appellation of Paris is
\"Île de Paris\"."Byte-ra azonos egy seed-en belül, különböző seed-ek között, pontosan ahogy hirdetik. Tehát amit a seed rögzít, az a sample function utolsó sorában lévő véletlen húzás — hogy egy adott eloszlásból melyik token kerül kiválasztásra.
Amit nem rögzít, az maga az eloszlás. És itt kezdődik a baj, mert a modell által előállított logit vektor nem matematikai objektum; milliárdnyi lebegőpontos összeadás kimenete, és ezeknek van sorrendjük.
A 2. fejezet készen hagyta ezt a kísérletet. Ugyanaz az egymillió float32 szám, különböző csoportosításokban összegezve:
sequential 998.564270020 error vs float64: 6.393e-03
pairwise (numpy) 998.570556641 error vs float64: 1.061e-04
in 4 chunks 998.570495605 error vs float64: 1.672e-04
in 8 chunks 998.570556641 error vs float64: 1.061e-04
in 16 chunks 998.570678711 error vs float64: 1.594e-05
sequential == pairwise? False
4 chunks == 8 chunks? FalseNézd az utolsó sort. A chunkok száma megváltoztatja a választ. Ez nem numpy-érdekesség; ez a mechanizmus, mert amikor egy inference szerver több vagy kevesebb párhuzamos egységre bont egy redukciót, pontosan ezt csinálja. A szerver pedig aszerint bont, hány kérést szolgál ki.
Íme ugyanez a hatás magán a modellen. Ugyanaz a prompt, ugyanaz a forward pass, az egyetlen különbség az, hány más kérés került éppen a batchbe:
20 identical forward passes, batch of 1: 20 / 20 bit-for-bit identical
the same prompt inside a batch of 2: 147,321 of 151,936 logits differ
the same prompt inside a batch of 4: 146,515 of 151,936 logits differ
the same prompt inside a batch of 8: 146,515 of 151,936 logits differ
the same prompt inside a batch of 16: 147,321 of 151,936 logits differ
largest change to any logit: 2.5e-05Egyedül futtatva a modell tökéletesen determinisztikus — húsz pass, bitre azonos. Tedd ugyanazt a promptot egy batchbe nem kapcsolódó kérésekkel, és a logit értékeinek 97 %-a megváltozik. A te kérésedben semmi nem változott. Valaki más kérése megérkezett.
Most az őszinte rész, mert ezt általában úgy mesélik, mintha ez lenne a történet vége. Egy nagyságú változás csak akkor módosítja a kimenetet, ha két jelölt token ennyire közel volt egymáshoz. Tizenkét prompt 717 generálási lépése során a két legfelső logit közti legkisebb rés volt — százszor nagyobb, mint a perturbáció — és egy lépés sem volt elég közel a fliphez. Tehát ezen a modellen, float32-ben, laptopon, a batching minden logit értéket megmozdított, de egyetlen token elemet sem változtatott meg.
Ez kedvező feltételek leírása, nem megnyugtatás, és elég egyetlen feltételt megváltoztatni:
same weights, same prompts, greedy decoding, no seed involved
float32 vs bfloat16: 6 of 8 answers diverge
first divergence at step 23, on average
float32: "...it is scattered and dispersed into different colors,
including blue. The blue light is scattered more than other
colors, so it appears to come from the sky."
bfloat16: "...it is scattered and scattered, causing the colors of the
sun to be scattered and scattered, creating the appearance
of a blue color."A nyolc válaszból hat eltér, és az egyik erősen leromlik. A 2. fejezet táblázata megmondja, miért: a bfloat16 7 mantisszabitet tart meg, ezért 16-os logit nagyság közelében a reprezentálható értékek 0,125-re vannak egymástól — 16,0, aztán 16,125, aztán 16,25 — és a kerekítés akár 0,0625-tel is elmozdíthat egy logit értéket. Eközben a fent mért generálási lépések 4,7 %-ánál a felső két érték közti rés 0,1 alatt volt. Ez a teljes különbség a két kísérlet között: float32-ben a perturbáció százszor kisebb volt, mint a legközelebbi döntés, bfloat16-ban pedig azonos nagyságrendű. A production inference 16 biten fut, olyan hardveren, fused kernelekkel és redukciós sorrendekkel, amelyek megtartását senki nem ígéri. Az, hogy „a numerikus zaj elhanyagolható-e”, a precízióról és a hardverről szóló kérdés, nem a modellről.
Tehát a négy ok, ahogy a 9. fejezet ígérte:
A lebegőpontos összeadás nem asszociatív
Link a szakaszhoz: A lebegőpontos összeadás nem asszociatívA 2. fejezet doboza. Egy összeg értéke változik az összeadás sorrendjével, ezért bármilyen változás abban, hogyan bontanak fel egy redukciót, megváltoztatja a logit értékeket. Ez az alapréteg; a másik három ennek a sorrendnek a megváltoztatási módja.
A dynamic batching idegenekével csoportosítja a kérésedet
Link a szakaszhoz: A dynamic batching idegenekével csoportosítja a kérésedetA 13. fejezetből ismert continuous batching miatt megfizethető az inference — és ez azt jelenti, hogy azoknak a mátrixoknak az alakja, amelyeken a token értékeid átfolynak, a forgalomtól függ. Fent mérve: 147 321 logit mozdult el, mert változott a batch size.
A mixture-of-experts routing a batchtől függ
Link a szakaszhoz: A mixture-of-experts routing a batchtől függA 9. fejezet doboza már elmondta. A router diszkrét döntést hoz tokenenként és rétegenként, a batch felett számolt, szakértőnkénti kapacitáskorlátok mellett. Egy token, amely egyedül expert 7-hez ment volna, társaságban expert 12-höz megy. Ez nem kerekítési különbség; ez más súlykészlet.
A név mögötti modell megváltozik
Link a szakaszhoz: A név mögötti modell megváltozikEgy -latest típusú verzióstring pointer, és a pointereket átirányítják. A providerek a kiszolgáló stacket is frissítik fix verzióazonosító alatt. Egyiket sem olyan granularitással jelentik be, amelyből összeköthetnéd a saját kimeneted változásával.
Az OpenAI seed paramétere az egyetlen lehetséges módon őszinte erről: együtt érkezik egy system_fingerprint mezővel, amely a backend konfigurációját azonosítja, és a dokumentáció kimondja, hogy a determinizmus best-effort, és a megváltozott fingerprint azt jelenti, hogy az eredmények eltérhetnek. Olvasd ezt annak, ami: egy provider közli veled, hogy a fenti négy ok mindegyikét ő irányítja, te egyiket sem, és az egyetlen dolog, amit kínálni tud, hogy utólag megmondja, valami elmozdult.
Merre tovább
Link a szakaszhoz: Merre továbbItt minden egy gombról és annak következményeiről szólt. Lépjünk egy szinttel hátrébb, és megjelenik a nehezebb probléma: az objektum, amelyet hangoltunk, valószínűségi eloszlás, a valószínűségi eloszlásoknak pedig nincs interfészük.
Egy function callnak van. Egy adatbázissorhoz van. Egy három kötelező mezős JSON body-t váró POST handlernek van, és minden mást elutasít. A modell és a rendszered minden más komponense között olyan szerződés ül, amelyről az egyik oldal nem tud ígéreteket tenni: a modell valamit elő fog állítani, egy általad formált, de nem rögzített eloszlásból húzva, a másik oldalon lévő kódnak pedig ismert típusú érték kell, különben hibát dob.
A két világ közötti híd ennek a fejezetnek az anyagából épül, nem parsingból és retry-ból. Ha egy token megtörné a szükséges struktúrát, nem sample-eled és reménykedsz — értékre állítod a logit értékét, mielőtt a softmax egyáltalán látná. A constrained decoding maszk ugyanazon a vektoron, amelyet ebben a fejezetben alakítgattunk, és a „kérlek, válaszolj JSON-ban” kérést garanciává változtatja.
A 18. fejezet ez a szerződés: tool calling, JSON Schema, strukturált kimenetek, és mi kell ahhoz, hogy egy valószínűségi rendszer tetején determinisztikus rendszert lehessen biztonságosan építeni.
Források és módszer
Link a szakaszhoz: Források és módszerA fejezet minden mérése Qwen/Qwen2.5-0.5B-Instruct modellen készült CPU-n, float32-ben, hacsak nincs másképp jelezve, a sampling pedig az opcionális szakaszban leírt módon lett implementálva, nem könyvtárra bízva. Ez egy kis modell, és a konkrét értékek az övéi; a mechanizmusok nem. Von Platen How to generate text with different decoding methods című írása (Hugging Face, 2020) az a cikk, amelyhez ez az anyag méri magát, és továbbra is a legjobb rövid bevezetés ugyanebbe a témába. A determinizmus szakaszhoz: a PyTorch reprodukálhatósági jegyzetei leírják, mit rögzít és mit nem egy seed egyetlen gépen, az OpenAI seed és system_fingerprint dokumentációja leírja, mit ígérhet és mit nem egy provider, a Thinking Machines 2025-ös írása a batch-invariant kernelekről pedig a legvilágosabb nyilvános magyarázat arra, miért lehetséges, de nem ingyenes ezt inference-server szinten kijavítani.
Hivatkozások
Link a szakaszhoz: Hivatkozások-
Ackley, D. H., Hinton, G. E. and Sejnowski, T. J. A Learning Algorithm for Boltzmann Machines. Cognitive Science 9(1), pp. 147–169 (1985), ahol a softmax temperature értéke a statisztikus fizikából érkezik. Hinton, G., Vinyals, O. and Dean, J., Distilling the Knowledge in a Neural Network, arXiv:1503.02531 (2015), 2. szakasz: itt jelenik meg újra ugyanez a paraméter a modern deep learningben — egy tanár teljes eloszlásának láthatóvá tételére, ami a 13. fejezet soft labels témája, nem ennek a fejezetnek a samplingja. ↩
-
Guo, C., Pleiss, G., Sun, Y. and Weinberger, K. Q. On Calibration of Modern Neural Networks. arXiv:1706.04599 (2017). Ne keverd össze ezt a fejezet temperature értékével. A temperature scaling egy validációs halmazon illeszt egyetlen értéket, hogy a modell magabiztossága megfeleljen a pontosságának; ez egy post-hoc kalibrációs módszer, amelyet osztályozók kimenetére alkalmaznak. A temperature sampling futásidejű vezérlő arra, hogyan húz token értékeket egy generátor. Ugyanaz a képlet, más cél, közös érték nélkül. ↩
-
Holtzman, A., Buys, J., Du, L., Forbes, M. and Choi, Y. The Curious Case of Neural Text Degeneration. arXiv:1904.09751 (2019). Bevezeti a nucleus sampling módszert és azt a mérést, hogy a maximalizáláson alapuló decoding olyan szöveget állít elő, amelynek valószínűségi profilja egyáltalán nem hasonlít emberi szövegre. ↩ ↩2
-
Fan, A., Lewis, M. and Dauphin, Y. Hierarchical Neural Story Generation. arXiv:1805.04833 (2018). A top-k samplingot népszerűsítő cikk. ↩
-
Nguyen, M. et al. Turning Up the Heat: Min-p Sampling for Creative and Coherent LLM Outputs. arXiv:2407.01082 (2024). ↩
-
Meister, C., Pimentel, T., Wiher, G. and Cotterell, R. Locally Typical Sampling. arXiv:2202.00666 (2022). ↩
-
Keskar, N. S., McCann, B., Varshney, L. R., Xiong, C. and Socher, R. CTRL: A Conditional Transformer Language Model for Controllable Generation. arXiv:1909.05858 (2019). A 4.1. szakasz az eredeti repetition penalty — az, amely oszt. ↩