İçeriğe geç
17/3030 bölümden 17. bölüm

Temperature, top-p ve sahip olmadığın determinizm

Temperature, logitleri softmax öncesi böler; bu gerçek yaratıcılık düğmesi fikrini çürütür. Aynı greedy çağrı, iki yanıt.

Bu sayfada

Aynı isteği aynı modele beş kez gönderiyoruz. Aynı ağırlıklar, aynı prompt, aynı makine, aynı rastgele seed. Değişen tek şey bir sayı.

TEXT
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 ('$ספטמבר..."

Hiçbir şey bozulmadı. Son satırdaki her token, modelin 151.936 girişli sözlüğü üzerindeki kendi olasılık dağılımından tamamen meşru biçimde çekildi. Değişen sayıya temperature denir; çoğu dokümanda bir yaratıcılık düğmesi olarak anlatılır ve bu anlatım, bu bölümün iddia etmek yerine gösterebileceği şekilde yanlıştır.

Bu aynı zamanda önceki üç sözün tutulduğu bölüm. Bölüm 4 logit kavramını tanımladı ama onu pek harcamadı. Bölüm 2’nin kayan nokta kutusu bir talimatla bitmişti — Bölüm 17 aynı prompt, model ve seed neden farklı tokenler üretebilir diye sorduğunda bunu hatırla. Ve Bölüm 9’un mixture-of-experts kutusu, determinizm dışılığın dört nedeninden oluşan bir katalog sözü vermişti. Üçü de aşağıda geliyor.

Bölüm 4, logiti normalize edilmemiş gerçek değerli bir skor olarak tanıttı; sınıf başına bir tane. Bölüm 8 bir dil modelinin sözlükteki her giriş için bir tane üretmesini sağladı. softmax bu vektörü z\mathbf{z} olasılıklara çevirir:

pi=ezijezjp_i = \frac{e^{z_i}}{\sum_j e^{z_j}}

Temperature buraya girer — adı, aynı parametrenin bir Boltzmann dağılımının düşük enerjili durumlarına ne kadar keskin yoğunlaşacağını kontrol ettiği istatistiksel fizikten ödünç alınmıştır1 — ve üstel işlemden önce logitleri böler:

pi(T)=ezi/Tjezj/Tp_i(T) = \frac{e^{z_i/T}}{\sum_j e^{z_j/T}}

Bu yerleşim tüm mekanizmadır; başka bir yerde olamayacağını görmek için iki satırlık cebire değer. Temperature’ı olasılıklara uygulamaya çalıştığını varsay — onları 1/T1/T ile ölçekleyip yeniden normalize et. Elde edeceğin şey şudur:

pi/Tjpj/T=pijpj=pi\frac{p_i/T}{\sum_j p_j/T} = \frac{p_i}{\sum_j p_j} = p_i

Sabit sadeleşir. Olasılıkları ölçeklemek hiçbir şey yapmaz; dağılım değişmeden geri gelir. Temperature yalnızca üssün üzerinde etki ettiği için işe yarar: üstel almadan önce TT ile bölmek, her olasılığı 1/T1/T kuvvetine yükseltmekle aynıdır — girişler arasındaki oranları değiştiren, ortak ölçeklerini değil, doğrusal olmayan bir yeniden şekillendirme.

Bu yerleşimden iki limit de ek çalışma gerektirmeden çıkar. T0T \to 0 iken en büyük logit diğerlerinden kopup gider ve pp tek en yüksek skorlu token üzerine çöker: greedy decoding. TT büyüdükçe her zi/Tz_i/T sıfıra yaklaşır, her üstel değer 1’e yaklaşır ve dağılım tüm sözlük üzerinde uniforme doğru düzleşir. Tam olarak T=0T = 0 noktasında formül sıfıra böler; bu yüzden her uygulama bunu aritmetik maksimum için özel durum yapar — aşağıdaki widget da dahil, T0.001T \le 0.001 noktasında argmax’e geçer.

Bir uyarı, çünkü ad çakışması gerçek kafa karışıklığı yaratıyor. Makine öğrenmesinde temperature denen ikinci, ilgisiz bir şey vardır: temperature scaling, bir sınıflandırıcının güveni doğruluğuyla eşleşsin diye doğrulama kümesinde tek bir değer uyduran bir kalibrasyon yöntemi.2 Aynı formül, generation ile ilgisi yok. Makaleler “temperature” dediğinde çoğu zaman onu kasteder; bu bölüm asla onu kastetmez.

İşte o dağılım; aritmetik önünde. logitler sabit ve makul, dolayısıyla aşağıdaki metindeki sayıları gördüklerinle karşılaştırabilirsin:

  • ␣Paris96.9%
  • ␣the1.3%
  • ␣located0.8%
  • ␣a0.5%
  • ␣Lyon0.2%
  • ␣called0.1%
  • ␣home0.1%
  • ␣Marseille0.0%
  • ␣not0.0%
  • ␣banana0.0%

10 token içinden 10 tanesi kesimden sağ çıkar ve olasılığı paylaşır.

Verileri tablo olarak gör
TokenlogitSıcaklıktan sonraKesimden sonra
␣Paris⁨9.4⁩96.90%96.90%
␣the⁨5.1⁩1.31%1.31%
␣located⁨4.6⁩0.80%0.80%
␣a⁨4.1⁩0.48%0.48%
␣Lyon⁨3.2⁩0.20%0.20%
␣called⁨2.9⁩0.15%0.15%
␣home⁨2.4⁩0.09%0.09%
␣Marseille⁨1.8⁩0.05%0.05%
␣not⁨1.1⁩0.02%0.02%
␣banana⁨-2.6⁩0.00%0.00%
Örnekleme: sıcaklık, top-p ve top-k

Temperature 1’de ve kesme olmadan The capital of France is için on aday devam. ␣Paris kütlenin %96,90’ını tutar; altta, 2.6-2.6 logit değerindeki ␣banana ise %0,00 alır. Temperature’ı 0’a kaydır ve tek token %100 ile hayatta kalır. 2’ye kaydır ve ␣Paris %69,81’e düşerken ␣banana %0,17’ye çıkar — modelin reddettiği token, okurun çevirdiği bir düğmeyle gerçek olasılık kazanır.

Temperature bir yaratıcılık düğmesi değildir

Bölüme bağlantı: Temperature bir yaratıcılık düğmesi değildir

␣banana sayısı tüm argümanın minyatür halidir: temperature’ı yükseltmek modele sahip olmadığı bir fikri veremez. logitler zaten hesaplanmıştır, sıralama zaten sabittir ve temperature bunu aynen korur — hiçbir ısı miktarı daha düşük skorlu bir tokeni daha yüksek skorlu bir tokenin üstüne taşımaz. Tek yaptığı, kütleyi modelin kendi ürettiği sıralamada aşağı doğru yeniden dağıtmaktır. Yüksek temperature modeli daha yaratıcı yapmaz; modelin kötü diye puanladığı tokenleri üretme olasılığını artırır.

Gerçek bir sözlükte bu bir merak olmaktan çıkar ve yüksek temperature çıktısının neden kullanılamaz olduğuna dönüşür. Qwen/Qwen2.5-0.5B-Instruct üzerinde ölçüldü; tek forward pass, yukarıdaki prompt, olasılık kütlesinin belirli bir payını biriktirmek için kaç token gerektiği sayılarak:

temperaturetop-1 olasılığıentropy%80’i tutan tokenler%90%95%99
0.5%99,980,00 nats1111
0.7%99,650,03 nats1111
1.0%96,010,30 nats11114
1.2%88,200,88 nats1213252
1.5%62,833,07 nats293532.67226.787
2.0%16,628,19 nats13.51632.96655.231101.205

Alt satırı yavaş oku. T=2T = 2 noktasında, tam olarak tek doğru cevabı olan bir soruda, 32.966 farklı token olasılık kütlesinin en üst %90’ını paylaşır. Bu daha geniş bir yaratıcı alan değildir. Bu, aritmetik tarafından A: sonrasındaki kelime için bir Korece edatla bir C++ tanımlayıcısını canlı seçenekler gibi ele alması söylenmiş bir modeldir. Açılış bloğundaki çöp bunun doğrudan sonucudur; modelde ya da kütüphanede bir bug değildir — isteğin istediği şey budur.

Kullanışlı aralık dardır ve zevkten çok göreve bağlıdır. Olgusal bir soruda cevap tek token olur ve yaklaşık 1.2 üzerindeki her ısı boşuna hata enjekte eder. Açık uçlu bir soruda ise gerçekten birden fazla iyi devam vardır ve bir miktar ısı, akıcılığı koruyan çeşitlilik satın alır:

TEXT
"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’te model özel ad ve çözümlenemeyen bir cümle uydurdu. Bu modelde bu görev için “her seferinde aynı” ile “tutarsız” arasındaki bant kabaca 0.6 ile 1.1 arasıdır; dürüst tavsiye ise bir blog yazısından sayı kopyalamak yerine bunu kendi görevin üzerinde ölçmendir.

Bütün bunların altında saklanan açık bir soru var: modelin bir olasılık dağılımı varsa ve bir token en olasıysa, neden her zaman onu almayalım? Greedy decoding bedavadır, tekrarlanabilirdir ve parametre gerektirmez.

Çünkü sonuç şudur:

TEXT
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 %

Sekiz cümle, tek cümle. Dört tokenlik pencerelerin neredeyse onda dokuzu aynı çıktı içinde daha önce görünmüştü. Bu, top-p’yi tanıtan makalede Holtzman ve diğerleri tarafından adlandırılıp açıklanan neural text degenerationdır.3 Model bozuk değildir; sequence olasılığını maksimize etmek, açık uçlu metin için basitçe yanlış hedeftir. İnsan yazısı en olası kelime dizisi değildir — sürpriz taşır, token başına olasılığı gezinir, düşer ve toparlanır — oysa maksimum olasılık yolu, bir kez girildiğinde ayrılmak için nedeni olmayan bir sabit noktadır.

Sampling’in var olmasının nedeni budur. Aynı zamanda, genelde atlanan kısım da şu: bu evrensel bir yasa değildir. Bölüm 12, iki adımlı kelime problemlerinde düz greedy decoding ile 24’te 24 doğru ölçtü; temperature 0.8’de sampling bunu %81’e düşürdü; self-consistency sonra greedy’nin zaten bulunduğu yere geri tırmanmak için altı kat token harcadı. İki gerçek aynı anda doğrudur:

Açık uçlu generation. Tek bir doğru devam yoktur, bu yüzden en olası olan tuzaktır — döngüye girer ve %87,6’sı kendisinden kopyalanır. Sample et.

Tek doğru cevabı olan görevler. Tek bir doğru devam vardır, dolayısıyla başka herhangi bir şeyi çekmek hata çekmektir. Bölüm 12’nin %100’ü tam da bu yüzden %81 oldu. Sample etme.

Çoğu production prompt ikinci türdendir ama birincisi gibi yapılandırılır; çünkü temperature örnek kodda neyse orada bırakılmıştır.

Kesmenin iki yolu ve yalnızca biri uyum sağlar

Bölüme bağlantı: Kesmenin iki yolu ve yalnızca biri uyum sağlar

Tam dağılımdan sampling yapmak kimsenin gerçekten yaptığı şey değildir; çünkü kuyruk devasa ve saçmalıkla doludur. Bir şeylerin kesilmesi gerekir. İki klasik cevap vardır ve her şeyi belirleyen tek bir açıdan ayrılırlar.

Top-k sabit sayıda adayı tutar. Olasılığa göre sırala, ilk kk tanesini tut, kalanı at, yeniden normalize et.4 Top-p, diğer adıyla nucleus sampling, sabit miktarda kütle tutar: tokenleri azalan sırayla al, kümülatif olasılıkları pp değerine ulaşana kadar devam et ve dur.3 Biçimsel olarak nucleus, şu koşulu sağlayan en küçük VpV_p kümesidir:

iVppip\sum_{i \in V_p} p_i \ge p

Fark kozmetik gibi duyulur ama değildir; çünkü aynı dakika içinde gönderdiğin iki prompt tamamen farklı dağılım şekillerine sahiptir. Bunların ikisi de temperature 1’de aynı modeldir:

Q: What is the capital of France?\nA:Once upon a time,
top-1 olasılığı%96,01%25,39
kütlenin %90’ını tutan tokenler1467
top-k = 40 şunu tutarkütlenin %99,61’ikütlenin %78,87’si
2 ile 40 arası sıralardaki kütle%3,61%53,48
40. sıradaki token␣Av, %0,0093␣Dr, %0,128

Tek bir sabit kk, zıt yönlerde iki başarısızlık. Olgusal prompt’ta k=40k = 40, birlikte %3,6 eden 39 tokeni içeri alır — kanıtı değil yuvaları saydığı için, yüzde dokuz binde bir değerindeki bir aday dahil çöpleri geçirir. Hikâye prompt’unda aynı k=40k = 40, modelin gerçekten atadığı kütlenin %21’ini atar; çünkü oradaki gerçek nucleus 467 token genişliğindedir.

Top-p tek bir sayıyla iki işi birden yapar. p=0.9p = 0.9 ayarla; ilk prompt’ta 1 token, ikincide 467 token tutar, çünkü dağılıma bir soru sorar, ona bir adet dayatmaz. Bu uyumu doğrudan izle — aynı kesme, dört temperature:

  • ␣Paris91.1%
  • ␣the5.2%
  • ␣located3.7%
  • ␣a0.0%
  • ␣Lyon0.0%
  • ␣called0.0%
  • ␣home0.0%
  • ␣Marseille0.0%
  • ␣not0.0%
  • ␣banana0.0%

10 token içinden 3 tanesi kesimden sağ çıkar ve olasılığı paylaşır.

Verileri tablo olarak gör
TokenlogitSıcaklıktan sonraKesimden sonra
␣Paris⁨9.4⁩85.03%91.10%
␣the⁨5.1⁩4.84%5.18%
␣located⁨4.6⁩3.47%3.71%
␣a⁨4.1⁩2.48%
␣Lyon⁨3.2⁩1.36%
␣called⁨2.9⁩1.12%
␣home⁨2.4⁩0.80%
␣Marseille⁨1.8⁩0.54%
␣not⁨1.1⁩0.34%
␣banana⁨-2.6⁩0.03%
Örnekleme: sıcaklık, top-p ve top-k

Temperature 1.5 iken top-p 0.90: on tokenin üçü hayatta kalır ve kütleyi paylaşır, ␣Paris %91,10’a yeniden normalize edilir. Şimdi yalnızca temperature’ı değiştir. 0.7’de aynı 0.90 bir hayatta kalan bırakır — bu kadar dar bir nucleus, farklı ad takmış greedy decoding’dir. 2.0’da beş bırakır. Kesme hiç hareket etmedi; altındaki şekil hareket etti.

Bu widget ayrıca adını koymaya değer bir yanlış kanıyı da kapatır, çünkü insanlara gerçek para kaybettirir. Güvenli bir dağılımda top_p = 0.9 “biraz çeşitlilik” değildir. Greedy’dir. Temperature 1’de buradaki önde gelen token %96,90 tutar; bu zaten 0.9’un üzerindedir, dolayısıyla nucleus bir token genişliğindedir ve başka hiçbir şey asla çekilemez. Ekipler top_p değerini 0.9’a ayarlayıp bir şeyi gevşettiklerine inanır, sonra her cevabın neden aynı olduğuna şaşar.

Bunun yerine top-k ayarla; zıt başarısızlık da aynı kadar görünürdür:

  • ␣Paris97.2%
  • ␣the1.3%
  • ␣located0.8%
  • ␣a0.5%
  • ␣Lyon0.2%
  • ␣called0.0%
  • ␣home0.0%
  • ␣Marseille0.0%
  • ␣not0.0%
  • ␣banana0.0%

10 token içinden 5 tanesi kesimden sağ çıkar ve olasılığı paylaşır.

Verileri tablo olarak gör
TokenlogitSıcaklıktan sonraKesimden sonra
␣Paris⁨9.4⁩96.90%97.20%
␣the⁨5.1⁩1.31%1.32%
␣located⁨4.6⁩0.80%0.80%
␣a⁨4.1⁩0.48%0.49%
␣Lyon⁨3.2⁩0.20%0.20%
␣called⁨2.9⁩0.15%
␣home⁨2.4⁩0.09%
␣Marseille⁨1.8⁩0.05%
␣not⁨1.1⁩0.02%
␣banana⁨-2.6⁩0.00%
Örnekleme: sıcaklık, top-p ve top-k

Top-k 5, top-p yok. Her temperature’da beş token hayatta kalır, çünkü istenen şey beştir. Temperature 1’de, gösterildiği gibi, ␣Paris altındaki dört aday birlikte %2,79 eder. 0.7’ye düşür ve aynı dördü %0,38 eder — kesme tiyatrodur ve model fiilen greedy’dir. 2.0’a yükselt ve %22,54 ederler. Aynı ayar, aynı hayatta kalan sayısı, üç tamamen farklı davranış; istekte hangisini aldığını söyleyen hiçbir şey yoktur.

Penalty’ler, formülleriyle birlikte; çünkü karıştırılmaları salgın

Bölüme bağlantı: Penalty’ler, formülleriyle birlikte; çünkü karıştırılmaları salgın

Benzer adlarla dolaşan üç farklı mekanizma vardır; farklı şeyler yaparlar ve fark ölçülebilir. cic_i, token ii’nin daha önce kaç kez göründüğü olsun.

ziziα1[ci>0]z_i \leftarrow z_i - \alpha \cdot \mathbb{1}[c_i > 0]

Herhangi bir kez bile görünmüş token’den sabit bir değer çıkar. Bir kez görünmekle kırk kez görünmek aynı şekilde cezalandırılır. Bu bir anahtardır, düğme değil.

ziziβciz_i \leftarrow z_i - \beta \, c_i

Sayımla orantılı çıkar. Dört kez kullanılan bir token, bir kez kullanılan tokenden dört kat sert cezalandırılır ve metin büyüdükçe baskı katlanır.

zi{zi/ρif zi>0ziρif zi0z_i \leftarrow \begin{cases} z_i / \rho & \text{if } z_i > 0 \\ z_i \cdot \rho & \text{if } z_i \le 0 \end{cases}

CTRL makalesindeki özgün yöntem.7 Çıkarmak yerine böler; işaret durumu gerekir, çünkü negatif bir logiti bölmek onu büyütür. Bu yüzden gücü logitin büyüklüğüne bağlıdır; bu da aynı ρ\rho değerinin aynı cümlenin farklı noktalarında farklı vurması demektir.

Daha önceki aynı bozulmuş devam; her biri uygulanmış halde. “Değişen adımlar”, 120 generation adımının kaçında cezasız modelin seçeceğinden farklı bir token seçildiğini sayar. Buradaki koşu yukarıdaki bloktaki 140 yerine 120 adımdır; cezasız baseline’ın %87,6 yerine %85,5 okumasının nedeni budur:

ayartekrarlanan 4-gramlardeğişen adımlar
hiçbir şey%85,50 / 120
presence 0.5%65,03 / 120
presence 1.0%3,411 / 120
frequency 0.5%6,012 / 120
frequency 1.0%0,020 / 120
repetition 1.2 (CTRL)%0,035 / 120

Üç sonuç çıkıyor. Presence 0.5, 120 karardan üçünü değiştirdi ve tekrarı dörtte bir azalttı — döngüyü bir avuç token bir arada tutuyordu. Frequency 0.5 dört kat fazla karar değiştirdi ve çok daha büyük etki yaptı; çünkü sayı çarpanı büyümeye devam ederken presence sabiti büyümez. Ve yaygınca kopyalanan 1.2 değerindeki CTRL penalty, 120 kararın 35’ini yeniden yazdı; bu bir dürtme değil, farklı bir modeldir.

Bu son sayı, kimsenin uyarmadığı başarısızlığın kurulumudur.

Penalty’ler tekrarlaması gereken metne ne yapar

Bölüme bağlantı: Penalty’ler tekrarlaması gereken metne ne yapar

Kod tekrar eder. Tablolar tekrar eder. Listeler tekrar eder. Yapılandırılmış çıktı tanımı gereği tekrar eder — yapı zaten budur. Bir penalty, döngüye sıkışmış model ile tablonun dördüncü satırını doğru şekilde üreten model arasındaki farkı anlayamaz; çünkü ikisi de bir tokenin yeniden görünmesi gibi görünür.

Aynı üç görev, üç şekilde üretildi:

görevhiçbir şeyfrequency 0.5repetition 1.2
markdown tablo, 6 satır0 / 56 değişen adım0 / 562 / 62
Python fonksiyonu0 / 930 / 9310 / 110
madde listesi, 1’den 12’ye0 / 500 / 500 / 50

Frequency penalty 0.5 üçünde de zararsız çıktı; bu yararlı ve biraz şaşırtıcı bir sonuç, ayrıca kesin bir şey söylüyor: karar değişmediğine göre yapısal tokenler, beş ve altı kez göründükten sonra bile, penalty’nin çıkardığından daha fazla farkla pozisyonlarını kazanmış olmalı. Buna karşılık bölen CTRL penalty onları yerinden oynatır; ürettiği şey şu:

TEXT
repetition 1.2, markdown table:
  | n | 2^n |
  | --- | --- |
  | 0 | 1      |
  | 1 | 2       |
  | 2 | 4       |

Hizalama dağılıyor: her hücre içindeki padding miktarı satırdan satıra değişiyor, çünkü kapanış pipe’ından önceki boşluk dizisi tam da penalty’nin kırmak için var olduğu tekrar türüdür. Kozmetik ve altı ekstra tokena mal oldu. Python vakası kozmetik değil:

TEXT
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,

Penalty modeli total üzerinden — docstring’de zaten kullanılmıştı — total_sum üzerine itti, çıktıyı kullanılmamış tokenlere bütçe harcamak için uydurma yorumlarla şişirdi ve sonra stride’lı üç argümanlı bir range içine yürüdü. Yorum her seferinde 2 artırarak diyor; bu, 1’den nn’ye kareler toplamı için yanlıştır. Bir repetition penalty, onsuz doğru yanıtlanan bir prompt’tan yanlış kod üretti.

Buradan çıkan kural kısa: penalty’ler açık uçlu düzyazı içindir; kod, yapılandırılmış çıktı, tablo verisi ve schema içeren her şey için kapalı olmalıdır. Bölüm 18 tam olarak bu ikinci kategoriyle ilgilidir.

Uygulama sırası ve cevabı neden değiştirir

Bölüme bağlantı: Uygulama sırası ve cevabı neden değiştirir

Her gerçek uygulama bunları belirli bir sırayla uygular:

penalty’ler → temperature → top-k → top-p → sample

Bu keyfi muhasebe değildir ve iki aşamanın yerini değiştirmek gerçekten farklı dağılımlar üretir. İki ölçüm, ikisi de olgusal prompt üzerinde.

Temperature’dan önce ya da sonra kesmek. Nucleus, kendisine verilen dağılım üzerinde hesaplanır ve temperature o dağılımı kökten değiştirir:

temperature sonrası top-p 0.9temperature öncesi top-p 0.9
T=1.0T = 1.01 token1 token
T=1.5T = 1.5353 token1 token
T=2.0T = 2.032.966 token1 token

T=2T = 2 noktasında aynı nominal ayar, yalnızca hangi aşamanın önce çalıştığına bağlı olarak 32.966 ya da 1 adaylık bir küme verir. Temperature’ı yükseltmenin bir sağlayıcıda neden “hiçbir şey yapmadığını”, aynı iki sayıyla başka bir sağlayıcıda çıktıyı neden mahvettiğini merak ettiysen, bu tablo makul bir cevaptır.

Temperature’dan önce ya da sonra cezalandırmak. Bir penalty α\alpha çıkarıp sonra TT ile bölmek, α/T\alpha/T etkili penalty verir; önce bölüp sonra çıkarmak α\alpha verir. Önde gelen tokena uygulanan 1.0 presence penalty ile:

temperatureönce cezalandır, sonra temperleönce temperle, sonra cezalandır
0.5%99,858%99,948
1.0%89,839%89,839
2.0%10,783%6,830

T=1T = 1 noktasında zorunlu olarak aynılar. T=2T = 2 noktasında aralarında 1,58 kat fark var. “Presence penalty 1.0”, temperature’ın nerede uygulandığını da bilmediğin sürece iyi tanımlı bir penalty miktarı değildir ve hiçbir API bunu belgelemiyor.

Ayrıntıları göster

İsteğe bağlı: yukarıdaki sırayla tüm pipeline.

On altı satır; bu bölümdeki her şey onların içinde. Widget’ın yaptığı aynı hesaplama, on sabit sayı yerine gerçek bir logit vektörü üzerinde.

sample.pyPYTHON
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)])

