ข้ามไปยังเนื้อหา
17/30บทที่ 17 จาก 30

Temperature, Top-p และ Determinism ที่คุณไม่มี

Temperature หาร logits ก่อน softmax ข้อเท็จจริงเดียวนี้ทำลายแนวคิดปุ่มปรับความสร้างสรรค์ พร้อมตัวอย่างคำตอบต่างกันจากคำสั่งเดิม

ในหน้านี้

นี่คือคำขอเดียวกันที่ส่งไปยังโมเดลเดียวกันห้าครั้ง weights เดิม, prompt เดิม, เครื่องเดิม, random seed เดิม สิ่งเดียวที่เปลี่ยนคือเลขหนึ่งตัว

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

ไม่มีอะไรพัง token ทุกตัวในบรรทัดสุดท้ายถูกสุ่มมาอย่างถูกต้องจากการแจกแจงความน่าจะเป็นของโมเดลเองเหนือ vocabulary 151,936 รายการ เลขที่เปลี่ยนเรียกว่า temperature เอกสารส่วนใหญ่อธิบายว่ามันเป็นปุ่มปรับความสร้างสรรค์ และคำอธิบายนั้นผิดในแบบที่บทนี้จะแสดงให้เห็น ไม่ใช่แค่กล่าวอ้าง

นี่ก็เป็นบทที่คำสัญญาสามข้อก่อนหน้านี้ถึงเวลาต้องชำระ บทที่ 4 นิยาม logit แล้วแทบไม่ได้ใช้มันจริง ๆ กล่องเรื่อง floating-point ของ บทที่ 2 จบด้วยคำสั่งว่า — จำเรื่องนี้ไว้เมื่อบทที่ 17 ถามว่าทำไม prompt, model และ seed เดียวกันจึงให้ tokens ต่างกันได้ และกล่อง mixture-of-experts ของ บทที่ 9 สัญญาว่าจะรวบรวมสาเหตุของ non-determinism สี่ข้อ ทั้งสามมาถึงด้านล่างนี้

บทที่ 4 แนะนำ logit ว่าเป็นคะแนนค่าจริงที่ยังไม่ถูก normalize หนึ่งค่าต่อ class บทที่ 8 ทำให้ language model สร้างหนึ่งค่าต่อรายการใน vocabulary softmax แปลงเวกเตอร์นั้น z\mathbf{z} ให้เป็นความน่าจะเป็น:

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

Temperature เข้ามาตรงนี้ — ชื่อนี้ยืมมาจากสถิติฟิสิกส์ ซึ่งพารามิเตอร์เดียวกันควบคุมว่า Boltzmann distribution จะกระจุกตัวบนสถานะพลังงานต่ำอย่างคมแค่ไหน1 — และ มันหาร logits ก่อน exponential:

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

ตำแหน่งนี้คือกลไกทั้งหมด และควรดูพีชคณิตสองบรรทัดเพื่อเห็นว่ามันอยู่ที่อื่นไม่ได้ สมมติว่าคุณพยายามใช้ temperature กับความน่าจะเป็นแทน — scale มันด้วย 1/T1/T แล้ว renormalise คุณจะได้

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

ค่าคงที่ตัดกันหมด การ scale ความน่าจะเป็นไม่ทำอะไรเลย; การแจกแจงกลับมาเหมือนเดิม Temperature มีผลก็ต่อเมื่อมันกระทำกับ exponent เพราะการหารด้วย TT ก่อน exponentiating เท่ากับยกความน่าจะเป็นแต่ละตัวกำลัง 1/T1/T — การปรับรูปแบบไม่เชิงเส้นที่เปลี่ยน อัตราส่วน ระหว่างรายการ แทนที่จะเปลี่ยน scale ร่วมของมัน

จากตำแหน่งนั้น ขีดจำกัดทั้งสองตามมาโดยไม่ต้องทำอะไรเพิ่ม เมื่อ T0T \to 0 logit ที่ใหญ่ที่สุดจะหนีห่างตัวที่เหลือ และ pp จะยุบลงบน token ที่ได้คะแนนสูงสุดเพียงตัวเดียว: greedy decoding เมื่อ TT โตขึ้น zi/Tz_i/T ทุกตัวจะมุ่งสู่ศูนย์ exponential ทุกตัวมุ่งสู่ 1 และการแจกแจงจะแบนลงจนเข้าใกล้ uniform เหนือ vocabulary ทั้งหมด ที่ T=0T = 0 พอดี สูตรจะหารด้วยศูนย์ ดังนั้น implementation ทุกตัวจึง special-case ให้เป็นค่าสูงสุดทางเลขคณิต — รวมถึง widget ด้านล่าง ซึ่งสลับไปใช้ argmax ที่ T0.001T \le 0.001

ขอเตือนหนึ่งอย่าง เพราะชื่อซ้ำกันทำให้สับสนจริง ๆ ใน machine learning ยังมีอีกสิ่งหนึ่งที่ไม่เกี่ยวกันแต่ชื่อ temperature เช่นกัน: temperature scaling วิธี calibration ที่ fit ค่าเดียวบน validation set เพื่อให้ confidence ของ classifier ตรงกับ accuracy ของมัน2 สูตรเดียวกัน แต่ไม่เกี่ยวกับ generation บทความที่พูดว่า “temperature” มักหมายถึงอันนั้น; บทนี้ไม่เคยหมายถึงมัน

นี่คือการแจกแจงนั้น พร้อมเลขคณิตให้เห็นตรงหน้า logits ถูกตรึงไว้และสมเหตุสมผล ดังนั้นตัวเลขในคำอธิบายด้านล่างตรวจเทียบกับสิ่งที่คุณเห็นได้:

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

10 จาก 10 token ผ่านการตัดและแบ่งความน่าจะเป็นกัน

ดูข้อมูลในรูปแบบตาราง
Tokenlogitหลังปรับอุณหภูมิหลังการตัด
␣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%
การสุ่มตัวอย่าง: อุณหภูมิ, top-p และ top-k

