今天來看看 DPO 的訓練流程吧!
回顧一下 DPO 的目標,訓練一個 Agent,讓它不只是「會回答問題」,而是更懂得什麼樣的回答才是我們真正想要的。
程式會先打開 dpo_tra_prefdata_v2.json,裡面存放的是我們事先整理好的偏好資料(Preference Data)。每一筆資料都在告訴模型:「這兩個答案之中,我比較喜歡哪一個?」
接著,這些 JSON 資料會被轉換成 Hugging Face 的 Dataset,準備送進訓練流程。
有了教材,接下來就有請我們的模型——Llama 3.1 8B Instruct。
程式先載入 Tokenizer,並把 padding token 設定成 eos token,確保文字在進入模型時能被正確處理。接著載入 8B 模型,使用 bfloat16 降低記憶體需求,再透過 device_map="auto",讓模型自動分配到可用的硬體資源上。
但問題來了:8B 模型可不小,如果真的把整個模型都拿來訓練,VRAM 很快就會吃不消。
這次設定 r=16、lora_alpha=32,主要調整 q_proj 和 v_proj。意思是:我們不需要重新訓練整個 Llama,而是在模型旁邊加上一小組可以學習的參數。
如此一來,訓練需要更新的參數大幅減少,也就能省下大量 VRAM。
Reference Model,用來判斷模型現在的行為到底偏離原本模型多少
一般來說,這代表可能需要額外放一份模型在 GPU 裡。
但在這個設定下,TRL 的 DPOTrainer 可以利用 adapter 的方式處理 Reference Model,不需要真的再完整複製一份 8B 模型,因此進一步降低記憶體負擔。
現在,學生(模型)、教材(偏好資料)和老師(Reference Model)都準備好了。
建立 DPOTrainer,設定 DPO 的核心參數,例如 beta=0.1,用來控制模型遵循偏好資料與不要偏離原始模型之間的平衡;學習率設定為 5e-6,並限制最多訓練 50 個 steps。
同時,訓練過程會把 Log 紀錄到 TensorBoard。
之後可以觀察 Loss、Reward 等數據,看看模型到底有沒有逐漸學會我們想要的行為。
一切準備完成後,真正的訓練就從:trainer.train() 開始。
最後還會記錄下 GPU 的峰值記憶體以及開始時間。等訓練結束後,再計算總耗時,並把 GPU 型號、訓練時間與最高 VRAM 使用量通通印出來。
最後,經過 DPO 訓練的 Agent 就會被保存到:./dpo_agent_final
一趟從偏好資料 → 模型 → LoRA → DPO 訓練 → 硬體監控 → 最終 Agent的旅程就完成了。
DPO 有趣的地方:我們沒有直接告訴模型「你應該怎麼回答」,而是透過大量「這個答案比那個答案好」的選擇,讓模型逐漸學會人類偏好的方向。
明天會探討Agent 的部署,又會遇到什麼難題呢?