Top-p satırındaki cumsum(0) - p, geçerli token hariç kümülatif kütledir; nucleus’un eşiği geçen tokeni dahil etmesini, hemen öncesinde durmamasını sağlayan şey budur. Bunu bir kaydırırsan top_p = 0.9 sessizce diğer her uygulamadan biraz daha sıkı bir kesmeye dönüşür.

Bu, kursun ikinci yarısında Python’ın doğru dil olduğu az sayıda yerden biridir; nedeni stil değil yapıdır: yukarıdaki her satır, logitlerin tüm vektörünün elinde olmasını gerektirir ve bir HTTP API üzerinden o vektör yoktur. Bir sağlayıcıya temperature ve top_p gönderebilirsin; onları uygulayamazsın ve ne yaptıklarını göremezsin.

Her sağlayıcı bu kontrollerin farklı bir alt kümesini, farklı aralıklarla alır ve geri kalanını sessizce yok sayar. Bu soyut bir şikâyet değil. Model seçimi sunan her uygulama farkları bir yere yazmak zorundadır; bunu yaptığı dosya uyumsuzluğun haritasıdır. Böyle bir katalog, desteklediği dokuz metin kaynağı boyunca tek bir parametre için şunu ilan ediyor:

ilan edilen temperature aralığıkaynaklar
0 ile 1Anthropic, Google, Meta, Cerebras, PaLM
0 ile 1.5Mistral
0 ile 2OpenAI, DeepSeek, xAI