candidate continuations สิบรายการของ The capital of France is ที่ temperature 1 และไม่มีการตัด ␣Paris ถือ mass 96.90 %; ␣banana ที่อยู่ล่างสุดด้วย logit 2.6-2.6 ได้ 0.00 % เลื่อน temperature ไปที่ 0 แล้วเหลือ token เดียวที่รอดด้วย 100 % เลื่อนไปที่ 2 แล้ว ␣Paris ลดลงเหลือ 69.81 % ขณะที่ ␣banana ไต่ขึ้นเป็น 0.17 % — token ที่โมเดลปฏิเสธ ถูกมอบความน่าจะเป็นจริงโดยปุ่มที่ผู้อ่านหมุนเอง

Temperature ไม่ใช่ปุ่มปรับความสร้างสรรค์

ลิงก์ไปยังส่วน: Temperature ไม่ใช่ปุ่มปรับความสร้างสรรค์

ตัวเลข ␣banana คือข้อโต้แย้งทั้งหมดในรูปย่อ: การเพิ่ม temperature ไม่สามารถให้ไอเดียที่โมเดลไม่มีอยู่แล้วแก่โมเดลได้ logits ถูกคำนวณแล้ว ranking ถูกกำหนดแล้ว และ temperature รักษา ranking นั้นไว้อย่างสมบูรณ์ — ความร้อนแค่ไหนก็ไม่เคยย้าย token ที่ได้คะแนนต่ำกว่าให้อยู่เหนือ token ที่ได้คะแนนสูงกว่าได้ สิ่งที่มันทำทั้งหมดคือกระจาย mass ลงไปตาม ranking ที่โมเดลสร้างเอง Temperature สูงไม่ได้ทำให้โมเดลคิดสร้างสรรค์กว่าเดิม; มันทำให้มีโอกาส emit tokens ที่มันให้คะแนนว่าแย่ มากขึ้น

บน vocabulary จริง เรื่องนี้หยุดเป็นความแปลกเล็ก ๆ และกลายเป็นเหตุผลที่ output จาก high-temperature ใช้งานไม่ได้ วัดบน Qwen/Qwen2.5-0.5B-Instruct, forward pass หนึ่งครั้ง, prompt ด้านบน, นับว่าต้องใช้กี่ tokens เพื่อสะสมสัดส่วนหนึ่งของ probability mass:

temperaturetop-1 probabilityentropytokens holding 80 %90 %95 %99 %
0.599.98 %0.00 nats1111
0.799.65 %0.03 nats1111
1.096.01 %0.30 nats11114
1.288.20 %0.88 nats1213252
1.562.83 %3.07 nats293532,67226,787
2.016.62 %8.19 nats13,51632,96655,231101,205

อ่านแถวล่างช้า ๆ ที่ T=2T = 2 บนคำถามที่มีคำตอบถูกต้องเพียงหนึ่งเดียว tokens ต่างกัน 32,966 ตัวแบ่งกันถือ top 90 % ของ probability mass นั่นไม่ใช่พื้นที่สร้างสรรค์ที่กว้างขึ้น แต่มันคือโมเดลที่ถูกเลขคณิตสั่งให้ปฏิบัติต่ออนุภาคภาษาเกาหลีกับ identifier ภาษา C++ เหมือนเป็นตัวเลือกที่ยังมีชีวิตสำหรับคำหลัง A: ขยะในบล็อกเปิดคือผลโดยตรง และมันไม่ใช่ bug ในโมเดลหรือ library — มันคือสิ่งที่คำขอนั้นขอไว้

ช่วงที่มีประโยชน์แคบและขึ้นกับงาน ไม่ใช่รสนิยม สำหรับคำถามเชิงข้อเท็จจริง คำตอบคือ token เดียว และความร้อนเหนือประมาณ 1.2 ใส่ error เข้ามาโดยไม่ได้ประโยชน์อะไร สำหรับงานปลายเปิด มี continuation ดี ๆ มากกว่าหนึ่งจริง และความร้อนบางส่วนซื้อ variety ที่ยังลื่นไหลได้:

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 โมเดลสร้างชื่อเฉพาะและประโยคที่ parse ไม่ได้ขึ้นมา ช่วงระหว่าง “เหมือนเดิมทุกครั้ง” กับ “ไม่รู้เรื่อง” อยู่ประมาณ 0.6 ถึง 1.1 สำหรับโมเดลนี้ในงานนี้ และคำแนะนำที่ซื่อตรงคือคุณต้องหาโดยวัดบนงาน ของคุณ ไม่ใช่คัดลอกเลขจากบล็อกโพสต์

ทำไมข้อความที่น่าจะเป็นที่สุดจึงเป็นข้อความที่แย่

ลิงก์ไปยังส่วน: ทำไมข้อความที่น่าจะเป็นที่สุดจึงเป็นข้อความที่แย่

มีคำถามชัดเจนซ่อนอยู่ใต้ทั้งหมดนี้: ถ้าโมเดลมีการแจกแจงความน่าจะเป็นและ token หนึ่งน่าจะเป็นที่สุด ทำไมไม่เลือกมันเสมอ? Greedy decoding ฟรี ทำซ้ำได้ และไม่ต้องใช้พารามิเตอร์

เพราะผลลัพธ์เป็นแบบนี้:

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 %

แปดประโยค หนึ่งประโยค เกือบเก้าในสิบของหน้าต่างสี่-token เคยปรากฏก่อนหน้าใน output เดียวกันแล้ว นี่คือ neural text degeneration ซึ่ง Holtzman et al. ตั้งชื่อและอธิบายไว้ใน paper ที่แนะนำ top-p3 โมเดลไม่ได้พัง; การ maximize sequence probability เป็น objective ที่ผิดสำหรับข้อความปลายเปิด Human writing ไม่ใช่ลำดับคำที่น่าจะเป็นที่สุด — มันมี surprise, per-token probability ของมันลอยขึ้นลง ดิ่งแล้วฟื้น — ขณะที่เส้นทางความน่าจะเป็นสูงสุดคือ fixed point ที่เมื่อเข้าไปแล้วไม่มีเหตุผลให้หลุดออกมา

