ข้ามไปยังเนื้อหาหลัก

[LLM 7/10] Model Distillation: คำตอบที่ผิดของครู คือส่วนที่มีค่าที่สุด

· อ่าน 9 นาที
Kobkrit Viriyayudhakorn
CEO, iApp Technology

บทที่ 6 เรากลั่น "บริบท" เข้าไปในน้ำหนักของโมเดลตัวเดิม บทนี้เราจะกลั่น "โมเดลทั้งตัว" ลงไปในโมเดลที่เล็กกว่า สองบทนี้เป็นคู่กันโดยตั้งใจ: context distillation เปลี่ยนสิ่งที่โมเดลรู้โดยไม่ต้องบอกมันอีกต่อไป — model distillation เปลี่ยนขนาดของโมเดลโดยพยายามไม่เปลี่ยนสิ่งที่มันทำได้ และหัวใจของบทนี้ขัดสัญชาตญาณอย่างแรง: สิ่งที่มีค่าที่สุดที่ครูส่งให้นักเรียนได้ ไม่ใช่คำตอบที่ถูก แต่คือวิธีที่ครูผิด — และปุ่มที่ชื่อ temperature คือสิ่งที่ทำให้เรามองเห็นมัน

Open in Colab07_model_distillation.ipynb

1. ปัญหา (Problem statement)

สมมติว่าคุณเดินทางมาครบหกบท จนได้ Qwen3-1.7B ที่ตอบโจทย์ภาษาไทยขององค์กรได้น่าพอใจ แล้ววันหนึ่งฝ่าย infrastructure ถามคำถามเดียวที่โมเดลตอบไม่ได้: "ค่า GPU เดือนละเท่าไหร่"

โมเดล 1.7B กิน VRAM เกือบ 3 เท่าของ 0.6B และตอบช้ากว่าราว 2.5 เท่า ที่ 100 คำขอต่อวินาที ส่วนต่างนี้ไม่ใช่รายละเอียด — มันคือจำนวนการ์ดที่ต้องซื้อเพิ่มทุกเดือนตลอดอายุระบบ

ทางเลือกคุณภาพต้นทุนตอนใช้งาน
Deploy ครู 1.7B ตรง ๆดีที่สุดVRAM ~3 เท่า ช้ากว่า ~2.5 เท่า จ่ายตลอดอายุระบบ
Deploy นักเรียน 0.6B ตรง ๆตกลงชัดเจนถูกและเร็ว
SFT นักเรียนด้วยเฉลยจริงดีขึ้นบ้างถูกและเร็ว
Model distillationขยับเข้าหาครูถูกและเร็ว เท่านักเรียนเป๊ะ

คำถามคือ แถวสุดท้ายรู้อะไรที่แถว SFT ไม่รู้ — เทรนเหมือนกัน ข้อมูลชุดเดียวกัน ต่างกันตรงไหน

คำตอบอยู่ที่ปริมาณข้อมูลต่อหนึ่ง token ฉลากแข็ง (hard label) คือ one-hot vector: บอกแค่ว่า "คำตอบคือ 3" จบ แต่ distribution ของครูที่ถูกทำให้นุ่มด้วย temperature บอกว่า "คำตอบคือ 3 — แต่ 8 ก็พอเป็นไปได้อยู่ ส่วน 'แมว' นี่ไร้สาระสิ้นเชิง" การจัดอันดับเหนือคำตอบที่ผิดทั้งหมดนี่แหละที่ Hinton เรียกว่า dark knowledge มันเข้ารหัสโครงสร้างความคล้ายของโลกเอาไว้ (เลข 3 ใกล้เลข 8 มากกว่าใกล้แมว) และมันหายไปหมดเกลี้ยงเมื่อคุณเก็บแต่ argmax

ทุกตำแหน่ง token ครูมีตัวเลขให้ 151,936 ตัว (ขนาด vocab ของ Qwen3) — ฉลากแข็งเก็บมาแค่ตัวเดียว

2. เราจะทำอะไร (Solution)

เราจะเอา Qwen/Qwen3-1.7B เป็นครู และ Qwen/Qwen3-0.6B-Base เป็นนักเรียน แล้วกลั่นด้วยกัน 3 ระดับ ซึ่งส่งข้อมูลจากครูละเอียดขึ้นเรื่อย ๆ:

  1. SeqKD — ให้ครู generate คำตอบ แล้ว SFT นักเรียนบนคำตอบนั้น (ตัวอย่างจาก distribution)
  2. Logit KD — ให้นักเรียนเลียนแบบ distribution ของครูทั้งก้อน ทีละตำแหน่ง token (ตัว distribution เอง)
  3. GKD (ทางเลือกเสริม) — ให้นักเรียนสุ่มคำตอบของตัวเอง แล้วครูให้คะแนน distribution แบบ on-policy

และที่ขาดไม่ได้คือแถวควบคุม: SFT นักเรียนด้วยเฉลยจริงบนข้อมูลชุดเดียวกัน จำนวน step เท่ากัน ถ้าไม่มีแถวนี้ เราจะแยกไม่ออกเลยว่ากำไรมาจาก "distribution ของครู" หรือมาจาก "การเทรนเพิ่มเฉย ๆ"