Kelime aynı; ölçek değil. “Temperature 1”, birinde değiştirilmemiş dağılım, diğerinde izin verilen maksimum ısıdır; kataloğun yarısı, diğer yarısının nötr-artı-biraz saydığı değeri ifade edemez. Diğer düğmeler de aynı derecede düzensizdir: OpenAI, DeepSeek ve xAI girdileri presence ve frequency penalty alır, topK almaz; Google, Meta, Cerebras ve PaLM girdileri topK alır, penalty almaz; Anthropic topK, topP ve stop sequences alır, penalty almaz; ve dokuz taneden tam olarak biri — Mistral — seed alır. Bir sağlayıcının uygulamadığı parametreyi göndermek genellikle hiç hata üretmez: istek başarılı olur, düğme hiçbir şey yapmaz ve sen ayarın etkisi olmadığı sonucuna varırsın.

Ve böyle bir dosyanın ne olduğuna dikkat et: başka birinin API’si hakkında, belirli bir günde yazılmış ve sonrasında hiçbir şeyin doğrulamadığı bir iddia. Artık 0 ile 2 kabul eden bir sağlayıcı için 0 ile 1 diyen bir katalog, her isteği sessizce kırpar.

Aynı aileye iki kontrol daha girer. logprobs, sunulduğu yerde, seçilen tokenin log-olasılıklarını ve çoğu zaman en üst birkaç alternatifi döndürür — bu bölümün anlattığı dağılıma açılan tek pencere ve kapalı bir model üzerinde kurulan her güven sezgisinin temeli. Ve maximum tokens ile stop sequences, olasılığa hiç bakmadan generation’ı bitirir: sert bir sınır ve string eşleşmesi. İkisi de Bölüm 14’teki finish_reason olarak görünür; orada length cevabının model tarafından bitirilmediğini, bütçe yüzünden cümlenin ortasında kesildiğini gösterir.