นั่นคือเหตุผลที่ sampling มีอยู่ตั้งแต่แรก และส่วนที่มักถูกละไว้คือ มันไม่ใช่กฎสากล บทที่ 12 วัดได้ 24 จาก 24 ข้อถูกในโจทย์คำสองขั้นด้วย plain greedy decoding และ sampling ที่ temperature 0.8 ทำให้ลดเหลือ 81 %; self-consistency จากนั้นใช้ tokens มากขึ้นหกเท่าเพื่อปีนกลับไปยังจุดที่ greedy อยู่แล้ว ข้อเท็จจริงทั้งสองจริงพร้อมกัน:

Open-ended generation. ไม่มี continuation ที่ถูกต้องเพียงหนึ่งเดียว ดังนั้นตัวที่น่าจะเป็นที่สุดจึงเป็นกับดัก — มันวนลูป และ 87.6 % ของมันคัดลอกจากตัวเอง Sample

งานที่มีคำตอบถูกต้องหนึ่งเดียว. มี continuation ที่ถูกต้องเพียงหนึ่งเดียวจริง ดังนั้นการดึงอย่างอื่นคือการดึง error 100 % ของบทที่ 12 กลายเป็น 81 % ด้วยเหตุผลนี้พอดี อย่า sample

prompt ใน production ส่วนใหญ่เป็นแบบที่สอง แต่ถูกตั้งค่าเหมือนแบบแรก เพราะ temperature ถูกปล่อยไว้ตามตัวอย่าง code ที่ใช้

วิธีตัดสองแบบ และมีเพียงแบบเดียวที่ปรับตัวได้

ลิงก์ไปยังส่วน: วิธีตัดสองแบบ และมีเพียงแบบเดียวที่ปรับตัวได้

การ sample จากการแจกแจงเต็มไม่ใช่สิ่งที่ใครทำจริง เพราะ tail มหึมาและเต็มไปด้วยเรื่องไร้สาระ ต้องมีอะไรบางอย่างถูกตัดออก คำตอบแบบคลาสสิกมีสองแบบ และต่างกันในแง่เดียวที่ตัดสินทุกอย่าง

Top-k เก็บ candidates จำนวนคงที่ เรียงตามความน่าจะเป็น เก็บ kk ตัวแรก ทิ้งที่เหลือ แล้ว renormalise4 Top-p หรือที่เรียกว่า nucleus sampling เก็บ mass ปริมาณคงที่: หยิบ tokens ตามลำดับลดหลั่นจน cumulative probability ถึง pp แล้วหยุด3 อย่างเป็นทางการ nucleus คือเซตที่เล็กที่สุด VpV_p ที่มี

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

ความต่างฟังดูเหมือนเครื่องสำอางแต่ไม่ใช่ เพราะ prompts สองอันที่คุณส่งในนาทีเดียวกันมีรูปทรงการแจกแจงต่างกันโดยสิ้นเชิง ทั้งสองรายการนี้คือโมเดลเดียวกันที่ temperature 1:

Q: What is the capital of France?\nA:Once upon a time,
top-1 probability96.01 %25.39 %
tokens holding 90 % of the mass1467
top-k = 40 keeps99.61 % of the mass78.87 % of the mass
mass in ranks 2 to 403.61 %53.48 %
token at rank 40␣Av, 0.0093 %␣Dr, 0.128 %

ค่า kk คงที่หนึ่งค่า ล้มเหลวสองทิศทางตรงข้ามกัน บน factual prompt, k=40k = 40 รับ tokens 39 ตัวที่รวมกันมีค่า 3.6 % — มันปล่อยขยะผ่านเข้ามา รวมถึง candidate ที่มีค่าเก้าในพันของเปอร์เซ็นต์ เพราะกฎนับ slots ไม่ใช่หลักฐาน บน story prompt, k=40k = 40 เดียวกันโยนทิ้ง mass 21 % ที่โมเดลให้ไว้จริง เพราะ nucleus จริงตรงนั้นกว้าง 467 tokens

Top-p ทำให้เลขเพียงตัวเดียวทำงานทั้งสองแบบได้ ตั้ง p=0.9p = 0.9 แล้วมันเก็บ 1 token ใน prompt แรกและ 467 ใน prompt ที่สอง เพราะมันถามคำถามเกี่ยวกับการแจกแจง แทนที่จะบังคับจำนวนลงไป ดูการปรับตัวนั้นตรง ๆ — cut เดียวกัน, temperature สี่ค่า:

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

3 จาก 10 token ผ่านการตัดและแบ่งความน่าจะเป็นกัน

ดูข้อมูลในรูปแบบตาราง
Tokenlogitหลังปรับอุณหภูมิหลังการตัด
␣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%
การสุ่มตัวอย่าง: อุณหภูมิ, top-p และ top-k

Top-p ที่ 0.90 โดย temperature อยู่ที่ 1.5: tokens สิบตัวมี สาม ตัวที่รอดและแบ่ง mass กัน, ␣Paris ถูก renormalised เป็น 91.10 % ทีนี้ขยับเฉพาะ temperature ที่ 0.7 ค่า 0.90 เดิมเหลือผู้รอด หนึ่ง ตัว — nucleus ที่แคบขนาดนั้นคือ greedy decoding ในชื่ออื่น ที่ 2.0 มันเหลือ ห้า ตัว cut ไม่เคยขยับ; รูปร่างข้างใต้มันต่างหากที่ขยับ

widget นั้นยังปิดความเข้าใจผิดที่ควรระบุชื่อ เพราะมันทำให้ผู้คนเสียเงินจริง บนการแจกแจงที่มั่นใจ top_p = 0.9 ไม่ใช่ “variety นิดหน่อย” มันคือ greedy ที่ temperature 1 token นำตรงนี้ถือ 96.90 % ซึ่งเกิน 0.9 อยู่แล้ว ดังนั้น nucleus กว้างหนึ่ง token และไม่มีอย่างอื่นถูกดึงได้เลย ทีมตั้ง top_p เป็น 0.9 โดยเชื่อว่าคลายอะไรบางอย่างแล้วสงสัยว่าทำไมทุก response เหมือนกัน