แนวคิดหลักของบทนี้

ฉลากแข็งบอกว่า "คำตอบคือ 3" — distribution ของครูบอกว่า "3 แต่ 8 ก็เกือบใช่ และ 'แมว' เป็นไปไม่ได้" การจัดอันดับเหนือคำตอบที่ผิดคือ dark knowledge และ temperature คือปุ่มที่เปิดเผยมัน ที่ T = 1 ความรู้นี้ถูกบีบจนมองไม่เห็น (ครูมั่นใจ 0.97) พอยก T ขึ้น มันจึงกลายเป็น signal ที่เทรนได้จริง

วิธีนี้ไม่ใช่เทคนิคห้องทดลอง — มันคือวิธีที่โมเดล "เล็กแต่เก่ง" ส่วนใหญ่ในโลกถูกสร้างจริง Qwen3-0.6B ที่เราใช้กันมาทั้งซีรีส์ ก็ถูกฝึกด้วย strong-to-weak distillation จากรุ่นใหญ่ของตระกูลมันเอง บทนี้เรากำลังทำสิ่งเดียวกัน ในขนาดที่ Colab ฟรีรับไหว

3. สมการ (Equation)

3.1 KD loss ของ Hinton

LKD=(1α)LCE(y, softmax(zS))+αT2DKL(softmax(zT/T)  softmax(zS/T))\mathcal{L}_{\text{KD}} = (1-\alpha)\,\mathcal{L}_{\text{CE}}\big(y,\ \text{softmax}(z_S)\big) + \alpha\, T^2\,\mathbb{D}_{\text{KL}}\Big(\text{softmax}(z_T/T)\ \big\|\ \text{softmax}(z_S/T)\Big)
  • zS,zTz_S, z_T = logits ของนักเรียนและครู ที่ตำแหน่ง token เดียวกัน บน input เดียวกัน
  • yy = เฉลยจริง (hard label) — พจน์แรกคือ cross-entropy ปกติ เหมือน SFT ทุกประการ
  • TT = temperature หารเข้าไปใน logits ทั้งสองฝั่ง ก่อน softmax
  • α\alpha = น้ำหนักของพจน์ soft (เราใช้ 0.9 — ฟังครูเป็นหลัก มีเฉลยจริงคอยกันหลุด)

สังเกตทิศของ KL: ครูอยู่หน้า นี่คือ forward KL ที่บังคับนักเรียนให้แผ่ความน่าจะเป็น ครอบคลุมทุกที่ที่ครูให้น้ำหนัก จำจุดนี้ไว้ เดี๋ยวสมการ 3.4 จะทำให้มันกลายเป็น "จุดหนึ่งบนเส้น"

แล้ว T2T^2 ที่คูณอยู่หน้า KL มาจากไหน โค้ด KD แทบทุกชิ้นบนอินเทอร์เน็ตมีตัวคูณนี้ แต่น้อยชิ้นมากที่อธิบายว่าทำไม — และถ้าไม่เข้าใจมัน คุณจะจูน T แบบผิด ๆ โดยไม่รู้ตัว

3.2 อนุมานที่มาของ T2T^2 — สองบรรทัดที่แยก "เข้าใจ" ออกจาก "ก๊อปมา"

บรรทัดที่ 1 — gradient ของพจน์ soft ต่อ logit ของนักเรียนหนึ่งตัว คือ gradient มาตรฐานของ softmax-CE บวก chain rule ผ่าน z/Tz/T ซึ่งคาย 1/T1/T ออกมาหนึ่งตัว:

LsoftzS,i=1T(qi(T)pi(T)),q(T)=softmax(zS/T),p(T)=softmax(zT/T)\frac{\partial \mathcal{L}_{\text{soft}}}{\partial z_{S,i}} = \frac{1}{T}\Big(q_i^{(T)} - p_i^{(T)}\Big), \qquad q^{(T)} = \text{softmax}(z_S/T),\quad p^{(T)} = \text{softmax}(z_T/T)

บรรทัดที่ 2 — เมื่อ TT ใหญ่ softmax จะแบนลงรอบ ๆ uniform: softmax(z/T)i1K+zizˉKT\text{softmax}(z/T)_i \approx \tfrac{1}{K} + \tfrac{z_i - \bar z}{KT} (โดย KK = ขนาด vocab) ดังนั้นผลต่าง qi(T)pi(T)q^{(T)}_i - p^{(T)}_i ก็หดลงตาม 1/T1/T อีกชั้นหนึ่ง:

LsoftzS,i(zS,izˉS)(zT,izˉT)KT2    1T2\frac{\partial \mathcal{L}_{\text{soft}}}{\partial z_{S,i}} \approx \frac{(z_{S,i} - \bar z_S) - (z_{T,i} - \bar z_T)}{K\,T^2} \;\propto\; \frac{1}{T^2}