Bir seed ayarla, sampling tekrarlanabilir olur. Bu kısım gerçektir ve doğrulaması kolaydır:

TEXT
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\"."

Aynı seed içinde byte düzeyinde aynı, seedler arasında farklı; tam da söylendiği gibi. Yani seed’in sabitlediği şey, o sample fonksiyonunun son satırındaki rastgele çekiliştir — bir dağılım verildiğinde hangi tokenin seçileceği.

Sabitlemediği şey dağılımdır. Sorun da oradadır; çünkü modelinin ürettiği logit vektörü matematiksel bir nesne değildir: milyarlarca kayan nokta toplamasının çıktısıdır ve bu toplamaların bir sırası vardır.

Bölüm 2 bu deneyi hazır bırakmıştı. Aynı bir milyon float32 sayı, farklı gruplamalarla toplanıyor:

TEXT
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?    False

Son satıra bak. Chunk sayısı cevabı değiştiriyor. Bu numpy hakkında bir merak konusu değildir; mekanizmanın kendisidir. Çünkü bir inference sunucusu bir reduction’ı daha fazla ya da daha az paralel birime böldüğünde tam olarak bunu yapar. Ve bir sunucu nasıl böleceğine, kaç isteğe hizmet ettiğine göre karar verir.

İşte modelin kendisinde bu etki. Aynı prompt, aynı forward pass; tek fark batch’te o sırada kaç başka isteğin bulunduğu:

TEXT
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-05

Tek başına çalıştırıldığında model kusursuz deterministiktir — yirmi geçiş, bit düzeyinde aynı. Aynı prompt’u ilgisiz isteklerle bir batch’e koy ve logitlerinin %97’si değişir. Senin isteğinde hiçbir şey değişmedi. Başkasının isteği geldi.

Şimdi dürüst kısım; çünkü bu genellikle hikâyenin sonuymuş gibi anlatılır. 2.5×1052.5 \times 10^{-5} büyüklüğünde bir değişim, yalnızca iki aday token birbirine bu kadar yakınsa çıktıyı değiştirir. On iki prompt boyunca 717 generation adımında, en üst iki logit arasındaki en küçük fark 2.5×1032.5 \times 10^{-3} idi — perturbation’dan yüz kat büyük — ve hiçbir adım flip edecek kadar yakın değildi. Yani bu modelde, float32’de, bir laptop’ta batching her logiti oynattı ama hiçbir tokeni değiştirmedi.

Bu, elverişli koşulların açıklamasıdır; güvence değildir. Bu koşullarda tek bir değişiklik yeterlidir:

TEXT
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."

Sekiz cevabın altısı ayrışıyor ve biri ciddi biçimde bozuluyor. Bölüm 2’nin tablosu nedenini söylüyor: bfloat16, 7 mantissa bit tutar; bu yüzden logit büyüklüğü 16 civarındayken temsil edilebilir değerler 0.125 aralıklıdır — 16.0, sonra 16.125, sonra 16.25 — ve yuvarlama bir logiti 0.0625’e kadar oynatabilir. Bu arada yukarıda ölçülen generation adımlarının %4,7’sinde top-two farkı 0.1’in altındaydı. İki deney arasındaki tüm fark bu: float32’de perturbation en yakın karardan yüz kat küçüktü; bfloat16’da aynı boyuttadır. Production inference 16-bit’te, fused kernel’lara sahip donanımda ve kimsenin sabit tutma sözü vermediği reduction sıralarıyla çalışır. “Sayısal gürültü ihmal edilebilir mi?” sorusu model hakkında değil, precision ve donanım hakkındadır.