ตั้ง top-k แทน แล้วความล้มเหลวตรงข้ามก็เห็นชัดไม่แพ้กัน:

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

5 จาก 10 token ผ่านการตัดและแบ่งความน่าจะเป็นกัน

ดูข้อมูลในรูปแบบตาราง
Tokenlogitหลังปรับอุณหภูมิหลังการตัด
␣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%
การสุ่มตัวอย่าง: อุณหภูมิ, top-p และ top-k

Top-k ที่ 5, ไม่มี top-p tokens ห้าตัวรอดทุก temperature เพราะห้าคือสิ่งที่ถูกขอ ที่ temperature 1 ตามที่แสดง candidates สี่ตัวใต้ ␣Paris มีค่ารวมกัน 2.79 % ลดไปที่ 0.7 แล้วสี่ตัวเดิมมีค่า 0.38 % — cut เป็นละคร และโมเดลแทบจะเป็น greedy เพิ่มไปที่ 2.0 แล้วมันมีค่า 22.54 % setting เดียวกัน survivor count เดียวกัน พฤติกรรมต่างกันโดยสิ้นเชิงสามแบบ และไม่มีอะไรในคำขอบอกคุณว่าคุณกำลังได้แบบไหน

penalties พร้อมสูตร เพราะคนสับสนกันเป็นโรคระบาด

ลิงก์ไปยังส่วน: penalties พร้อมสูตร เพราะคนสับสนกันเป็นโรคระบาด

กลไกสามแบบเดินทางภายใต้ชื่อคล้ายกัน มันทำสิ่งต่างกัน และความต่างวัดได้ ให้ cic_i เป็นจำนวนครั้งที่ token ii ปรากฏไปแล้ว

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

ลบ ค่าคงที่ จาก token ใด ๆ ที่เคยปรากฏเลย ปรากฏหนึ่งครั้งกับปรากฏสี่สิบครั้งถูกลงโทษเท่ากัน มันคือสวิตช์ ไม่ใช่ปุ่มหมุน

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

ลบตาม สัดส่วนของจำนวนครั้ง token ที่ถูกใช้สี่ครั้งถูกลงโทษหนักกว่า token ที่ใช้ครั้งเดียวสี่เท่า และแรงกดทับซ้อนเมื่อข้อความยาวขึ้น

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}

ตัวดั้งเดิมจาก paper CTRL7 มัน หาร แทนที่จะลบ โดยต้องแยกกรณี sign เพราะการหาร logit ติดลบจะทำให้มัน ใหญ่ขึ้น ดังนั้นความแรงของมันขึ้นกับ magnitude ของ logit ซึ่งหมายความว่า ρ\rho เดียวกันกระทบต่างกันในจุดต่าง ๆ ของประโยคเดียวกัน

continuation ที่ degenerate เดิมจากก่อนหน้า เมื่อนำแต่ละแบบไปใช้ “Steps altered” นับว่าจาก 120 generation steps มีเท่าไรที่เลือก token ต่างจากโมเดลที่ไม่ถูกลงโทษ การ run ตรงนี้มี 120 steps เทียบกับ 140 ในบล็อกด้านบน ซึ่งเป็นเหตุผลที่ baseline แบบไม่ลงโทษอ่านได้ 85.5 % ไม่ใช่ 87.6 %:

settingrepeated 4-gramssteps altered
nothing85.5 %0 / 120
presence 0.565.0 %3 / 120
presence 1.03.4 %11 / 120
frequency 0.56.0 %12 / 120
frequency 1.00.0 %20 / 120
repetition 1.2 (CTRL)0.0 %35 / 120

มีสามอย่างตามมา Presence ที่ 0.5 เปลี่ยนการตัดสินใจสามครั้งจาก 120 และลด repetition ลงหนึ่งในสี่ — ลูปถูกยึดไว้ด้วย tokens เพียงหยิบมือ Frequency ที่ 0.5 เปลี่ยนการตัดสินใจมากกว่าสี่เท่าและให้ผลใหญ่กว่ามาก เพราะตัวคูณ count โตต่อไปเรื่อย ๆ ขณะที่ค่าคงที่ของ presence ไม่โต และ CTRL penalty ที่ค่าถูกคัดลอกกันแพร่หลาย 1.2 เขียน 35 จาก 120 การตัดสินใจ ใหม่ ซึ่งไม่ใช่การสะกิด; มันคือโมเดลคนละตัว

เลขสุดท้ายนั้นคือฉากตั้งต้นสำหรับความล้มเหลวที่ไม่มีใครเตือน

penalties ทำอะไรกับข้อความที่ควรต้องซ้ำ

ลิงก์ไปยังส่วน: penalties ทำอะไรกับข้อความที่ควรต้องซ้ำ

Code ซ้ำ Tables ซ้ำ Lists ซ้ำ Structured output ซ้ำโดยนิยาม — นั่นแหละคือ structure penalty แยกไม่ออกระหว่างโมเดลที่ติดลูปกับโมเดลที่กำลัง emit แถวที่สี่ของตารางอย่างถูกต้อง เพราะทั้งสองดูเหมือน token ปรากฏอีกครั้ง

สามงานเดิม สร้างสามวิธี:

tasknothingfrequency 0.5repetition 1.2
markdown table, 6 rows0 / 56 steps altered0 / 562 / 62
Python function0 / 930 / 9310 / 110
bulleted list, 1 to 120 / 500 / 500 / 50

Frequency penalty ที่ 0.5 กลายเป็นว่าไม่เป็นอันตรายในทั้งสามงาน ซึ่งเป็นผลที่มีประโยชน์และน่าประหลาดใจเล็กน้อย และมันบอกอะไรที่แม่นยำ: เนื่องจากไม่มีการตัดสินใจเปลี่ยน structural tokens ต้องชนะตำแหน่งของตัวเองด้วย margin มากกว่าค่าที่ penalty ลบ แม้หลังจากปรากฏห้าและหกครั้งแล้ว CTRL penalty ซึ่ง หาร แทน กลับเขี่ยมันหลุด และนี่คือสิ่งที่มันสร้าง:

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