gradient ของพจน์ soft สเกลตาม 1/T21/T^2 ขณะที่พจน์ hard CE ไม่ขึ้นกับ TT เลย ถ้าไม่คูณ T2T^2 คืน การขยับ T จาก 1 เป็น 4 จะเท่ากับแอบหาร learning rate ของพจน์ soft ด้วย ~16 คุณจะสรุปว่า "T สูงแล้วไม่เวิร์ก" ทั้งที่จริง ๆ คุณแค่เผลอปิด soft loss ของตัวเองไปเฉย ๆ การคูณ T2T^2 ทำให้สเกลของ gradient แทบไม่ขึ้นกับ T — ค่า α\alpha ที่จูนไว้จึงมีความหมายเดิมทุก T

ของแถมจากบรรทัดที่ 2: ในลิมิตเดียวกัน soft loss ลดรูปเป็นการ match logits ที่ถูก center แบบ MSE — KD คือ "logit regression แบบนุ่ม" ที่ให้น้ำหนักส่วนหัวของ distribution มากกว่าส่วนหาง

3.3 SeqKD — baseline ราคาถูก (Kim & Rush, 2016)

LSeqKD=Ey^πT[tlogπS(y^tx,y^<t)]\mathcal{L}_{\text{SeqKD}} = -\,\mathbb{E}_{\hat y \sim \pi_T}\left[\sum_t \log \pi_S(\hat y_t \mid x, \hat y_{<t})\right]

อ่านแล้วคุ้นไหมครับ — นี่คือ SFT ธรรมดาบนคำตอบที่ครู generate ไม่มีอะไรมากกว่านั้น แทนที่จะส่ง distribution ทั้งก้อน ครูส่ง "ตัวอย่างหนึ่งตัว" ที่สุ่มจาก distribution ของตัวเองมาให้

ข้อดีที่มักถูกมองข้าม: SeqKD ไม่สนใจว่า tokenizer ตรงกันหรือไม่ เพราะมันส่งข้อความ ไม่ได้ส่ง logits โมเดล open-source จำนวนมากที่โฆษณาว่า "distilled from GPT-4" แท้จริงคือ SeqKD ล้วน ๆ — เก็บคำตอบครูผ่าน API แล้ว SFT นี่คือเหตุผลที่มันเป็น baseline ที่เราต้องวัดให้ได้ก่อนไปวิธีที่แพงกว่า

3.4 GKD และ generalized JSD — เส้นที่เชื่อมบทนี้กับบทที่ 6

Logit KD ตามสมการ 3.1 มีจุดอ่อนเชิงโครงสร้าง: นักเรียนเรียนบนประโยคที่คนอื่นเขียน (teacher forcing) แต่ตอนใช้งานจริงมันต้อง generate ต่อจากคำตอบของตัวเอง — ความคลาดเคลื่อนสะสมนี้เรียกว่า exposure bias GKD (Agarwal et al., 2023) แก้ด้วยการให้นักเรียนสุ่มคำตอบเอง แล้วครูให้คะแนนบน token เหล่านั้น พร้อมทั้ง generalize ระยะทางระหว่าง distribution เป็น:

DJSD(β)(PQ)=βDKL(PM)+(1β)DKL(QM),M=βP+(1β)Q\mathbb{D}^{(\beta)}_{\text{JSD}}(P\,\|\,Q) = \beta\,\mathbb{D}_{\text{KL}}(P\,\|\,M) + (1-\beta)\,\mathbb{D}_{\text{KL}}(Q\,\|\,M), \qquad M = \beta P + (1-\beta) Q

โดย PP = ครู, QQ = นักเรียน ค่า β\beta กวาดจากขั้วหนึ่งไปอีกขั้วหนึ่ง:

  • β0\beta \to 0forward KL DKL(PQ)\mathbb{D}_{\text{KL}}(P\|Q) — mass-covering: นักเรียนต้องแผ่คลุมทุกโหมดของครู
  • β1\beta \to 1reverse KL DKL(QP)\mathbb{D}_{\text{KL}}(Q\|P) — mode-seeking: นักเรียนเลือกยึดบางโหมดที่ตัวเองไหว

พูดให้ชัดที่สุด: reverse KL ที่บทที่ 6 เลือกใช้ ไม่ใช่ของแปลกจากอีกโลก — มันคือจุด β=1\beta = 1 บนเส้นเดียวกันนี้ ส่วน KD คลาสสิกของ Hinton คือจุด β=0\beta = 0 สองบทนี้จึงเป็นสมาชิก ครอบครัวเดียวกันที่ต่างกันแค่ว่า "ใครต้องขยับเข้าหาใคร" — นักเรียนที่เล็กกว่าครูมากมัก ได้ประโยชน์จากฝั่ง mode-seeking เพราะความจุไม่พอจะคลุมทุกโหมดของครูอยู่แล้ว

เนื้อหาเต็มอยู่ในคอร์ส

บทความนี้คือประมาณ 30% แรกของบทเรียน — ส่วนที่เหลือ (การเตรียมสภาพแวดล้อม, การเตรียมข้อมูล, โค้ดหลัก, ผลลัพธ์จริง และบทสรุป) อยู่ในคอร์ส LLM Finetuning ซึ่งเรียนฟรี เพียงเข้าสู่ระบบด้วย Google

อ่านเนื้อหาเต็มในคอร์ส →