O halde Bölüm 9’un söz verdiği gibi dört neden kataloğu:

Kayan nokta toplaması associativity taşımaz

Bölüme bağlantı: Kayan nokta toplaması associativity taşımaz

Bölüm 2’nin kutusu. Bir toplamın sırası değerini değiştirir; dolayısıyla bir reduction’ın nasıl bölündüğündeki her değişiklik logitleri değiştirir. Alt tabaka budur; diğer üçü sırayı değiştirmenin yollarıdır.

Dynamic batching isteğini yabancılarınkiyle gruplar

Bölüme bağlantı: Dynamic batching isteğini yabancılarınkiyle gruplar

Bölüm 13’ten continuous batching, inference’ın ekonomik olmasının nedenidir — ve tokenlerinin içinden aktığı matrislerin şeklinin trafiğe bağlı olduğu anlamına gelir. Yukarıda ölçüldü: batch boyutu değiştiği için 147.321 logit oynadı.

Mixture-of-experts routing batch’e bağlıdır

Bölüme bağlantı: Mixture-of-experts routing batch’e bağlıdır

Bölüm 9’un kutusu zaten söylemişti. Router, batch üzerinden hesaplanan uzman başına kapasite sınırlarına tabi olarak, token başına katman başına ayrık bir seçim yapar. Tek başına expert 7’ye gidecek bir token, yanında başkaları varken expert 12’ye gider. Bu bir yuvarlama farkı değildir; farklı bir ağırlık kümesidir.