alignment พัง: ปริมาณ padding ภายในแต่ละ cell เปลี่ยนจากแถวหนึ่งไปอีกแถวหนึ่ง เพราะชุด spaces ก่อน closing pipe คือ repetition แบบที่ penalty ถูกสร้างมาเพื่อทำลายพอดี เป็นเรื่อง cosmetic และใช้ tokens เพิ่มอีกหกตัว เคส Python ไม่ใช่ cosmetic:

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 ผลักโมเดลออกจาก total — ที่ใช้ไปแล้วใน docstring — ไปยัง total_sum, ยัด output ด้วย comments ที่แต่งขึ้นเพื่อใช้ budget กับ tokens ที่ยังไม่ถูกใช้ แล้วเดินเข้าสู่ range แบบสามอาร์กิวเมนต์พร้อม stride comment บอกว่า incrementing by 2 each time ซึ่งผิดสำหรับผลรวมกำลังสองจาก 1 ถึง nn repetition penalty สร้าง code ที่ไม่ถูกต้องจาก prompt ที่ตอบได้ถูกต้องเมื่อไม่มีมัน

กฎที่ตามมาสั้น ๆ: penalties มีไว้สำหรับ prose ปลายเปิด และควรปิดสำหรับ code, structured output, tabular data และสิ่งใดก็ตามที่มี schema บทที่ 18 ว่าด้วยหมวดที่สองนั้นพอดี

ลำดับการใช้ และทำไมมันเปลี่ยนคำตอบ

ลิงก์ไปยังส่วน: ลำดับการใช้ และทำไมมันเปลี่ยนคำตอบ

implementation จริงทุกตัวใช้สิ่งเหล่านี้ในลำดับเฉพาะหนึ่งลำดับ:

penalties → temperature → top-k → top-p → sample

นี่ไม่ใช่งานบัญชีตามใจชอบ และการสลับสองขั้นทำให้การแจกแจงต่างกันจริง ๆ สองการวัด ทั้งคู่บน factual prompt

ตัดก่อนหรือหลัง temperature. nucleus ถูกคำนวณบนการแจกแจงที่มันได้รับ และ temperature เปลี่ยนการแจกแจงนั้นอย่างรุนแรง:

top-p 0.9 after temperaturetop-p 0.9 before temperature
T=1.0T = 1.01 token1 token
T=1.5T = 1.5353 tokens1 token
T=2.0T = 2.032,966 tokens1 token

ที่ T=2T = 2 setting nominal เดียวกันให้ candidate set ขนาด 32,966 หรือ 1 ขึ้นอยู่กับล้วน ๆ ว่าขั้นไหนทำก่อน ถ้าคุณเคยสงสัยว่าทำไมการเพิ่ม temperature “ไม่ทำอะไร” กับ provider หนึ่งแต่ทำลาย output กับอีก provider โดยใช้ตัวเลขสองตัวเดียวกัน ตารางนี้คือคำตอบที่เป็นไปได้

ลงโทษก่อนหรือหลัง temperature. ลบ penalty α\alpha แล้วค่อยหารด้วย TT ให้ effective penalty เป็น α/T\alpha/T; หารก่อนแล้วค่อยลบให้ α\alpha ด้วย presence penalty 1.0 ที่ใช้กับ leading token:

temperaturepenalise, then tempertemper, then penalise
0.599.858 %99.948 %
1.089.839 %89.839 %
2.010.783 %6.830 %

เหมือนกันที่ T=1T = 1 อย่างที่ต้องเป็น ต่างกันด้วย factor 1.58 ที่ T=2T = 2 “Presence penalty 1.0” ไม่ใช่ปริมาณ penalty ที่นิยามชัดเจน เว้นแต่คุณรู้ด้วยว่า temperature ถูกใช้ตรงไหน และไม่มี API ไหน document เรื่องนี้

แสดงรายละเอียด

ทางเลือก: pipeline ทั้งหมด ตามลำดับด้านบน

สิบหกบรรทัด และทุกอย่างในบทนี้อยู่ในนั้น มันคือ computation เดียวกับที่ widget ทำ บนเวกเตอร์ logit จริงแทนที่จะเป็นตัวเลขคงที่สิบตัว

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)])

cumsum(0) - p ในบรรทัด top-p คือ cumulative mass ที่ไม่รวม token ปัจจุบัน ซึ่งเป็นสิ่งที่ทำให้ nucleus รวม token ที่ข้าม threshold เข้าไป แทนที่จะหยุดก่อนหน้ามันพอดี ทำ off by one ตรงนี้ แล้ว top_p = 0.9 จะกลายเป็น cut ที่แน่นกว่า implementation อื่นเล็กน้อยอย่างเงียบ ๆ

นี่เป็นหนึ่งในไม่กี่จุดในครึ่งหลังของคอร์สที่ Python เป็นภาษาที่ถูกต้อง และเหตุผลเป็นเชิงโครงสร้าง ไม่ใช่สไตล์: ทุกบรรทัดด้านบนต้องมีเวกเตอร์ logits เต็มอยู่ในมือ และเมื่อผ่าน HTTP API เวกเตอร์นั้นไม่มีอยู่ คุณส่ง temperature และ top_p ไปให้ provider ได้; คุณ implement มันเองไม่ได้ และคุณมองไม่เห็นว่ามันทำอะไร

provider ทุกเจ้ารับ subset ต่างกันของ controls เหล่านี้ ด้วยช่วงค่าต่างกัน และเพิกเฉยส่วนที่เหลืออย่างเงียบ ๆ นี่ไม่ใช่คำบ่นเชิงนามธรรม แอปพลิเคชันใดก็ตามที่มีตัวเลือก model ต้องเขียนความต่างเหล่านี้ไว้ที่ไหนสักแห่ง และไฟล์ที่ทำแบบนั้นคือแผนที่ของความเข้ากันไม่ได้ นี่คือสิ่งที่ catalogue หนึ่งในลักษณะนี้ประกาศสำหรับพารามิเตอร์เดียวเหนือ text sources เก้าแหล่งที่มันรองรับ:

declared temperature rangesources
0 to 1Anthropic, Google, Meta, Cerebras, PaLM
0 to 1.5Mistral
0 to 2OpenAI, DeepSeek, xAI

คำเดียวกัน แต่ scale ไม่เหมือนกัน “temperature of 1” คือการแจกแจงที่ไม่ถูกแก้ไขสำหรับที่หนึ่ง และเป็นความร้อนสูงสุดที่อนุญาตในอีกที่หนึ่ง และครึ่งหนึ่งของ catalogue ไม่สามารถแสดงค่าที่อีกครึ่งถือว่า neutral-plus-a-bit ได้ knobs ที่เหลือไม่สม่ำเสมอพอกัน: entries ของ OpenAI, DeepSeek และ xAI รับ presence และ frequency penalties และไม่มี topK; entries ของ Google, Meta, Cerebras และ PaLM รับ topK และไม่มี penalties; Anthropic รับ topK, topP และ stop sequences และไม่มี penalties; และ มีเพียงหนึ่งจากเก้า — Mistral — ที่รับ seed การส่งพารามิเตอร์ที่ provider ไม่ implement โดยทั่วไปไม่ให้ error เลย: request สำเร็จ, knob ไม่ทำอะไร, แล้วคุณสรุปว่า setting ไม่มีผล

และสังเกตว่าไฟล์แบบนี้คืออะไร: claim เกี่ยวกับ API ของคนอื่น เขียนขึ้นในวันหนึ่งวันใด และไม่มีอะไรตรวจสอบหลังจากนั้น catalogue ที่บอก 0 ถึง 1 สำหรับ provider ที่ตอนนี้รับ 0 ถึง 2 จะ cap ทุก request อย่างเงียบ ๆ

controls อีกสองตัวอยู่ในตระกูลเดียวกัน logprobs เมื่อมีให้ใช้ จะคืน log-probabilities ของ token ที่เลือก และมักคืน alternatives อันดับต้น ๆ ไม่กี่ตัว — หน้าต่างเดียวที่คุณมีสู่การแจกแจงที่บทนี้พูดถึง และเป็นฐานของ confidence heuristic ทุกแบบที่สร้างบน closed model ส่วน maximum tokens บวก stop sequences จบ generation โดยไม่อ้างอิงความน่าจะเป็นเลย: hard cap และ string match ทั้งคู่ปรากฏเป็น finish_reason จาก บทที่ 14 ซึ่ง length หมายความว่าคำตอบของคุณถูกตัดกลางประโยคด้วย budget ไม่ใช่โมเดลจบเอง

ตั้ง seed แล้ว sampling จะทำซ้ำได้ ส่วนนั้นจริง และตรวจสอบง่าย:

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

เหมือนกันระดับ byte ภายใน seed เดียวกัน ต่างกันข้าม seeds เป็นไปตามที่โฆษณาไว้พอดี ดังนั้นสิ่งที่ seed fix คือ random draw ในบรรทัดสุดท้ายของฟังก์ชัน sample นั้น — token ใดถูกเลือกเมื่อมีการแจกแจงหนึ่ง

สิ่งที่มันไม่ fix คือการแจกแจง และตรงนั้นคือปัญหา เพราะเวกเตอร์ logits ที่โมเดลของคุณสร้างไม่ใช่วัตถุทางคณิตศาสตร์; มันคือผลลัพธ์ของการบวก floating-point หลายพันล้านครั้ง และการบวกเหล่านั้นมีลำดับ

บทที่ 2 เตรียมการทดลองนี้ไว้แล้ว ตัวเลข float32 หนึ่งล้านตัวเดียวกัน บวกด้วยการจัดกลุ่มต่างกัน:

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

ดูบรรทัดสุดท้าย จำนวน chunks เปลี่ยนคำตอบ นั่นไม่ใช่เรื่องแปลกเกี่ยวกับ numpy; มันคือกลไก เพราะเมื่อ inference server แบ่ง reduction ไปยังหน่วย parallel มากขึ้นหรือน้อยลง มันกำลังทำสิ่งนี้พอดี และ server แบ่งตามจำนวน requests ที่มันกำลังให้บริการ

นี่คือผลนั้นบนตัวโมเดลเอง prompt เดียวกัน, forward pass เดียวกัน, ความต่างเดียวคือมี requests อื่นเกิดขึ้นใน batch กี่รายการ:

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

run ลำพัง โมเดล deterministic สมบูรณ์ — ยี่สิบ pass เหมือนกันระดับ bit ใส่ prompt เดียวกันเป๊ะเข้าไปใน batch พร้อม requests ที่ไม่เกี่ยวข้อง แล้ว 97 % ของ logits เปลี่ยน ไม่มีอะไรเกี่ยวกับ request ของคุณเปลี่ยน มี request ของคนอื่นมาถึง

ทีนี้ส่วนที่ซื่อตรง เพราะเรื่องนี้มักถูกเล่าเหมือนจบแค่นั้น การเปลี่ยน 2.5×1052.5 \times 10^{-5} จะเปลี่ยน output ก็ต่อเมื่อ candidate tokens สองตัวอยู่ห่างกันภายในค่านั้น จาก 717 generation steps ในสิบสอง prompts ช่องว่างที่เล็กที่สุดระหว่าง top two logits คือ 2.5×1032.5 \times 10^{-3} — ใหญ่กว่า perturbation ร้อยเท่า — และ ไม่มี step ใดใกล้พอที่จะ flip ดังนั้นบนโมเดลนี้, ใน float32, บน laptop, batching ขยับ logit ทุกตัวแต่ไม่เปลี่ยน token ใดเลย

นั่นคือคำอธิบายของเงื่อนไขที่เอื้ออำนวย ไม่ใช่คำปลอบใจ และเปลี่ยนเงื่อนไขเพียงอย่างเดียวก็พอ:

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

