[LLM 4/10] DPO: เมื่อโมเดลภาษากลายเป็น reward model ของตัวเอง
บทที่แล้วเราทำ RLHF ด้วย PPO และคุณคงเห็นแล้วว่ามันมีชิ้นส่วนเยอะแค่ไหน — ต้องเทรน reward model แยกหนึ่งตัว ต้องโหลดโมเดลพร้อมกัน 4 ตัวใน VRAM ต้องจูน PPO อีกสิบกว่าพารามิเตอร์ และถ้า reward model เพี้ยน โมเดลจะไปเจอทางลัดที่โกงคะแนนได้ บทนี้เราจะทำสิ่งเดียวกันด้วยลูป training ธรรมดาแบบ supervised — ไม่มี reward model ไม่มี RL และที่สำคัญคือ มันไม่ใช่การประมาณ เราจะพิสูจน์ด้วยพีชคณิตว่าทั้งสองชิ้นนั้นตัดกันหายไปจริง ๆ
Open in Colab04_dpo.ipynb
1. ปัญหา (Problem statement)
สมมติคุณอยากให้ผู้ช่วย AI ของคุณ "ตอบเป็นภาษาไทยเสมอ" — ฟังดูง่าย แต่ลองเขียนเป็น loss function ดูสิครับ คุณจะเขียนไม่ออก
นี่คือปัญหาแกนกลางของ alignment: คุณภาพของคำตอบ เขียนเป็นสมการไม่ได้ "สุภาพกว่า" "เป็นธรรมชาติกว่า" "ไม่หลุดไปเป็นภาษาอังกฤษ" — ไม่มีเฉลยเดียวที่ถูกต้อง มีแต่การเปรียบเทียบ ให้คนดูคำตอบสองอันแล้วบอกว่าชอบอันไหนมากกว่า ข้อมูลที่ได้จึงมีหน้าตาเป็นสามสิ่ง: prompt , คำตอบที่ชอบ (chosen), คำตอบที่ไม่ชอบ (rejected)
RLHF แบบ PPO แก้ปัญหานี้ด้วยการเดินอ้อมสองขั้น:
- เทรน reward model ให้เลียนแบบความชอบของมนุษย์
- ใช้ RL ดัน policy ไปหาคะแนนสูง ๆ ของ reward model นั้น
การเดินอ้อมนี้มีราคา:
| ปัญหาของ RLHF/PPO | ผลที่เกิดขึ้นจริง |
|---|---|
| ต้องเทรนโมเดลเพิ่ม 1 ตัว | เพิ่มขั้นตอน เพิ่มโอกาสพัง เพิ่มเวลา |
| ต้องโหลด 4 โมเดลพร้อมกัน | policy + ref + reward + value — VRAM บาน |
| reward hacking | โมเดลหาช่องโกงคะแนน โดยที่มนุษย์ไม่ได้ชอบขึ้นเลย |
| PPO ไวต่อ hyperparameter | รันสองรอบด้วย seed ต่างกัน อาจได้ผลคนละเรื่อง |
คำถามของบทนี้จึงเป็นคำถามเดียวสั้น ๆ: เราข้ามขั้นที่ 1 กับ 2 ไปเลยได้ไหม
2. เราจะทำอะไร (Solution)
คำตอบคือได้ และเหตุผลสวยมาก
จุดเริ่มคือข้อสังเกตว่า objective ของ RLHF ที่มี KL constraint นั้น มีคำตอบในรูปปิด (closed form) เรารู้อยู่แล้วว่า policy ที่ดีที่สุดหน้าตาเป็นอย่างไร โดยไม่ต้องรัน RL เลยแม้แต่ step เดียว เมื่อรู้แบบนั้น เราก็พลิกสมการกลับด้าน — แทนที่จะถามว่า "reward นี้ให้ policy อะไร" เราถามว่า "policy นี้แปลว่า reward เท่าไหร่"
เมื่อพลิกสมการ ตัวโมเดลภาษาเองก็คือ reward model อยู่แล้วโดยปริยาย
reward model กับ RL loop ไม่ได้ถูก "ประมาณทิ้ง" แต่มันตัดกันหายไปทางพีชคณิต
สิ่งที่เหลือคือ loss function แบบ supervised ธรรมดาที่เทรนด้วย Trainer ตัวเดียวจบ
นี่คือ DPO (Direct Preference Optimization) ซึ่งเสนอโดย Rafailov และคณะ (2023) ชื่อ "Direct" มาจากการที่เรา optimize บนข้อมูล preference โดยตรง ไม่ผ่านตัวกลาง
3. สมการ (Equation)
3.1 ตั้งโจทย์: RLHF objective
อ่านเป็นภาษาคน: "ทำคะแนน reward ให้สูงที่สุด แต่ห้ามเดินห่างจากโมเดลตั้งต้นมากเกินไป"
- = policy คือโมเดลที่เรากำลังเทรน
- = reference policy คือโมเดลตั้งต้น (ในบทนี้คือโมเดลหลัง SFT จากบทที่ 2)
- = reward ของคำตอบ ต่อ prompt
- = ความเข้มของสายจูง ยิ่งมากยิ่งดึงกลับหา แรง
พจน์ KL ไม่ใช่ของประดับ ถ้าไม่มีมันโมเดลจะวิ่งหนีไปหาจุดที่ reward สูงแต่ภาษาพัง
3.2 ขั้นที่ 1 — คำตอบในรูปปิด
โจทย์ข้างบนนี้แก้ได้ด้วยมือ (เป็นการหา distribution ที่ minimize KL ต่อ distribution เป้าหมาย) ได้ผลว่า
- คือ partition function ตัวหารที่ทำให้ผลรวมเป็น 1
- สังเกตว่า ขึ้นกับ เท่านั้น ไม่ขึ้นกับ — จำประโยคนี้ไว้ให้ดี เดี๋ยวมันจะกลายเป็นพระเอก
ความหมายเชิงสัญชาตญาณ: policy ที่ดีที่สุดคือ โมเดลเดิม ถ่วงน้ำหนักใหม่ด้วย คำตอบที่ reward สูงถูกขยายความน่าจะเป็น คำตอบที่ reward ต่ำถูกกด แต่ตั้งต้นจากรูปร่างเดิมของ เสมอ
ในทางปฏิบัติเราคำนวณ ไม่ได้ เพราะต้องรวมทุกคำตอบที่เป็นไปได้ทั้งจักรวาล นี่คือเหตุผลที่คนใช้ RL — และเป็นเหตุผลที่ DPO ไม่ต้องใช้
3.3 ขั้นที่ 2 — พลิกสมการหา reward
ใส่ log ทั้งสองข้างแล้วย้ายข้าง จะได้
บรรทัดนี้คือหัวใจ reward ทุกฟังก์ชันเขียนใหม่ได้ในรูปของ policy ที่ optimal กับ policy ตั้งต้น แปลว่าถ้าเรามีโมเดลสองตัว เราคำนวณ reward โดยปริยายของมันได้ทันที โดยไม่ต้องเทรน reward model ใด ๆ
3.4 ขั้นที่ 3 — แทนใน Bradley-Terry แล้ว ตัดหาย
โมเดลมาตรฐานของความชอบคือ Bradley-Terry: โอกาสที่คนจะเลือก เหนือ คือ
โดย คือ sigmoid สังเกตว่าในสมการนี้ reward ปรากฏในรูป ผลต่าง เท่านั้น แทนสมการ 3.3 ลงไป — อยู่ทั้งสองฝั่งเท่ากันเป๊ะเพราะ ตัวเดียวกัน — มันจึงตัดกันหายไป
สิ่งที่คำนวณไม่ได้ () ตัดหายไป เพราะ Bradley-Terry สนใจแค่ผลต่างของ reward ที่เหลือคือ log-probability ของโมเดลสองตัวบนข้อความที่เรามีอยู่แล้ว ซึ่งคำนวณด้วย forward pass ธรรมดา ไม่มีการสุ่มคำตอบ ไม่มี rollout ไม่มี value function — DPO เป็น supervised learning เต็มตัว
3.5 Gradient — ที่ซึ่งสัญชาตญาณอยู่
โดย เรียกว่า implicit reward (reward โดยปริยาย)
อ่านทีละชิ้น:
- วงเล็บขวา = ทิศทาง ดัน log-prob ของ ขึ้น และกด log-prob ของ ลง พร้อมกัน
- = น้ำหนัก คือ "โมเดลจัดอันดับคู่นี้ผิดแค่ไหน"
น้ำหนักตัวนี้คือจุดสอนที่สำคัญที่สุด ถ้าโมเดลจัดอันดับคู่นี้ถูกอยู่แล้ว ( มากกว่า ชัดเจน) ค่า จะเข้าใกล้ศูนย์ และคู่นั้นแทบไม่ส่ง gradient เลย DPO จึงโฟกัสไปที่ความผิดพลาดของตัวเองโดยอัตโนมัติ ไม่ต้องมีใครมาคัดข้อมูลให้
บทความนี้คือประมาณ 30% แรกของบทเรียน — ส่วนที่เหลือ (การเตรียมสภาพแวดล้อม, การเตรียมข้อมูล, โค้ดหลัก, ผลลัพธ์จริง และบทสรุป) อยู่ในคอร์ส LLM Finetuning ซึ่งเรียนฟรี เพียงเข้าสู่ระบบด้วย Google
อ่านเนื้อหาเต็มในคอร์ส →