-latest gibi bir version string bir pointer’dır ve pointer’lar yeniden işaretlenir. Sağlayıcılar ayrıca sabit bir version identifier altında serving stack’i günceller. İkisi de kendi çıktındaki değişimle ilişkilendirmene yetecek ayrıntı düzeyinde duyurulmaz.

OpenAI’ın seed parametresi bu konuda olabileceği tek şekilde dürüsttür: backend yapılandırmasını tanımlayan bir system_fingerprint alanıyla birlikte gelir ve dokümantasyon determinizmin best-effort olduğunu, fingerprint değişirse sonuçların farklılaşabileceğini söyler. Bunu olduğu gibi oku — bir sağlayıcı sana yukarıdaki dört nedenin hepsini kendisinin kontrol ettiğini, senin hiçbirini kontrol etmediğini ve sunabileceği tek şeyin olaydan sonra bir şeyin hareket ettiğini söylemek olduğunu anlatıyor.

Buradaki her şey bir düğme ve sonuçları hakkındaydı. Bir seviye geri çekilince daha zor problem görünür: ayarladığımız nesne bir olasılık dağılımıdır ve olasılık dağılımlarının arayüzü yoktur.

Bir function call’un vardır. Bir veritabanı satırının vardır. Üç zorunlu alanlı bir JSON body bekleyen POST handler’ın vardır ve başka her şeyi reddeder. Model ile sistemindeki diğer her bileşen arasında, bir tarafın hakkında söz veremediği bir sözleşme oturur: model, şekillendirdiğin ama sabitlemediğin bir dağılımdan çekilmiş bir şey üretecektir; diğer taraftaki kod ise bilinen tipte bir değer ister, yoksa hata fırlatır.