หกจากแปดคำตอบแยกทาง และหนึ่งคำตอบแย่ลงมาก ตารางของบทที่ 2 บอกว่าทำไม: bfloat16 เก็บ mantissa 7 bits ดังนั้นใกล้ magnitude logit 16 ค่าที่ represent ได้ห่างกัน 0.125 — 16.0, แล้ว 16.125, แล้ว 16.25 — และ rounding สามารถขยับ logit ได้ถึง 0.0625 ขณะเดียวกัน 4.7 % ของ generation steps ที่วัดด้านบนมี top-two gap ต่ำกว่า 0.1 นั่นคือความต่างทั้งหมดระหว่างสองการทดลอง: ใน float32 perturbation เล็กกว่าการตัดสินใจที่ใกล้ที่สุดร้อยเท่า และใน bfloat16 มันมีขนาดเท่ากัน Production inference run ใน 16-bit บน hardware ที่มี fused kernels และ reduction orders ที่ไม่มีใครสัญญาว่าจะคงไว้ คำถามว่า “numerical noise เล็กน้อยจนละเลยได้ไหม” เป็นคำถามเกี่ยวกับ precision และ hardware ไม่ใช่เกี่ยวกับโมเดล

ดังนั้น สาเหตุสี่ข้อ ตาม catalogue ที่บทที่ 9 สัญญาไว้:

กล่องของบทที่ 2 ลำดับของผลรวมเปลี่ยนค่าของมัน ดังนั้นการเปลี่ยนวิธีแบ่ง reduction ใด ๆ จะเปลี่ยน logits นี่คือ substrate; อีกสามข้อคือวิธีเปลี่ยนลำดับ

Dynamic batching จัดกลุ่ม request ของคุณกับคนแปลกหน้า

ลิงก์ไปยังส่วน: Dynamic batching จัดกลุ่ม request ของคุณกับคนแปลกหน้า

Continuous batching จาก บทที่ 13 คือเหตุผลที่ inference ราคาเอื้อมถึง — และหมายความว่ารูปร่างของ matrices ที่ tokens ของคุณไหลผ่านขึ้นกับ traffic วัดไว้ด้านบน: logits 147,321 ตัวขยับเพราะ batch size เปลี่ยน

กล่องของบทที่ 9 พูดไว้แล้ว router เลือกแบบ discrete ต่อ token ต่อ layer ภายใต้ capacity limits ต่อ expert ที่คำนวณเหนือ batch token ที่หากอยู่ลำพังจะไป expert 7 เมื่อมีเพื่อนร่วมทางจะไป expert 12 นี่ไม่ใช่ความต่างจาก rounding; มันคือชุด weights คนละชุด

version string อย่าง -latest คือ pointer และ pointers ถูก repoint ได้ Providers ยัง update serving stack ภายใต้ version identifier คงที่ด้วย ทั้งสองอย่างไม่ได้ถูกประกาศใน granularity ที่ให้คุณ correlate กับ output ของคุณที่เปลี่ยนได้

พารามิเตอร์ seed ของ OpenAI ซื่อตรงเรื่องนี้ในทางเดียวที่มันทำได้: มันมาพร้อม field system_fingerprint ที่ระบุ backend configuration และ documentation ระบุว่า determinism เป็น best-effort และ fingerprint ที่เปลี่ยนหมายความว่าผลลัพธ์อาจต่าง อ่านมันตามที่มันเป็น — provider กำลังบอกคุณว่ามันควบคุมสาเหตุทั้งสี่ข้อข้างบน คุณควบคุมไม่ได้เลย และสิ่งเดียวที่มันเสนอได้คือบอกคุณ หลังจากข้อเท็จจริง ว่าบางอย่างขยับ

ทุกอย่างที่นี่ว่าด้วย knob และผลที่ตามมา ถอยออกมาหนึ่งระดับ แล้วปัญหาที่ยากกว่าจะปรากฏ: วัตถุที่เราปรับจูนกันอยู่คือการแจกแจงความน่าจะเป็น และการแจกแจงความน่าจะเป็นไม่มี interface

function call มี interface database row มี interface handler POST ที่คาดหวัง JSON body พร้อม required fields สามช่องมี interface และมันจะ reject อย่างอื่นทั้งหมด ระหว่างโมเดลกับ component อื่นทุกตัวในระบบของคุณมี contract ที่ฝ่ายหนึ่งให้คำสัญญาไม่ได้: โมเดลจะสร้าง บางอย่าง ที่ดึงมาจากการแจกแจงซึ่งคุณปรับรูปทรงแล้วแต่ไม่ได้ตรึงไว้ และ code อีกฝั่งต้องการค่าชนิดที่รู้จัก ไม่เช่นนั้นก็ throw

สะพานระหว่างสองโลกนั้นสร้างจากวัสดุของบทนี้ ไม่ใช่จาก parsing และ retries ถ้า token หนึ่งจะทำลาย structure ที่ต้องการ คุณไม่ sample มันแล้วหวัง — คุณตั้ง logit ของมันเป็น -\infty ก่อนที่ softmax จะเห็นมันด้วยซ้ำ Constrained decoding คือ mask เหนือเวกเตอร์เดียวกับที่เราใช้ทั้งบทปรับรูปทรง และมันเปลี่ยน “please reply in JSON” จากคำขอให้เป็นการรับประกัน

บทที่ 18 คือ contract นั้น: tool calling, JSON Schema, structured outputs และสิ่งที่ต้องใช้เพื่อทำให้ deterministic system ปลอดภัยพอจะสร้างทับบน probabilistic system