Bu iki dünya arasındaki köprü, parsing ve retry’lardan değil bu bölümün malzemesinden kurulur. Bir token gerekli yapıyı bozacaksa onu sample edip umut etmezsin — softmax onu görmeden önce logitini -\infty yaparsın. Constrained decoding, bu bölüm boyunca yeniden şekillendirdiğimiz aynı vektörün üzerine bir maskedir ve “lütfen JSON yanıtla” ifadesini bir istek olmaktan çıkarıp garantiye dönüştürür.

Bölüm 18 bu sözleşmedir: tool calling, JSON Schema, structured outputs ve probabilistic bir modelin üzerine güvenle deterministic bir sistem kurmak için gerekenler.


Bu bölümdeki tüm ölçümler Qwen/Qwen2.5-0.5B-Instruct üzerinden CPU’da, aksi belirtilmedikçe float32 ile ve sampling bir kütüphaneye devredilmek yerine isteğe bağlı bölümde yazıldığı gibi uygulanarak yapılmıştır. Küçük bir modeldir ve belirli değerler ona aittir; mekanizmalar değildir. Von Platen’ın How to generate text with different decoding methods yazısı (Hugging Face, 2020), bunun karşısında ölçüldüğü makaledir ve aynı konuya hâlâ en iyi kısa girişlerden biridir. Determinizm bölümü için: PyTorch’un reproducibility notları bir seed’in tek makinede neyi sabitleyip neyi sabitlemediğini açıklar; OpenAI’ın seed ve system_fingerprint dokümantasyonu bir sağlayıcının neyi vaat edip neyi edemeyeceğini açıklar; Thinking Machines’in 2025 batch-invariant kernel tartışması ise bunu inference-server düzeyinde düzeltmenin mümkün ama bedava olmadığına dair en açık kamuya açık anlatımdır.

  1. Ackley, D. H., Hinton, G. E. ve Sejnowski, T. J. A Learning Algorithm for Boltzmann Machines. Cognitive Science 9(1), s. 147–169 (1985); burada softmax içindeki temperature istatistiksel fizikten gelir. Hinton, G., Vinyals, O. ve Dean, J., Distilling the Knowledge in a Neural Network, arXiv:1503.02531 (2015), bölüm 2, aynı parametrenin modern deep learning’de yeniden ortaya çıktığı yerdir — bir öğretmenin tam dağılımını açığa çıkarmanın yolu olarak; bu da bu bölümün sampling’i değil Bölüm 13’ün soft labels konusudur.

  2. Guo, C., Pleiss, G., Sun, Y. ve Weinberger, K. Q. On Calibration of Modern Neural Networks. arXiv:1706.04599 (2017). Bunu bu bölümdeki temperature ile karıştırma. Temperature scaling, modelin güveni doğruluğuyla eşleşsin diye doğrulama kümesinde tek bir değer uydurur; bir sınıflandırıcının çıktılarına uygulanan post-hoc kalibrasyon yöntemidir. Temperature sampling, bir generator’ın tokenleri nasıl çekeceği üzerinde runtime kontrolüdür. Aynı formül, farklı amaç ve ortak değer yok.

  3. Holtzman, A., Buys, J., Du, L., Forbes, M. ve Choi, Y. The Curious Case of Neural Text Degeneration. arXiv:1904.09751 (2019). Nucleus sampling’i ve maximisation tabanlı decoding’in olasılık profili insan metnine hiç benzemeyen metin ürettiği ölçümünü tanıtır. 2

  4. Fan, A., Lewis, M. ve Dauphin, Y. Hierarchical Neural Story Generation. arXiv:1805.04833 (2018). top-k sampling’i yaygınlaştıran makale.

  5. Nguyen, M. ve diğerleri. Turning Up the Heat: Min-p Sampling for Creative and Coherent LLM Outputs. arXiv:2407.01082 (2024).

  6. Meister, C., Pimentel, T., Wiher, G. ve Cotterell, R. Locally Typical Sampling. arXiv:2202.00666 (2022).

  7. Keskar, N. S., McCann, B., Varshney, L. R., Xiong, C. ve Socher, R. CTRL: A Conditional Transformer Language Model for Controllable Generation. arXiv:1909.05858 (2019). Bölüm 4.1 özgün repetition penalty’dir — bölen yöntem.

Seçimi LIA'ya bırakmaya hazır mısın?

Tüm yapay zeka modelleriyle tek yerde üret — bugün ücretsiz başla.