การวัดทั้งหมดในบทนี้มาจาก Qwen/Qwen2.5-0.5B-Instruct บน CPU, float32 เว้นแต่ระบุไว้ โดย implement sampling ตามที่เขียนใน section ทางเลือก แทนที่จะ delegate ให้ library มันเป็นโมเดลขนาดเล็ก และค่าจำเพาะเป็นของมัน; กลไกไม่ใช่ Von Platen, How to generate text with different decoding methods (Hugging Face, 2020) คือบทความที่บทนี้วัดเทียบ และยังเป็นบทนำสั้นที่ดีที่สุดสู่เนื้อหาเดียวกัน สำหรับ section determinism: reproducibility notes ของ PyTorch อธิบายว่า seed fix และไม่ fix อะไรบนเครื่องเดียว, documentation ของ OpenAI สำหรับ seed และ system_fingerprint อธิบายว่า provider สัญญาอะไรได้และไม่ได้ และบทสนทนาในปี 2025 ของ Thinking Machines เรื่อง batch-invariant kernels เป็นคำอธิบายสาธารณะที่ชัดที่สุดว่าทำไมการแก้สิ่งนี้ที่ระดับ inference-server เป็นไปได้แต่ไม่ฟรี

  1. Ackley, D. H., Hinton, G. E. and Sejnowski, T. J. A Learning Algorithm for Boltzmann Machines. Cognitive Science 9(1), pp. 147–169 (1985), ซึ่ง temperature ใน softmax มาจาก statistical physics Hinton, G., Vinyals, O. and Dean, J., Distilling the Knowledge in a Neural Network, arXiv:1503.02531 (2015), section 2, คือที่ที่พารามิเตอร์เดียวกันกลับมาปรากฏใน deep learning สมัยใหม่ — ในฐานะวิธีเผยการแจกแจงเต็มของ teacher ซึ่งเป็น soft labels ของบทที่ 13 ไม่ใช่ sampling ของบทนี้

  2. Guo, C., Pleiss, G., Sun, Y. and Weinberger, K. Q. On Calibration of Modern Neural Networks. arXiv:1706.04599 (2017). อย่าสับสนสิ่งนี้กับ temperature ในบทนี้ Temperature scaling fit ค่าเดียวบน validation set เพื่อให้ confidence ของโมเดลตรงกับ accuracy ของมัน; มันเป็น post-hoc calibration method ที่ใช้กับ outputs ของ classifier Temperature sampling คือ runtime control เหนือวิธีที่ generator ดึง tokens สูตรเดียวกัน จุดประสงค์ต่างกัน และไม่มีค่าที่ใช้ร่วมกัน

  3. Holtzman, A., Buys, J., Du, L., Forbes, M. and Choi, Y. The Curious Case of Neural Text Degeneration. arXiv:1904.09751 (2019). แนะนำ nucleus sampling และการวัดที่ว่า maximisation-based decoding สร้างข้อความที่ probability profile ไม่เหมือน human text เลย 2

  4. Fan, A., Lewis, M. and Dauphin, Y. Hierarchical Neural Story Generation. arXiv:1805.04833 (2018). paper ที่ทำให้ top-k sampling เป็นที่นิยม

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

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

  7. 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). Section 4.1 คือ repetition penalty ดั้งเดิม — ตัวที่หาร


สร้างโดย

David Vicente Campos

ผู้ก่อตั้ง NeuraLIA Labs และผู้ร่วมก่อตั้ง MyRealFood

ผมเป็นวิศวกรคอมพิวเตอร์ที่จบจากมหาวิทยาลัยเลออน ผมร่วมก่อตั้ง MyRealFood ที่ที่ผมในฐานะ CTO ได้สร้างแอปซึ่งผู้คนหลายล้านคนใช้เพื่อกินให้ดีขึ้น และผมก่อตั้ง NeuraLIA Labs ที่ที่ผมสร้างผลิตภัณฑ์ AI ที่นี่ผมเขียนถึงสิ่งที่ผมต้องทำความเข้าใจระหว่างทาง ในแบบที่ผมเคยหวังว่าจะมีใครสักคนอธิบายให้ผมฟัง

เพิ่มเติมเกี่ยวกับผู้เขียน

เผยแพร่โดย NeuraLIA Labs

รับโพสต์ใหม่ในกล่องจดหมาย

ข่าว AI คู่มือ และอัปเดตผลิตภัณฑ์ — อีเมลสั้น ๆ เมื่อเรามีสิ่งที่คุ้มเวลาของคุณ

ชอบแบบข้อความมากกว่าไหม รับเนื้อหาเดียวกันได้ที่นี่:คอมมูนิตี้ WhatsApp (เปิดในแท็บใหม่)ช่อง Telegram (เปิดในแท็บใหม่)

ดัชนีคอร์ส

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jevอ่าน 5 นาที

โมเดล AI Jev สร้างมาเพื่อการตัดสินใจ ไม่ใช่การเขียนความเรียง

Jev ของ TypeSafe AI กำลังได้รับความสนใจ เพราะมองความฉลาดของซอฟต์แวร์เป็นปัญหาความน่าจะเป็น: เลือกกิ่งที่ถูกต้อง แนบความมั่นใจ และหลีกเลี่ยงการจ่ายเงินให้ LLM เขียนข้อความเมื่อโค้ดต้องการการตัดสินใจ

Abstract legal research workspace with documents, search nodes and governance controls.
openaiอ่าน 4 นาที

Astra for Law ของ OpenAI คือระบบ AI ด้านกฎหมาย ไม่ใช่โมเดลใหม่

การเปิดตัวด้านกฎหมายของ OpenAI ไม่ได้เน้นโมเดลฐานรากใหม่เท่ากับระบบที่ล้อมรอบโมเดลนั้น: การค้นคืนเฉพาะโดเมน เครื่องมือที่เชื่อถือได้ สิทธิ์ เบนช์มาร์ก และเส้นทางการตรวจทาน

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineeringอ่าน 4 นาที

วิศวกรรมบริบทสำหรับเอเจนต์ AI ที่ทำงานระยะยาว

เอเจนต์ที่ทำงานต่อเนื่องไม่ได้ล้มเหลวเพียงเพราะหน้าต่างบริบทเล็กเกินไป แต่ล้มเหลวเมื่อไฟล์ ผลลัพธ์จากเครื่องมือ และประวัติที่ค้างเก่าบดบังงานที่เอเจนต์ควรทำให้เสร็จ

พร้อมให้ LIA เลือกโมเดลให้แล้วหรือยัง?

สร้างงานด้วยโมเดล AI ทุกตัวในที่เดียว เริ่มฟรีวันนี้