TL;DR
- LLMã®æé©åææ³ã§ããDPOãšãã®æŽŸçææ³ (IPO, cDPO, RSO, KTO) ã«ã€ããŠè§£èª¬ãã
- trlã©ã€ãã©ãªãšLoRAãçšããŠããããã®ææ³ã§æ¥æ¬èªLLMãæé©åããæ§èœãå®éçã«æ¯èŒãã
- 3.6Bãã©ã¡ãŒã¿ã®LLMãVRAM40GBã®GPU1æã§å šãã©ã¡ãŒã¿ãDPOã§åŠç¿ããæ¹æ³ã説æãã
ã¯ããã«
Direct Policy Optimazation (DPO)ã¯å€§èŠæš¡èšèªã¢ãã«(LLM)ã®æåãå¶åŸ¡ããããªã·ãŒæé©åïŒæèã«ãã£ãŠã¯ã¢ã©ã€ã¡ã³ããšãåŒã°ããŸãïŒã®ããã®åŠç¿ææ³ã§ã匷ååŠç¿ãçšããProximal Policy Optimization (PPO)ã«ä»£ãããã®ãšããŠæè¿æ³šç®ãéããŠããŸãã
PPOã«é¢ããŠã¯ããã¡ã
ã®èšäºã§è©ŠããŠã¿ãŸããã®ã§ãä»åã¯ãã®ç¶ããšããŠãDPOãšãã®æŽŸçææ³ã䜿ã£ãŠæ¥æ¬èªLLMããã¡ã€ã³ãã¥ãŒãã³ã°ããŠã¿ãŸããåŠç¿ã«ã¯trlã©ã€ãã©ãªã®DPOTrainerã䜿çšããŸããååãšåæ§ã«ãæç€ºæã®äžã§èªå°Ÿãæå®ããããã«åŸã£ãŠè¿çã§ããããšããåçŽãªã¿ã¹ã¯èšå®ãæ±ãããšã§ãææ³ã®ç°¡äŸ¿ãªå®éè©äŸ¡ã詊ã¿ãŸãã
ããªã·ãŒæé©åææ³è§£èª¬
ãŸãåãã«ãtrlã©ã€ãã©ãªã§çŸåšäœ¿çšå¯èœãªææ³ãäžå¿ã«åçš®ã®ããªã·ãŒæé©åææ³ã«ã€ããŠè§£èª¬ããŸãã
RLHF
GPT-3.5ãªã©ã®LLMã®åŠç¿ã¯ä»¥äžã®ïŒæ®µéã§è¡ãããŠããŸãã
- Pre-traininig: å€§èŠæš¡ãªã³ãŒãã¹ãçšããèšèªã¢ãã«ã®äºååŠç¿
- Supervised Fine Tuning (SFT): 察話圢åŒãæç€ºã»å¿ç圢åŒã®ããŒã¿ã»ãããçšãããã¡ã€ã³ãã¥ãŒãã³ã°
- Policy Optimization: 人éã«ãšã£ãŠå¥œãŸããå¿çããããããã®ãã¡ã€ã³ãã¥ãŒãã³ã° (Reinforcement Learning with Human Feedback; RLHF)
3段éç®ã®ããªã·ãŒæé©åã¯ãSFTãšã¯ç°ãªããå ¥åã«å¯ŸããŠæ±ºãŸã£ãæ£è§£ãäžããããã§ã¯ãªããLLMã®å¿çã«å¯ŸããŠäœããã®è©äŸ¡ãè¿ããŠãè©äŸ¡ãé«ããªãããã«LLMã®ãã©ã¡ãŒã¿ãæŽæ°ãããšãããã®ã§ãã
ããªã·ãŒæé©åã®æé©å颿°ã¯æ¬¡ã®ãããªãã®ã§ãã
\underset{\pi_\theta}{\text{max}}\big\{ \mathbb{E}_{x\sim \mathcal{D}, \, y\sim \pi_\theta (\cdot|x)} \left[ r(x,y)\right]
-\beta \mathbb{D}_\text{KL} \left[ \pi_\theta (y|x) || \pi_\text{ref} (y|x)\right]\big\}
\tag{1}
åèšå·ã®æå³ã¯ä»¥äžã®éãã§ãã
- $x\,$: å ¥åæïŒããã³ããïŒ
- $\mathcal{D}\,$: å ¥åæã®ããŒã¿ã»ãã
- $y\,$: å¿çæ
- $\pi_\theta (y|x)\,$: åŠç¿å¯Ÿè±¡ã®LLMãå ¥åæ$x$ãäžãããããšãã«å¿çæ$y$ãçæãããæ¡ä»¶ä»ç¢ºçã
- $\theta\,$: åŠç¿ã§æŽæ°ããããã©ã¡ãŒã¿
- $\pi_\text{ref} (y|x)\,$: åç §ã¢ãã«
- $r(x,y)\,$: å ¥åæ$x$ãšå¿çæ$y$ã«å¯Ÿããè©äŸ¡ïŒå ±é ¬ïŒé¢æ°
- $\mathbb{E}_{x\sim \mathcal{D}, \, y\sim \pi_\theta (\cdot|x)}\,$: $\mathcal{D}$ãããµã³ãã«ãã$x$ãš$\pi_\theta (\cdot|x)$ãããµã³ãã«ãã$y$ã«å¯ŸããæåŸ å€
- $\mathbb{D}_\text{KL} \left[ \pi_\theta (y|x) || \pi_\text{ref} (y|x)\right]\,$: $\pi_\theta (y|x)$ãš$\pi_\text{ref} (y|x)$ã$y$ã«é¢ãã確çååžãšã¿ãªããæã®ãäž¡è ã®KLãã€ããŒãžã§ã³ã¹
- $\beta\,$: æ£ã®ãã€ããŒãã©ã¡ãŒã¿
è©äŸ¡ã»å ±é
¬é¢æ°$r(x,y)$ãšããŠã¯ã人éããã®ãã£ãŒãããã¯ãªã©ã®ããŒã¿ã»ããã䜿ã£ãŠåŠç¿ããå¥ã®ã¢ãã«ã䜿ãããããšãå€ãã§ãã
(1)åŒã«ããã$r$ã®æåŸ
å€ã®é
ã®æå³ã¯ãLLMãçæããçµæã®è©äŸ¡ã»å ±é
¬ãé«ããªãããã«LLMãæé©åãããšããããšã§ããããããããã ãã ãšè©äŸ¡ãé«ããããã®æãéãååšããå Žåãææ³çã«ã¯ãã¡ããã¡ãã ãã©è©äŸ¡ã ãã¯é«ããšãããããªããã¹ãã®çæãè¡ãããã«åŠç¿ãé²ãã§ããŸãã®ã§ããããé²ãããã«ç¬¬2é
ã®KLãã€ããŒãžã§ã³ã¹ãå ããããŠããŸãã
KLãã€ããŒãžã§ã³ã¹ã¯ïŒã€ã®ååžã®éã®è·é¢ãäžãããã®ã§ãååžãäžèŽããã°0ãç°ãªã£ãŠããã°æ£ã®å€ãåããŸãããããã£ãŠãåŠç¿å¯Ÿè±¡ã®LLM $\pi_\theta (y|x)$ãšåç
§ã¢ãã« $\pi_\text{ref} (y|x)$ã®çæç¢ºçã®ååžãéãéãããšã第2é
ã®çµ¶å¯Ÿå€ã倧ãããªãããã«ãã£ãäžãããããšããããšã«ãªããŸããåç
§ã¢ãã«ãšããŠèªç¶ãªæç« ãçæã§ãããããªã¢ãã«ã䜿ãã°ãåŠç¿ããã¢ãã«ã¯èªç¶ãªæç« ãçæããèœåãä¿æããªããå ±é
¬ãé«ãæ¯ãèããããããã«ãªããŸãã
KLãã€ããŒãžã§ã³ã¹ã®é ãå ·äœçã«æžããšã
\mathbb{D}_\text{KL} \left[ \pi_\theta (y|x) || \pi_\text{ref} (y|x)\right]
= \mathbb{E}_{x\sim \mathcal{D},\, y\sim \pi_\theta (\cdot|x)} \left[ \log \frac{\pi_\theta (y|x)}{\pi_\text{ref} (y|x)}\right]
\tag{2}
ãšãªããŸããïŒ$x$ã«å¯ŸããæåŸ å€ã¯ããã«ã¯å«ããªãã®ãèªç¶ãªå®çŸ©ã§ããã(1)åŒãç°¡æœãã€ãããèŠã衚åŒã«åãããããããã®ããã«å®çŸ©ããŠãããŸããïŒ
ããŠã(1)åŒã¯$\pi_\theta (y|x)$ãããµã³ãã«ããå¿çæ$y$ã«å¯ŸããæåŸ å€ãšããŠæžãããŠããŸãããå ·äœçãªããŒã¯ã³åãšããŠãµã³ãã«ããæç¹ã§ã¢ãã«ãã©ã¡ãŒã¿$\theta$ã§åŸ®åããããšã¯ã§ããªããªã£ãŠããŸããŸãããããã£ãŠã深局åŠç¿ã¢ãã«ã®åŠç¿ã§éåžžè¡ããããæé©å颿°ïŒæå€±é¢æ°ïŒã®ã¢ãã«ãã©ã¡ãŒã¿ã«ã€ããŠã®åŸ®åãéèª€å·®äŒæã§æ±ããŠãã©ã¡ãŒã¿ãæŽæ°ãããšããææ³ã¯é©çšã§ããã匷ååŠç¿ã®ææ³ãç¹ã«PPOãçšããæé©åãè¡ãããã®ãäž»æµã§ããã
PPOã¯OpenAIã®LLMã®åŠç¿ã«äœ¿ãããŠãã匷åãªææ³ã§ã¯ãããŸãããèšç®ã³ã¹ãã®é«ããïŒç¹ã«å€§ããªã¢ãã«ã«å¯ŸããïŒåŠç¿ã®äžå®å®ããªã©ã®èª²é¡ããããå®è¡ããã®ã¯æ·å± ãé«ãææ³ã§ããã
PPOã¯trlã©ã€ãã©ãªã«PPOTrainerãšããŠå®è£ ãããŠããŸãããååã®èšäºã§è©ŠããŠã¿ããšããã確ãã«èšç®ã³ã¹ããé«ããåŠç¿ã«é·ãæéãèŠããŸããã
DPO
DPOã¯PPOã«ä»£ããããªã·ãŒæé©åææ³ãšããŠ2023幎5æã«çºè¡šãããææ³ã§ã匷ååŠç¿ãçšããéåžžã®æåž«ããåŠç¿ãšåããããªæé ã§(1)åŒã®æé©åãè¡ãããšãããã®ã§ãã
ãã®ããã«RLHFã®åé¡èšå®ã«å ããŠããã€ãã®ä»®å®ã眮ããŸããRLHFã«ãããŠã¯å ±é ¬é¢æ°$r(x,y)$ã®ã¢ããªã³ã°ã«å¯ŸããŠã¯äœã®ä»®å®ãããŠããªãã£ãã®ã§ãããDPOã§ã¯Bradley-Terryã¢ãã«ã«ããå®åŒåãããŠãããšä»®å®ããŸãã
p^{\ast} (y_1 \succ y_2 |x) = \frac{\exp \!\left[ r(x, y_1) \right]}{\exp \!\left[ r(x, y_1) \right] + \exp \!\left[ r(x, y_2) \right]}
\tag{3}
ããã§ã $p^{\ast} (y_1 \succ y_2 |x)$ã¯å
¥åæ$x$ã«å¯Ÿããå¿çã2ã€äžãããããšãããã®ãã¡$y_1$ã®æ¹ã奜ãŸãã確çãæå³ããŠããŸãããã® $p^{\ast} (y_1 \succ y_2 |x)$ãå³èŸºã®è¡šåŒã§å ±é
¬é¢æ°$r(x,y)$ãéããŠè¡šçŸããããšããã®ãä»®å®ã§ããèŠããã«å ±é
¬$r$ãé«ãå¿çã®æ¹ã奜ãŸãããšå€å®ããããšããããšãªã®ã§ãèªç¶ãªã¢ããªã³ã°ã§ããå³èŸºã¯ã·ã°ã¢ã€ã颿°$\sigma (x)$ãçšããŠã$\sigma \left(r(x, y_1) - r(x, y_2)\right)$ãšæžãããšãã§ããŸãã
ããŠããã®ã¢ãã«ãåŠç¿ãããããã«ãå
¥åæ$x$ãšå¥œãŸããå¿ç$y_w$ã奜ãŸãããªãå¿ç$y_l$ããæãããŒã¿ã»ãã$\mathcal{D}_\text{pair} = \big\{ x^{(i)}, y_w^{(i)}, y_l^{(i)}\big\}_{i=1}^N$ããããšããŸããæ·»ãåã®$w$ã¯winã$l$ã¯loseã®é æåã§ãã
å ±é
¬é¢æ°ãåŠç¿ããããã®æé©å颿°ã¯éåžžã®ã·ã°ã¢ã€ãæå€±ã§
L_\text{reward} = -\mathbb{E}_{(x,y_w, y_l)\sim \mathcal{D}_\text{pair}} \log \sigma \!\left(r(x, y_w) - r(x, y_l)\right)
\tag{4}
ãšæžããŸãã
DPOã®æ žãšãªãã¢ã€ãã£ã¢ã¯ããã®å ±é ¬é¢æ°ã®æé©å颿°(4)ãLLMã®æé©å颿°ã«çœ®ãæããŠããŸããšããããšã§ãããã®ããã«ãå ã®LLMã®ããªã·ãŒæé©åã®ããã®æé©å颿°(1)ã«ã¯å³å¯è§£
\pi (y|x) = \frac{1}{Z(x)} \pi_\text{ref} (y|x) \exp \left( \frac{1}{\beta} r(x,y)\right)
\tag{5}
ãååšããããšã䜿ããŸãã$Z(x)=\sum_y \pi_\text{ref} (y|x) \exp \left( \frac{1}{\beta} r(x,y)\right)$ã¯èŠæ Œåã®ããã®åé
颿°ã§ãã1
ãã®è§£ãå®éã«æé©å颿°(1)ãæå€§åããããšã®èšŒæã¯DPOè«æã®Appendixã«äžããããŠããŸãã
å³å¯è§£ãååšãããªããããããPPOãDPOã®ã¢ã«ãŽãªãºã ã工倫ããŠæã®ãããæ°å€èšç®ãè¡ããªããŠãããã®ã§ã¯ãšæã人ããããããããŸããããããã¯ãããŸã§åœ¢åŒè§£ã§ãã£ãŠãå®çšã«ã¯åããŸãããçç±ã¯åé 颿°$Z(x)$ãããããå¿çããã¹ã$y$ã®åã§äžããããŠããããããããèšç®ããããšã¯çŸå®çã§ã¯ãªãããã§ããæ£åŽãµã³ããªã³ã°æ³ãªã©ã®ææ³ã䜿ãã°èŠæ Œå宿°ãããããªã確çååžããã®ãµã³ããªã³ã°ãå¯èœã§ãããç³»åããŒã¿ã§ãã$y$ãçæãããšããä»ã®åé¡èšå®ã§ã¯ãããé£ãããšæããŸãã
DPOå°åºã®æ¬¡ã®éèŠãªã¹ãããã¯ã(5)åŒã$r$ã«ã€ããŠè§£ãããšã§ãã
r(x,y) = \beta \log \frac{\pi (y|x)}{\pi_\text{ref} (y|x)} + \beta \log Z(x)
\tag{6}
ãã§ã«è¿°ã¹ãããã«åé 颿°$Z(x)$ã¯å®éã«ã¯èšç®ã§ããªãæªç¥ã®é¢æ°ãªã®ã§ããããã®(6)åŒãå ±é ¬é¢æ°ã®æé©å颿°(4)ã«ä»£å ¥ãããšã$Z(x)$ããã£ã³ã»ã«ããŠæ¶ããŠããŸããŸãã
L_\text{reward} = -\mathbb{E}_{(x,y_w, y_l)\sim \mathcal{D}_\text{pair}} \log \sigma \!\left(\beta \log \frac{\pi (y_w|x)}{\pi_\text{ref} (y_w|x)} - \beta \log \frac{\pi (y_l|x)}{\pi_\text{ref} (y_l|x)}\right)
\tag{7}
ãã®æé©å颿°ã¯LLMã®ã¿ã§è¡šçŸãããŠããŸãã®ã§ãLLMãåŠç¿ããããã®æå€±é¢æ°ãšã¿ãªãããšãã§ããŸãããããæç¢ºã«ããããã$\pi$ãåŠç¿å¯Ÿè±¡ã®LLM $\pi_\theta$ã§çœ®ãæãããã®ã$L_\text{DPO}$ãšåŒã¶ããšã«ããŸãããã
L_\text{DPO} = -\mathbb{E}_{(x,y_w, y_l)\sim \mathcal{D}_\text{pair}} \log \sigma \!\left(\beta \log \frac{\pi_\theta (y_w|x)}{\pi_\text{ref} (y_w|x)} - \beta \log \frac{\pi_\theta (y_l|x)}{\pi_\text{ref} (y_l|x)}\right)
\tag{8}
奜ãŸããå¿çãããå°€åºŠïŒæ£ç¢ºã«ã¯åç
§ã¢ãã«ãšã®å¯Ÿæ°å°€åºŠæ¯ïŒãé«ãã奜ãŸãããªãå¿çã®å°€åºŠãäœãããããšããæå€±é¢æ°ãšãªã£ãŠããŸãã
ãã®æå€±é¢æ°ã¯åç
§ã¢ãã«ã«ãäŸåããŠãããšããç¹ãé€ãã°ãéåžžã®æåž«ããåŠç¿ã®æå€±é¢æ°ãšåæ§ã®åœ¢åŒã§ãããSFTãšåãèŠé ã§åŠç¿ãè¡ãããšãã§ããŸãã
DPOã¯trlã©ã€ãã©ãªã®DPOTrainerã§loss_type="sigmoid"ïŒããã©ã«ãèšå®ïŒãšããããšã§ç°¡åã«äœ¿ãããšãã§ããŸããå ·äœçãªæ¹æ³ã¯åŸãã説æããŸãã
IPO (ΚPO)
DPOã¯å ±é
¬é¢æ°ã®æºåãšåŒ·ååŠç¿ã®å®è¡ã®äž¡æ¹ãäžèŠã«ããç»æçãªææ³ã§ãããåŠç¿ããŒã¿ã«éé©åãããããšããåé¡ãææãããŠããŸããã
Google DeepMindã®è«æ "A General Theoretical Paradigm to Understand Learning from Human Preferences"ã§ã¯ãDPOãäžè¬åããΚPOãå°å
¥ããããã§ãDPOãéé©åããããåå ãæããã«ããΚPOã®ç¹æ®ã±ãŒã¹ãšããŠIPOãææ¡ããŠããŸãã
ãŸãã$\Psi (x)$ãšããå®çŸ©åã$[0,1]$ã§ããéæžå°å®é¢æ°ãèããŸãããã®é¢æ°ã䜿ã£ãŠã(1)åŒã§äžããããPPOããã³DPOã®æé©åç®ç颿°ã次ã®ããã«äžè¬åããŸãã
\underset{\pi_\theta}{\text{max}}\big\{ \mathbb{E}_{x\sim \mathcal{D},\, y \sim \pi_\theta (\cdot|x),\, y^\prime \sim \mu (\cdot|x)} \left[ \Psi \left( p^{\ast} (y \succ y^\prime |x)\right)\right]
-\beta \mathbb{D}_\text{KL} \left[ \pi_\theta (y|x) || \pi_\text{ref} (y|x)\right]\big\}
\tag{9}
ããã§ã$\mu (y^\prime|x)$ã¯$\pi_\theta (y|x)$ãšã¯ç°ãªãäœããã®LLMïŒããæ£ç¢ºã«ã¯$y^\prime$ãçæããäœããã®ããªã·ãŒïŒã§ãã$p^{\ast}$ã¯(3)åŒã§äžããããBradley-Terryã¢ãã«ã§ãã第1é
ã®æåŸ
å€ã®äžèº«ã®$\Psi \left( p^{\ast} (y \succ y^\prime |x)\right)$ã¯å ±é
¬$r(x,y)$ã«é¢ããå¢å 颿°ã§ãã®ã§ãäžåŒã¯KLé
ã®å¶çŽã®äžã§å ±é
¬ãæå€§åãããšããæå³ã§(1)åŒãšç®çã¯åãã§ããã颿°$\Psi$ãèªç±ã«å€ãããããšããæå³ã§(1)åŒã®äžè¬åãšãªã£ãŠããŸãã
å®éã$\Psi (x) = \log \frac{x}{1-x}$ïŒã·ã°ã¢ã€ã$\sigma(x)$ã®é颿°ïŒãšãããšã(9)åŒã¯$\pi_\theta$ã«äŸåããªã宿°ãé€ããŠ(1)åŒãšäžèŽããŸãã
(9)åŒã§äžããããΚPOã®æé©å颿°ã¯å ±é ¬$r(x,y)$ã«äŸåããŠããŸãã®ã§ãDPOãšéã£ãŠçŽæ¥æé©åããããšã¯ã§ããŸãããã$\Psi (x)$ã®å ·äœåœ¢ãããŸãéžãã§ãããšãçŽæ¥æé©åå¯èœãªç®ç颿°ãåŸãããŸãããããIPOã§ãããããŠãIPOã¯DPOã®éé©åãããããšããåé¡ãåé¿ãããã®ã«ãªã£ãŠããŸãã
ãŸããDPOããªãéé©åããããã®ãã説æããŸãã
DPOã§ã¯å¥œãŸããå¿ç$y_w$ãšå¥œãŸãããªãå¿ç$y_l$ãåŠç¿ããŒã¿ã«çšããŸãã®ã§ã(9)åŒã«ããã$p^{\ast} (y \succ y^\prime |x)$ã«å¯Ÿããæ£è§£ã©ãã«ã¯0ãŸãã¯1ã®å€ãåãããšã«ãªããŸãã
(3)åŒã®Bradley-Terryã¢ãã«ã¯ã·ã°ã¢ã€ã颿°ã§äžããããŠããŸãã®ã§ã$p^{\ast}=0,1$ãšãªãã®ã¯ãã·ã°ã¢ã€ãã®åŒæ°ã§ãã$r(y)-r(y^\prime)$ã$\pm \infty$ã®æã§ãããã¡ãããæ°å€èšç®äžç¡é倧ã¯çŸããŸããããããããDPOã®èšç®ã§ã¯å ±é
¬$r$ã¯å®éã«ã¯èšç®ãããŠããªãä»®æ³çãªæŠå¿µã§ãããä»®æ³çã«$|r(y)|$ãéåžžã«å€§ãããªã£ãŠããŸããšããããšã§ãããããšãDPOã®ããšããšã®æé©å颿°(1)åŒã«ãããŠã第1é
ã«æ¯ã¹ãŠç¬¬2é
ã®KLé
ãçžå¯Ÿçã«å°ãããªã£ãŠããŸããŸãããããã£ãŠãKLé
ã®æ£ååãå¹ããªããªã£ãŠãåŠç¿ããŒã¿ã«éé©åããŠããŸããšããããã§ãã
ã€ãŸããéé©åã®åå ã¯ã·ã°ã¢ã€ã颿°ã®å€åãéåºé$(0,1)$ã§ããããšã§ããåãããšã§ãããDPOã®$\Psi$颿°ã§ããã·ã°ã¢ã€ãã®é颿°$\Psi_\text{DPO} (x) = \log \frac{x}{1-x}$ã䜿ã£ãŠèª¬æãããšã$\Psi_\text{DPO} (x)$ãéæçã§ã$x\to 0, 1$ã®æã«$\Psi_\text{DPO} (x) \to \pm \infty$ãšãªãããšãåå ã§ãã
ããã§ããã®ãããªæ§è³ªãæããªãåçŽãªé¢æ°ãšããŠãæç颿° (Identity function) $\Psi (x) =x$ãçšããã®ãIPOã§ãã
ãã®$\Psi$ã(9)åŒã«ä»£å
¥ãããšãIPOã®ç®ç颿°
\underset{\pi_\theta}{\text{max}}\big\{ \mathbb{E}_{x\sim \mathcal{D},\, y \sim \pi_\theta (\cdot|x),\, y^\prime \sim \mu (\cdot|x)} \left[ p^{\ast} (y \succ y^\prime |x)\right]
-\beta \mathbb{D}_\text{KL} \left[ \pi_\theta (y|x) || \pi_\text{ref} (y|x)\right]\big\}
\tag{10}
ãåŸãããŸãããã®ãŸãŸã§ã¯ãäŸç¶ãšããŠå ±é
¬é¢æ°$r$ã«éœã«äŸåããŠããã®ã§çŽæ¥æé©åã¯ã§ããªãã®ã§ãããDPOãšåæ§ã«å³å¯è§£ãæŽçšããããšã§ãçŽæ¥æé©åã®ã¢ã«ãŽãªãºã ãå°ãããšãã§ããŸãã
å°åºã¯DPOã«æ¯ã¹ãŠè€éã§å°ãé·ããªãã®ã§çç¥ããŸããæ°ã«ãªãæ¹ã¯åè«æãåç
§ãã ãããæçµçãªæé©å颿°ã¯
L_\text{IPO} = \mathbb{E}_{(x,y_w, y_l)\sim \mathcal{D}_\text{pair}}
\left(\log \frac{\pi_\theta (y_w|x)}{\pi_\text{ref} (y_w|x)} - \log \frac{\pi_\theta (y_l|x)}{\pi_\text{ref} (y_l|x)} -\frac{1}{2\beta} \right)^2
\tag{11}
ãšãªããŸããDPOã¯ã·ã°ã¢ã€ãæå€±ã®ãããªåœ¢ã§ãã£ãã®ã«å¯ŸããŠãIPOã¯2ä¹èª€å·®ã®ãããªåœ¢ãããŠããŸãã
DPOã§ã¯ã·ã°ã¢ã€ãã®åŒæ°å
šäœãæ£ååä¿æ°$\beta$ã«æ¯äŸããŠããããã$\beta$ã®å€ã®å€§ããã«é¢ãããã奜ãŸããå¿çã®å¯Ÿæ°å°€åºŠæ¯ã倧ããã奜ãŸãããªãå¿çã®å¯Ÿæ°å°€åºŠæ¯ãå°ããããããšåŠç¿ãé²ãã®ã§ãéé©åããããã£ãã®ã§ãããIPOã§ã¯ïŒã€ã®å¯Ÿæ°å°€åºŠæ¯ã®å€ã$1/(2\beta)$ã ãé¢ããç¶æ
ãæé©ãšããã®ã§DPOãšæ¯ã¹ãŠéé©åã¯èµ·ãã«ãããšããããšã颿°åœ¢ããããããŸãã
IPOã¯DPOTrainerã§loss_type="ipo"ãšããã°äœ¿ãããšãã§ããŸãã
ã¡ãªã¿ã«ãDPOTrainerã«ãããIPOã®å®è£
ã¯æåééã£ããã®ã§ããã
ãã¡ã
Preference Tuning LLMs with Direct Preference Optimization Methods
ã®èšäºã§ã¯ãDPO, IPO, KTOã$\beta$ãã©ã¡ãŒã¿ãå€ããªããæ¯èŒããŠããã®ã§ãããæåã«å
¬éããããšãã¯IPOã®æ§èœãå£ããšããçµè«ã§ãããäžèšã®å çä¿®æ£çã®èšäºã®æåã«æžããŠããããã«ããã®åŸIPOã®å®è£
ã«ééããèŠã€ãããä¿®æ£ããŠå®éšãããçŽãããšãããIPOã¯DPOãšåçšåºŠã®æ§èœã«ãªã£ããšã®ããšã§ãã
IPOã®å®è£
ã®ééãã¯ãã¡ãã®PRã«ãããtrl==0.7.11ã§ã¯ä¿®æ£ãããŠããŸãã
cDPO
äžèšã®IPOã®è§£èª¬ã§DPOãå ±é ¬ã«éé©åããããçç±ã¯Bradley-Terryã¢ãã«ã«äžããããæ£è§£ã©ãã«ã0ã1ã§ããããšã ãšè¿°ã¹ãŸãããã€ãŸããããŒã¿ã»ããã«ãããŠå¥œãŸããå¿ç$y_w$ãšå¥œãŸãããªãå¿ç$y_l$ãã¯ã£ãããšæ±ºããããŠããããšãåå ã§ãããšèšããŸããããã§ãIPOãšã¯å¥ã®éé©åãé²ãããã®ã·ã³ãã«ãªã¢ãããŒããšããŠãã©ãã«ã«ãã€ãºãå ¥ããããšããã¡ãã®ããŒãã§ææ¡ãããŸãããåé¡åé¡ã§ããçšããããæ£ååææ³ã®ã©ãã«ã¹ã ãŒãžã³ã°ãšåãèãæ¹ã§ããcDPOã¯conservative DPOã®ç¥ã§ãã
å ·äœçã«ã¯ã©ãã«ã¹ã ãŒãžã³ã°ã®ç¢ºç$\epsilon$ãèšå®ããŠãæå€±é¢æ°ã
L_\text{DPO}^\epsilon = (1-\epsilon) L_\text{DPO} (\theta; y_w, y_l) + \epsilon L_\text{DPO} (\theta; y_l, y_w)
\tag{12}
ãšããã ãã§ãã第ïŒé ã®$L_\text{DPO} (\theta; y_w, y_l)$ã¯(8)åŒã§äžããããDPOã®æå€±é¢æ°ãã®ãã®ã§ãã第ïŒé ã®$L_\text{DPO} (\theta; y_l, y_w)$ã¯å¥œãŸããå¿çãšå¥œãŸãããªãå¿çãå ¥ãæ¿ãããã®ã§ãã
DPOTrainerã§ã¯loss_type="sigmoid"ãšããããã§ãlabel_smoothingåŒæ°ã«0ãã倧ãã0.5æªæºã®å€ãäžããããšã§äœ¿çšã§ããŸããïŒå ¬åŒããã¥ã¡ã³ãã®äžéšã«ã¯loss_type="cdpo"ãšãããšæžããŠãããŸãããçŸåšã®ããŒãžã§ã³ã§ã¯ãã®æå®ã®ä»æ¹ã¯ç¡å¹ã§ããïŒ
RSO
次ã«ãDPOTrainerã§ã䜿çšã§ããhinge lossãå°å ¥ããè«æ"Statistical Rejection Sampling Improves Preference Optimization"ã玹ä»ããŸãã
DPOã®æé©å颿°(8)ã¯çµå±ã®ãšããã奜ãŸããå¿çãšå¥œãŸãããªãå¿çã®ãã¢ã®ããŒã¿ã»ãããæºåããŠãåè ã®çæç¢ºçãé«ããåŸè ã®çæç¢ºçãäœããªãããã«æåž«ããåŠç¿ãããšãããã®ã§ããããã®ãããªçŽæ¥çãªèãã«åºã¥ããææ³ã¯DPOãããåã«ææ¡ãããŠãããSLiCã§ã¯ä»¥äžã®ãããªãã³ãžé¢æ°$\text{max}(0,x)$ã䜿ã£ãæå€±é¢æ°ã䜿ãããŠããŸãã
L_\text{SLiC} = \mathbb{E}_{(x,y_w, y_l)\sim \mathcal{D}_\text{pair}} \text{max} \left(0, \delta -\log \pi_\theta (y_w|x) + \log \pi_\theta (y_l|x) \right)
-\lambda \mathbb{E}_{(x,y_\text{ref})\sim \mathcal{D}_\text{ref}} \log \pi_\theta (y_\text{ref}|x)
\tag{13}
$\delta$ã¯æ£ã®å®æ°ã§ããŒãžã³ã衚ããŠããŸãã第ïŒé
ã¯éé©åãé²ãããã®æ£ååé
ã§éåžžã®SFTãšåãæå€±é¢æ°ã§ãã
ãã®æå€±é¢æ°ã«ã¯åç
§ã¢ãã«ãç»å Žããªã代ããã«ããã¢ããŒã¿ã»ãã$\mathcal{D}_\text{pair}$ãšéåžžã®SFTã®ããã®ããŒã¿ã»ãã$\mathcal{D}_\text{ref}$ãåæã«åŠç¿ããªããŠã¯ãªããŸããã
RSOè«æã§ã¯ãDPOã®æå€±é¢æ°ã«å¯ãã圢ãšããŠã以äžã®ãããªæå€±é¢æ°ãæå±ããŠããŸãã
L_\text{RSO} = \mathbb{E}_{(x,y_w, y_l)\sim \mathcal{D}_\text{pair}} \text{max} \left(0, 1 -\left[ \beta \log \frac{\pi_\theta (y_w|x)}{\pi_\text{ref} (y_w|x)} -\beta \log \frac{\pi_\theta (y_l|x)}{\pi_\text{ref} (y_l|x)} \right] \right)
\tag{14}
æ£ååãã©ã¡ãŒã¿$\beta$ã®éæ°ãããŒãžã³ã®åœ¹å²ãæãããŸãã
ãã®æå€±é¢æ°ã¯DPOãIPOã®ããã«å
ã®RLHFã®æé©å颿°(1)ããæ°åŠçã«å°ããããã®ã§ã¯ãªãããã¥ãŒãªã¹ãã£ãã¯ã«å°å
¥ããããã®ã§ãã
ãã®æå€±é¢æ°ã¯DPOTrainerã§loss_type="hinge"ãšããããšã§äœ¿çšã§ããŸãã
RSOè«æã®è²¢ç®ã¯ã¿ã€ãã«ãããããããã«ããã®æå€±é¢æ°ãææ¡ããããšã ãã§ã¯ãªããæ£åŽãµã³ããªã³ã°æ³ (rejection sampling)ã䜿ã£ãŠãããè¯ããã¢ããŒã¿ã»ãããéžå¥ããŠæé©åã®ããã»ã¹ãæ¹åãããšããããšã§ãã
RLHFã«ãããŠå ±é
¬ã¢ãã«ãåŠç¿ãããããã®ããŒã¿ã»ããããããã¯DPOãIPOã§çŽæ¥æé©åã«äœ¿ãããããŒã¿ã»ãã$\mathcal{D}_\text{pair}$ã®å¿çããã¹ããšããã®ã¯ã人éãæžãããã®ããäœããã®LLMãåºåãããã®ã§ãããããã®å¿çããã¹ããçæããããã®ããªã·ãŒãšããã®ã¯ãåŠç¿å¯Ÿè±¡ã®LLMãæé©åãããåŸã®ããªã·ãŒãšã¯ç°ãªããŸãããã®ã®ã£ãããåããããšããã®ãRSOã®ç®çã§ãã
ããªãã¡ãæé©åãçµãã£ãåŸã®LLMãçæããããã¹ãã«ããè¿ãããã¹ãã§LLMãåŠç¿ãããããšããããšã§ããåçŽã«èãããšãæªæ¥ã®èªåèªèº«ãçæããã§ãããããã¹ãã§çŸåšã®èªåãåŠç¿ãããšããããšã«ãªãã®ã§ç¡çãªè©±ã«æããŸããã圢åŒçãªå³å¯è§£(5)ãæŽ»çšããããšã§å¯èœã«ãªããŸãã
æé ãšããŠã¯ããŸãããŒã¿ã»ãã$\mathcal{D}_\text{pair}$ïŒè«æã§ã¯ããŒã¿ã»ãã$\mathcal{D}_\text{hf}$ãšæžãããŠããŸãïŒã䜿ã£ãŠãBradley-Terryã¢ãã«(3)ã«å¯Ÿå¿ããã©ã³ãã³ã°ã¢ãã«ãåŠç¿ããŸããå ±é
¬ã®ããŒã¹ã©ã€ã³ãå®çŸ©ããã°ã©ã³ãã³ã°ã¢ãã«ããå ±é
¬é¢æ°$r(x,y)$ãåŸãããšãã§ããŸããïŒãããã¯RLHFãšåãããã«ããŒã¿ããçŽæ¥çã«å ±é
¬é¢æ°ãåŠç¿ããŠãããã§ããããïŒ
ããããŠåŸãããå ±é
¬é¢æ°ãå³å¯è§£(5)ã«ä»£å
¥ããã°ãæé©åãããåŸã®LLMã圢åŒçã«ã¯åŸãããŸãããã§ã«è¿°ã¹ãããã«åé
颿°$Z(x)$ãèšç®ããããšã¯çŸå®çã«ã¯äžå¯èœãªã®ã§ãå³å¯è§£ãéåžžã®LLMã®ããã«çæã«äœ¿ãããšã¯é£ããã§ãããæ£åŽãµã³ããªã³ã°æ³ã䜿ãã°å³å¯è§£ã®ç¢ºçååžã«åŸãããŒã¿ã»ãããæ§æããããšãã§ããŸããããã§ããæ£åŽãµã³ããªã³ã°æ³ã¯ãèŠæ Œå宿°ãããã£ãŠããªã確çå¯åºŠé¢æ°ããã®ä¹±æ°çæã«äœ¿ãããææ³ã®ããšã§ããå
·äœçã«ã¯ãææ¡ååžãšããŠ$\pi_\text{ref} (y|x)$ïŒè«æã§ã¯$\pi_\text{SFT} (y|x)$ãšæžãããŠããïŒãçšããŠããããããµã³ãã«ãçæããããã§ãéåžžã®æ£åŽãµã³ããªã³ã°æ³ã®æç¶ãã«åŸã£ãŠæ¡æãæ£åŽããæ±ºããããšã§ã確çååž$\pi (y|x) \propto \pi_\text{ref} (y|x) \exp (r(x,y)/\beta)$ã«åŸãããŒã¿ã»ãããäœæããŸãã
ããããŠäœæããããŒã¿ã»ãããçšããŠã(14)åŒã®æé©åãè¡ãã®ãRSOã§ãã
ãã ããæ£åŽãµã³ããªã³ã°æ³ã䜿ãéšåã¯ããŒã¿ã»ãããäœæããææ®µã§ãã®ã§ãDPOTrainerã«ã¯å®è£
ãããŠããŸãããDPOTrainerã«å®è£
ãããŠããã®ã¯ãããŸã§(14)åŒã®æå€±é¢æ°ã§ãããã®æå³ã§ã以äžã§ã¯hinge lossã䜿ãæé©åææ³ãRSOãšã¯åŒã°ãã«hingeãšåŒã¶ããšãšããŸãã
KTO
æåŸã«KTO (Kahneman-Tversky Optimazation)ã«ã€ããŠè§£èª¬ããŸãã
KTOã¯ã«ãŒããã³ãšããã«ã¹ããŒã«ããããã¹ãã¯ãçè«ã«çæ³ãåŸãææ³ã§ãã
ããã¹ãã¯ãçè«ã¯äººéã®æææ±ºå®ã«é¢ããçè«ã§ã以äžã®ãããªè©±ãæåã§ãã
- ã確å®ã«100äžåè²°ããããšããå Žåãšã確ç50%ã§200äžåè²°ãããã確ç50%ã§äœãè²°ããªãããšããå Žåã®ã©ã¡ãããéžã¹ãšèšããããšãè²°ããéé¡ã®æåŸ å€ã¯ã©ã¡ããåãã ããåè ãéžã¶äººãå€ã
- è²°ãããšããã®ãè² åµã«çœ®ãæããŠãã確å®ã«è² åµã100äžåå¢ããããšããå Žåãšã確ç50%ã§è² åµã200äžåå¢ãããã確ç50%ã§äœãå€ãããªãããšããå Žåãèãããšãä»åºŠã¯åŸè ãéžã¶äººãå€ã
ãã®ããã«å©çãšæå€±ã«å¯Ÿãã人éã®åå¿ã察称ã§ã¯ãªããšããã®ããããã¹ãã¯ãçè«ã®äž»åŒµãããšããã®äžã€ã§ãããKTOã®æè¡ã¬ããŒãã«ãããšãRLHFãDPOã¯å ±é ¬ã«å¯Ÿããé察称æ§ãåããŠãããããã¹ãã¯ãçè«ã«æ²¿ã£ããã®ã«ãªã£ãŠããããã§ãã
KTOãäž»ã«äŸæ ããŠããã®ã¯ãã人ã¯å¯ãã®ãã®ã§ãªããå¯ã®å€åéããå¹çšãåŸãããšããããã¹ãã¯ãçè«ã®ããäžã€ã®äž»åŒµã§ããããªãã¡ãå©çãæå€±ã絶察éãšããŠãšãããã®ã§ã¯ãªããåºæºããã®å€åéãšããŠçžå¯Ÿçã«ãšãããããšããããšã§ãã
RLHFã®æé©å颿°(1)ã«ãããŠã¯ãå
¥å$x$ã«å¯Ÿããå¿ç$y$ã®äŸ¡å€$r(x,y)$ãã®ãã®ãæå€§åããããšããŠããŸããããããã¹ãã¯ãçè«ã®äž»åŒµã«æ²¿ããšã䟡å€$r(x,y)$ãšããã®ã¯çžå¯Ÿçãªãã®ãªã®ã§ãåºæºããã®å·®ã«çç®ããã¹ãããšããããšã«ãªããŸãã
䟡å€ã®åºæºãšããŠã¯ãè²ã
ãªå¿ç$y$ã«å¯Ÿããå¹³åå€ãæ¡çšããŸãããããã£ãŠã$r(x,y)$ã®ä»£ããã«
r(x,y) - \mathbb{E}_{y \sim \pi (\cdot|x)} \left[ r(x,y)\right]
ãæå€§åãããšããããšã«ãªããŸããããã«ãæé©ååé¡ã®å³å¯è§£ããåŸããã(6)åŒãä»£å ¥ãããšãDPOã®å°åºãšåãããã«åé 颿°$Z(x)$ããã£ã³ã»ã«ããŠã次åŒãåŸãããŸãã
\beta \log \frac{\pi (y|x)}{\pi_\text{ref} (y|x)} - \beta \mathbb{E}_{y \sim \pi (\cdot|x)} \left[ \log \frac{\pi (y|x)}{\pi_\text{ref} (y|x)}\right]
\tag{15}
KTOã®æè¡ã¬ããŒãã§ã¯ç¬¬ïŒé ãKLãã€ããŒãžã§ã³ã¹ã§æžãæããŠããŸããããã®èšäºã§ã¯(2)åŒã®ããã«$y$ã ãã§ãªã$x\sim \mathcal{D}$ã«å¯ŸããŠãæåŸ å€ãåã£ããã®ãKLãã€ããŒãžã§ã³ã¹ãšå®çŸ©ããŠããã®ã§ãããã§ã¯KLãã€ããŒãžã§ã³ã¹ã§æžãæããŠã¯ããŸããã
ä»ãåŠç¿ããŒã¿$\mathcal{D}_\text{KTO}$ãšããŠå ¥å$x$ãšããã«å¯Ÿãã奜ãŸããå¿ç$y_w$ã®ãã¢$(x,y_w)$ãšãå ¥åãšå¥œãŸãããªãå¿ç$y_l$ã®ãã¢$(x,y_l)$ããããšãããšã$y_w$ã«å¯ŸããŠã¯(15)åŒã®çžå¯ŸäŸ¡å€ãæå€§åã$y_l$ã«å¯ŸããŠã¯æå°åããã°ããã®ã§ãKTOã®æå€±é¢æ°ã¯ä»¥äžã®ããã«ãªããŸãã
L_\text{KTO} = \mathbb{E}_{(x,y)\sim \mathcal{D}_\text{KTO}} \left[ 1 - \hat{h} (x,y)\right]
\tag{16}
ããã§ã$\hat{h}$ã¯(15)åŒã®çžå¯ŸäŸ¡å€ãã·ã°ã¢ã€ãã«éãããã®ã§ãã
\hat{h}(x,y) = \begin{cases}
\sigma \left( \beta \log \frac{\pi_\theta (y|x)}{\pi_\text{ref} (y|x)} - \beta \mathbb{E}_{y \sim \pi_\theta (\cdot|x)} \left[ \log \frac{\pi_\theta (y|x)}{\pi_\text{ref} (y|x)}\right]\right) \ \text{if}\ y=y_w \\
\sigma \left( \beta \mathbb{E}_{y \sim \pi_\theta (\cdot|x)} \left[ \log \frac{\pi_\theta (y|x)}{\pi_\text{ref} (y|x)}\right] - \beta \log \frac{\pi_\theta (y|x)}{\pi_\text{ref} (y|x)} \right) \ \text{if}\ y=y_l
\end{cases}
ã·ã°ã¢ã€ãã«éããŠããã®ã¯ãæé©åèšç®ãè¡ããããããç®çã ãšæãããŸãã
奜ãŸãããªãå¿çã«å¯ŸããŠã¯æå€±ã倧ãããããã®ã§ãã·ã°ã¢ã€ãã®äžèº«ã®ç¬Šå·ãã²ã£ããè¿ããŠããŸãã
KTOãDPOãªã©ã®ä»ææ³ã«å¯ŸããŠåªäœãªç¹ã¯ãåŠç¿ããŒã¿ã»ããã奜ãŸããå¿çãšå¥œãŸãããªãå¿çã®ãã¢ã§ããå¿
èŠããªããšããããšã§ããDPOã®åŠç¿ããŒã¿ã»ãã$\mathcal{D}_\text{pair}$ã¯äžã€ã®å
¥å$x$ã«å¯Ÿããå¿çãšããŠå¥œãŸãããã®ãšå¥œãŸãããªããã®ã®äž¡æ¹ã®ãã¢ãå¿
èŠã§ãããäžæ¹ãKTOã«ãããŠã¯ãäžã€ã®å
¥å$x$ã«å¯Ÿããå¿çãšããŠã¯å¥œãŸãããã®ãšå¥œãŸãããªããã®ã®ã©ã¡ããäžæ¹ãããã°äžèšã®æå€±é¢æ°ãèšç®ããããšãã§ããŸãã
åªå£ã®ãã¢ã®å¿çããŒã¿ãéããããšã«æ¯ã¹ãã°ãåäžã®è©äŸ¡ãéããããšã¯éåžžã«ç°¡åã§ãã®ã§ãå®å¿çšãèãããšKTOã®æ§è³ªã¯å€§ããªã¢ããã³ããŒãžãšãªããŸãã
ãã ããtrlã©ã€ãã©ãªã®DPOãã¬ãŒããŒã§äœ¿çšã§ããKTOã®å®è£ ã¯ãDPOãšåããã¢åœ¢åŒã®ããŒã¿ã»ãããä»®å®ãããã®ã«ãªã£ãŠããŸããããªãã¡å®è£ ãããŠããæå€±é¢æ°ã¯(16)åŒã§ã¯ãªãã
L_\text{KTO(pair)} = \mathbb{E}_{(x,y_w,y_l)\sim \mathcal{D}_\text{pair}} \left[ 2 - \hat{h} (x,y_w)- \hat{h} (x,y_l)\right]
\tag{17}
ãšããããšã ãšæããŸããããã¯ãDPOTrainerãšããåãã¯ã©ã¹ã«å®è£ ãããŠããéœåã§ãå ¬åŒããã¥ã¡ã³ãã«ã¯ãã¢ã§ã¯ãªãããŒã¿ã«å¯Ÿå¿ããKTOã¯KTOTrainerãšããŠå¥ã¯ã©ã¹ã«å®è£ ãããããšã«ãªãã ããããšãããããªããšãæžããŠãããŸãã
ç°å¢
å®éšã¯Google Colab (Pro+)äžã§A100GPU (Syetem RAM 83.5GB, GPU RAM 40.0GB)ã䜿çšããŠè¡ããŸããã
ã©ã€ãã©ãªã®ã€ã³ã¹ããŒã«
transformersã®ããŒãžã§ã³ã¯ååã®å®éšæãšæããŸããã
deepspeedãšflash-attnã¯ãã«ãã¡ã€ã³ãã¥ãŒãã³ã°ãè¡ãå Žåã«ã¯å¿
èŠãšãªããŸãã
!pip install -U transformers==4.36.2
!pip install datasets accelerate bitsandbytes peft sentencepiece
!pip install trl
!pip install deepspeed ninja
!pip install flash-attn --no-build-isolation
Pythonããã³äž»èŠã©ã€ãã©ãªã®ããŒãžã§ã³
Python 3.10.12
accelerate 0.26.1
bitsandbytes 0.42.0
datasets 2.16.1
deepspeed 0.12.6
flash-attn 2.5.0
ninja 1.11.1.1
peft 0.8.1
torch 2.1.0+cu121
transformers 4.36.2
trl 0.7.10
ãã ããtrlã®äžèšã®ããŒãžã§ã³ã§ã¯DPOTrainerã®IPOã®éšåã«ééããããããšã倿ããã®ã§ãIPOã«é¢ããŠã¯åŸããtrl==0.7.11ã§èšç®ãããçŽããŸããã
trl==0.7.11ã¯èšäºå·çæç¹ã§pipã€ã³ã¹ããŒã«ã§ããææ°çã§ãã
以äžã§ã¯æç€ºããŸããããåããŒãããã¯ã§google driveãããŠã³ãããŠãããã®ãšããŸãã
åé¡èšå®
ããªã·ãŒæé©åã®å¹æãç°¡åã«å®éçã«ç¢ºèªã§ãããããªåé¡èšå®ãšããŠãããã³ããã®æå®ã§è¿çã®èªå°Ÿãå€ãããããšããããšãèããŸãã
å
·äœçã«ã¯æ¢åã®ããŒã¿ã»ããã®ããã³ããã®äžã«### Tagãšãããã£ãŒã«ãã远å ããŠãããã§æå®ãã顿åã§ã以äžã®ããã«è¿çéšåã®èªå°Ÿãæå®ããŸãã
| tag | èªå°Ÿ |
|---|---|
| ð | ïŒå€åãªãïŒ |
| ð«¡ | ããã |
| ð€ª | ãã£ã±ã£ãŽãŒ |
| ð€ | ãããããã¥ããw |
ð«¡ãšð€ã§ããããããéè€ããŠããã®ã¯ãã¿ã¹ã¯ãé£ããããããã§ãã
æ¥æ¬èªdollyããŒã¿ã»ããdatabricks-dolly-15k-jaãšããã®èªå°Ÿããããããã«å€ããéç§°ãããããŒã¿ã»ããdatabricks-dolly-15k-ja-gozaruã䜿ã£ãŠããŒã¿ã»ãããäœæããŸãããå ·äœçãªããŒã¿äœææé ã«ã€ããŠã¯ååã®èšäºãåç §ãã ããã
ããŒã¿ã®äžèº«ã¯äŸãã°ä»¥äžã®ãããªãã®ã§ãã
### Instruction
Slackã®ãšãã±ãããšããŠãã©ã®ãããªã«ãŒã«ãããã®ã§ãããã?
### Tag
ð€
### Answer
Slackã®ãšãã±ããã¯è·å Žã«ãã£ãŠå€§ããç°ãªããããäžè¬çãªã¬ã€ãã©ã€ã³ã瀺ãããšã¯å°é£ã§ãã§ãããããã¥ããwãããããSlackã䜿çšããã»ãšãã©ã®è·å Žã«ã¯ãããã€ãã®å
±éã«ãŒã«ããããŸãã§ãããããã¥ããwãäŸãã°ãå€åæéå€ã«ã¡ãã»ãŒãžãæžããŠããå Žåã¯ãå€åæéå
ã«éä¿¡ããããã«ã¹ã±ãžã¥ãŒã«ããã®ãããã§ãããã§ãããããã¥ããwãã¡ãã»ãŒãžã«è¿ä¿¡ããå Žåã¯ãæ°ããã¹ã¬ãããç«ãŠãããããã¹ã¬ããã§è¿ä¿¡ããã»ããããã§ãããããã¥ããwã
ãã®ãããªããŒã¿ã»ãããçšããŠLLMãSFTããã¿ã°ã®æç€ºã§èªå°Ÿãå€ããŠè¿çããããã«èšç·ŽããŸããå¥ã«çšæãããã¹ãããŒã¿ã䜿ã£ãŠæç€ºã«åŸãå²åã粟床ãšããŠç®åºãšããŸããããã«SFTåŸã®ã¢ãã«ãDPOãªã©ã®ããªã·ãŒæé©åã«ããæç€ºã«åŸãããã«è¿œå ã§åŠç¿ããããšã§ã粟床ãã©ãã ãåäžããããèŠãããšã«ããããªã·ãŒæé©åææ³ã®å¹æãå®éçã«è©äŸ¡ããããšãšããŸãã
LLMãšããŠã¯äºååŠç¿æžã¿ã®LINEã®LLM japanese-large-lm-3.6bã䜿çšããäžã§èª¬æããããŒã¿ã»ãã14,126ä»¶ãçšããŠSFTããŸããããã¹ãããŒã¿ã¯200ä»¶ã®dollyããŒã¿ã«4çš®é¡ã®ã¿ã°ãä»äžããèš800ä»¶ã§ãã粟床ãç®åºããéã«ã¯ãðã«å¯ŸããŠã¯å¿çã®äžã«ïŒçš®é¡ã®èªå°Ÿã®ããããçŸããªããã°æ£è§£ãä»ã®ã¿ã°ã«å¯ŸããŠã¯è©²åœã®èªå°Ÿã®ã¿ãçŸããŠããã°æ£è§£ãšããŸããã
SFTã®å®éã®åŠç¿æé ã¯ååã®èšäºã§èª¬æããã®ã§ããã§ã¯çç¥ããŸãããã«ãã¡ã€ã³ãã¥ãŒãã³ã°ã§ïŒãšããã¯åŠç¿ããããšã®ç²ŸåºŠïŒå šäœæ£è§£çïŒã¯0.666ã§ããã
ãã®SFTã¢ãã«ãããšã«DPO, cDPO, IPO, hinge, KTOã«ããããªã·ãŒæé©åãããããè¡ããçµæã®æ¯èŒãè¡ããŸãã
ããŒã¿ã»ããæºå
trlã©ã€ãã©ãªã®DPOTrainerã䜿ãããã«ã¯ãå
¥åæ$x$ãšå¥œãŸããå¿ç$y_w$ã奜ãŸãããªãå¿ç$y_l$ã®ïŒã€ãçµãšãªã£ãããŒã¿ã»ãããå¿
èŠã§ãã
å
¥åæãšå¥œãŸããå¿çã«ã€ããŠã¯SFTçšã®ããŒã¿ã»ããããã®ãŸãŸäœ¿çšãã奜ãŸãããªãå¿çã«é¢ããŠã¯å
¥åæã®äžã§æå®ãããèªå°Ÿãšã¯éãèªå°Ÿãã©ã³ãã ã«éžãã§ããã®èªå°Ÿãã€ããå¿çã䜿çšããããšãšããŸãã
ãŸããSFTçšã®ããŒã¿ã»ãããèªã¿èŸŒã¿ãŸãããã®ããŒã¿ã»ããã®äœææ¹æ³ã«ã€ããŠã¯ååã®èšäºãåç §ãã ããã
from datasets import load_from_disk
# äœææžã¿ã®SFTçštrainããŒã¿ã»ããèªã¿èŸŒã¿
dataset = load_from_disk("train_dataset.hf")
print(dataset)
# Dataset({
# features: ['category', 'index', 'output', 'input', 'instruction', 'tag'],
# num_rows: 14126
# })
è€æ°ã«ã©ã ã«åãããŠããŸããã'instruction', 'input', 'tag'ã¯å ¥åæã®æ§æèŠçŽ ã§ã'output'ãæ£è§£ã®å¿çæã§ãã'category'ãš'index'ã¯å ã®dollyããŒã¿ã»ããã«ããã«ã©ã ã§ãcategoryã¯äœ¿çšããªãã®ã§äžèŠã§ãããindexã¯å¥œãŸãããªãå¿çãšã®çŽã¥ãã«äœ¿çšããŸãã
DPOTrainerã®ããã®ããŒã¿ã»ããã¯å ¥åæã«çžåœãã'prompt'ã奜ãŸããå¿çã®'chosen'ããããŠå¥œãŸãããªãå¿çã®'reject'ã®ïŒã€ã®ã«ã©ã ãå¿ èŠã§ãããŸããSFTçšããŒã¿ã»ãããã'prompt'ãš'chosen'ãäœæããŸãã
def format_prompt(sample):
instruction = f"### Instruction\n{sample['instruction']}"
input = f"### Context\n{sample['input']}" if len(sample["input"]) > 0 else None
tag = f"### Tag\n{sample['tag']}"
# 3ã€ãçµåããŠpromptãäœæ
sample["prompt"] = "\n\n".join([i for i in [instruction, input, tag] if i is not None])
# æ£è§£ã®outputãchosenãšãã
sample["chosen"] = f"### Answer\n{sample['output']}"
return sample
dataset = dataset.map(format_prompt, remove_columns=["category", "instruction", "input", "output"])
次ã«'reject'ãäœæããããã«ãå ã®æ¥æ¬èªdollyããŒã¿ã»ãããšãããããŒã¿ã»ãããindexã«ã©ã ãããŒã«ããŠçµåããŸãã
from datasets import load_dataset, Dataset
import pandas as pd
# æ¥æ¬èªdollyããŒã¿ã»ãããšãããããŒã¿ã»ãããèªã¿èŸŒã
dataset_dolly = load_dataset("kunishou/databricks-dolly-15k-ja", split="train")
dataset_gozaru = load_dataset("bbz662bbz/databricks-dolly-15k-ja-gozaru", split="train")
# äžåºŠãpandas DataFrameã«å€æããŠãããindexãããŒã«ããŒãžãã
dataset_df = pd.DataFrame(dataset)
dolly_df = pd.DataFrame(dataset_dolly)[["index", "output"]].rename(columns={"output": "dolly_output"})
gozaru_df = pd.DataFrame(dataset_gozaru)[["index", "output"]].rename(columns={"output": "gozaru_output"})
_df = pd.merge(dolly_df, gozaru_df, on="index")
dataset_df = pd.merge(dataset_df, _df, on="index", how="left")
# datasetã«æ»ã
dataset = Dataset.from_pandas(dataset_df)
print(dataset)
# features: ['index', 'tag', 'prompt', 'chosen', 'dolly_output', 'gozaru_output', '__index_level_0__'],
# num_rows: 14126
æåŸã«ãåè¡ã«ãããŠpromptã§æå®ãããã¿ã°ä»¥å€ã®ã¿ã°ãã©ã³ãã ã«éžã³ããã®ã¿ã°ã«è©²åœããå¿çæã'dolly_output'ã'gozaru_output'ããäœæãã'rejected'ãšããŸãã
import random
tag_list = ["ð", "ð«¡", "ð€ª", "ð€"]
tag_rule = {
"ð«¡": lambda text: text,
"ð€ª": lambda text: text.replace("ããã", "ãã£ã±ã£ãŽãŒ"),
"ð€": lambda text: text.replace("ããã", "ãããããã¥ããw"),
}
def make_rejected_output(sample):
index = sample["index"]
designated_tag = sample["tag"]
# å
¥åã§æå®ãããtag以å€ã®tagããã©ã³ãã ã«éžãã ãã®ãrejectedçšã«ãã
other_tags = [t for t in tag_list if t != designated_tag]
rejected_tag = random.choice(other_tags)
if rejected_tag == "ð":
# å
ã®dolly-jaããŒã¿ã»ããã䜿çš
rejected_output = sample["dolly_output"]
else:
# ãããããŒã¿ã»ããã䜿çš
rejected_output = sample["gozaru_output"]
# èªå°Ÿãrejected_tagã«åãããŠæ¹å€
rejected_output = tag_rule[rejected_tag](rejected_output)
sample["rejected"] = f"### Answer\n{rejected_output}"
return sample
keep_cols = ['prompt', 'chosen', "rejected"]
remove_columns = [c for c in list(dataset.features) if c not in keep_cols]
dataset = dataset.map(make_rejected_output, remove_columns=remove_columns)
print(dataset)
# features: ['prompt', 'chosen', 'rejected'],
# num_rows: 14126
ããŒã¿ã»ããã®äžèº«ã¯äŸãã°ä»¥äžã®ãããªãã®ã§ãã
- prompt
### Instruction
ã¯ãªã¹ãã¹ã«å®¶æã«æ¯ãèããè¯ãããªããªããŒæçã3ã€æããŠãã ããã
### Tag
ð«¡
- chosen
### Answer
ããã§ã¯ãããªããŒã·ãŒãºã³ã®ãç¥ãã®é£äºã3ã€ã玹ä»ããŸãïŒ
* ãã©ã€ã ãªããšãšãŒã¯ã·ã£ãŒããã£ã³ã°ã¯ããšãŠãäŒçµ±çãªæçã§ãããã
* ã¿ãŒããŒãããã·ã¥ããããã¯ã©ã³ããªãŒãã¹ã¿ããã£ã³ã°ã¯ãã«ã©ãã«ã§ããããã¢ã¡ãªã«ã®äŒçµ±çãªæçã§ãããã
* ä»çŸã®ã¢ã¢èãšãã³ããœãŒã¹ã®çµã¿åãããå
æ°ãã£ã±ãã§ãããã
- rejected
### Answer
ããã§ã¯ãããªããŒã·ãŒãºã³ã®ãç¥ãã®é£äºã3ã€ã玹ä»ããŸãïŒ
* ãã©ã€ã ãªããšãšãŒã¯ã·ã£ãŒããã£ã³ã°ã¯ããšãŠãäŒçµ±çãªæçã§ãã
* ã¿ãŒããŒãããã·ã¥ããããã¯ã©ã³ããªãŒãã¹ã¿ããã£ã³ã°ã¯ãã«ã©ãã«ã§ããããã¢ã¡ãªã«ã®äŒçµ±çãªæçã§ãã
* ä»çŸã®ã¢ã¢èãšãã³ããœãŒã¹ã®çµã¿åãããå
æ°ãã£ã±ãã§ãã
ããã§ã¯ãchosenãšrejectedã¯èªå°Ÿãéãã ãã§å¿çã®äžèº«ã¯åããã®ãšããŠããŸãããå¿ ãããããã§ããå¿ èŠã¯ãªããäŸãã°rejectedãšããŠã¯SFTã¢ãã«ã®ééã£ãèªå°Ÿã®å¿çã䜿ããšãããããªããšãããŠããããããããŸããããŸããRSOã®ãããªææ³ã§"ããè¯ã"ããŒã¿ã»ãããäœãããšã广çãããããŸããããä»åã®å®éšã§ã¯åçŽãªããŒã¿ã»ããã䜿çšããŸãã
DPOã¯éé©åãããããšèšãããŠããŸãã®ã§ãåŠç¿æã«æ€èšŒããŒã¿ã«å¯Ÿããæå€±ãã¢ãã¿ãŒããããšã«ããŸãããã®ããã«ããŒã¿ãåå²ããŠä¿åããŸãã
indices = list(range(len(dataset)))
random.shuffle(indices)
val_size = 2000
val_indices = indices[:val_size]
train_indices = indices[val_size:]
val_dataset = dataset.select(val_indices)
train_dataset = dataset.select(train_indices)
print(len(train_dataset)) # 12126
print(len(val_dataset) # 2000
# ä¿å
train_dataset.save_to_disk("dpo_train_dataset.hf")
val_dataset.save_to_disk("dpo_val_dataset.hf")
å®éš
åŠç¿æé
DPOTrainerã䜿ã£ãããªã·ãŒæé©åã®å®è¡æé ãDPOã®å ŽåãäŸã«èª¬æããŸãã
ããŒã¿ã»ããèªã¿èŸŒã¿
from datasets import load_from_disk
train_dataset = load_from_disk("dpo_train_dataset.hf")
eval_dataset = load_from_disk("dpo_val_dataset.hf")
ããŒã¯ãã€ã¶ãŒã®ç«ã¡äžã
from transformers import AutoTokenizer
model_name = "line-corporation/japanese-large-lm-3.6b"
tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=False)
DPOTrainerã§ã¯å ¥åããããŒã¿ã®æå€§ç³»åé·ãšããã³ããéšåã®æå€§ç³»åé·ãæå®ããå¿ èŠãããã®ã§ãåŠç¿ããŒã¿ã®åéšåã®æå€§ç³»åé·ã調ã¹ãŠãããŸãã
def measure_length(sample):
sample["prompt_len"] = len(tokenizer(sample["prompt"])["input_ids"])
sample["chosen_len"] = len(tokenizer(sample["chosen"])["input_ids"])
sample["rejected_len"] = len(tokenizer(sample["rejected"])["input_ids"])
return sample
dataset_len = train_dataset.map(measure_length)
print(max(dataset_len["prompt_len"])) # -> 162
print(max(dataset_len["chosen_len"])) # -> 166
print(max(dataset_len["rejected_len"])) # -> 188
ããã³ããã®æå€§ç³»åé·ã¯162ãå šäœã®æå€§ç³»åé·ã¯162+188=350ã§ããã
SFTæžã¿ã®ã¢ãã«ãèªã¿èŸŒã¿ãŸãã
DPOã«ããåŠç¿ã¯LoRAã§è¡ãããšãšããŸãã®ã§ãpeftã䜿ã£ãŠèšå®ãè¡ããŸãã
import torch
from transformers import AutoModelForCausalLM
from peft import LoraConfig, get_peft_model
sft_model_path = "./line_sft" # åŠç¿æžã¿SFTã¢ãã«ã®ãã¹
model = AutoModelForCausalLM.from_pretrained(
sft_model_path,
)
# LoRAèšå®
target_modules = ["query_key_value", "dense", "dense_h_to_4h", "dense_4h_to_h"]
lora_config = LoraConfig(
target_modules=target_modules,
r=16,
lora_alpha=32,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora_config)
次ã«DPOTrainerãç«ã¡äžããŸãã
PPOTrainerãšã¯éããDPOTrainerã«æž¡ãtraining_argsã¯transformersã©ã€ãã©ãªã®Trainerã¯ã©ã¹ã§äœ¿çšããTrainingArgumentsã§ãããããã£ãŠãTrainerã¯ã©ã¹ã§äœ¿çšå¯èœã ã£ãæ©èœã¯DPOTrainerã¯ã©ã¹ã§ã䜿çšå¯èœã§ãã
from transformers import TrainingArguments
from trl import DPOTrainer
output_dir="./line_dpo_1"
training_args = TrainingArguments(
output_dir=output_dir,
overwrite_output_dir=True,
per_device_train_batch_size=2,
gradient_accumulation_steps=128,
per_device_eval_batch_size=16,
learning_rate=1e-5,
weight_decay=0.01,
num_train_epochs=2,
lr_scheduler_type="constant_with_warmup",
warmup_steps=10,
fp16=True,
evaluation_strategy="steps",
save_strategy="steps",
save_steps=32,
logging_steps=8,
eval_steps=8,
load_best_model_at_end=True,
save_safetensors=False,
save_only_model=True,
remove_unused_columns=False,
)
dpo_trainer = DPOTrainer(
model=model,
args=training_args,
beta=0.3,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
tokenizer=tokenizer,
max_prompt_length=162,
max_length=512,
loss_type="sigmoid", # sigmoid, hinge, ipo, kto_pair
label_smoothing=0.0,
)
èšå®ã«é¢ããäž»ãªã³ã¡ã³ãã¯ä»¥äžã®éãã§ãã
- DPOTrainerã«ã¯åç
§ã¢ãã«ã
ref_modelåŒæ°ã§äžããããšãã§ããŸãããåŠç¿å¯Ÿè±¡ã¢ãã«ã®åæç¶æ ïŒä»åã®äŸã§ã¯SFTã¢ãã«ïŒãåç §ã¢ãã«ã«äœ¿ãå Žåã¯çç¥ã§ããŸãã -
per_device_train_batch_size=2ã¯40GB RAMã§OOMããªãããã«èª¿æŽãããã®ã§ãå®è³ªã®ããããµã€ãºã¯256ãšãªãããã«gradient_accumulation_stepsãèšå®ããŠããŸãã -
max_prompt_lengthã¯äºåã«èª¿ã¹ãéã162ãšããŠãmax_lengthã¯å¿µã®ããäœè£ãæãããŠ512ãšããŸããã -
loss_typeã«ããæé©åææ³ãåãæ¿ããããšãã§ããŸãã- sigmoid: DPO, cDPO
- hinge: RSOã§å°å ¥ããããã³ãžæå€±
- ipo: IPO
- kto_pair: KTOã§ããŒã¿ããã¢ã®ããŒãžã§ã³
- cDPOã䜿çšããã«ã¯loss_type="sigmoid"ãšããããã§label_smoothingã«æ£ã®å€ãäžããŸãã
åŠç¿å®è¡ãšä¿å
dpo_trainer.train()
# ä¿å
dpo_trainer.save_state()
model.save_pretrained(output_dir)
ïŒãšããã¯ïŒ94ã¹ããããåŠç¿ããŒã¿ä»¶æ°12,126ïŒã®åŠç¿ã¯67åã»ã©ã§å®äºããŸããã
PPOã®åŠç¿ãè¡ã£ãæã¯åŠç¿ããŒã¿ä»¶æ°ã3,000ä»¶ãŸã§çµã£ãŠã1ãšããã¯ïŒ45ã¹ãããïŒã®åŠç¿ã«210åã»ã©ããã£ãŠããŸããã®ã§ãDPOã®èšç®ã³ã¹ãã¯PPOãããæ Œæ®µã«äœããšããããšã確ãããããŸããã
ãã€ããŒãã©ã¡ãŒã¿ã«ã€ããŠ
DPOTrainerã®ãã€ããŒãã©ã¡ãŒã¿ã®äžã§ç¹ã«éèŠãªã®ã¯åŠç¿çlearning_rateãšKLãã€ããŒãžã§ã³ã¹é
ã®ä¿æ°betaã§ãã
ã¯ããã¯ããã©ã«ãå€ã®learning_rate=5e-5ãšbeta=0.1ãšããã®ã§ãããå ±é
¬ã«å¯ŸããŠéé©åããŠããŸããŸããããèšç·ŽããŒã¿ã«å¯ŸããŠéé©åïŒéåŠç¿ïŒãã§ã¯ãªããå ±é
¬ã«å¯ŸããŠéé©åããšãããšããããã€ã³ãã§ããå®éãåŠç¿äžã®ãã¹ã¯èšç·Žãæ€èšŒãã©ã¡ããåãçšåºŠã®å€§ããã§ãæ€èšŒããŒã¿ã«å¯Ÿãããã¹ãæåŸãŸã§äžããç¶ããŠããŸããããããèŠãŠãéåŠç¿ããã«åŠç¿ãããŸããã£ããšæã£ãã®ã§ãããåŠç¿åŸã®ã¢ãã«ã§æšè«ããŠã¿ããšä»¥äžã®ããã«ãæé ã§ãããªããã§ãããããã¥ããwããšèšããªã©ãæå®ãããèªå°Ÿã䜿ããšããæå³ã§ã¯å ±é
¬ãé«ãæ¯ãèããããŠãããã®ã®ãæç« ãšããŠã¯ãã¡ããã¡ããªå¿çã«ãªã£ãŠããŸããŸãããéåžžèªå°Ÿã®ðã«é¢ããŠã¯ãæ¥æ¬èªãšããŠã¯äžèªç¶ã§ã¯ãããŸãããã質åã«å¯ŸããåçãšããŠã¯ïŒãã¶ãã§ããïŒäžé©åãªãã®ã«ãªã£ãŠããŸãã
### Instruction
ãµãŒããã§ãåã¯æ¶Œå®®ãã«ãã®ãã£ã©ã§èª°ã奜ããªã®ïŒ
### Tag
ð
### Answer
ã¹ãã£ãŒãã³ããªãã£ãŒãããããã®äººã
ã¯ãç©èªã®äžã§éèŠãªåœ¹å²ãæãããŠããŸããç¹ã«ãã¹ãã£ãŒãã³ã¯ãSFããžã£ã³ã«
### Instruction
ãµãŒããã§ãåã¯æ¶Œå®®ãã«ãã®ãã£ã©ã§èª°ã奜ããªã®ïŒ
### Tag
ð«¡
### Answer
ã§ããããæè
ã¯ã鲿é¢ç¯€éã§ãããã§ããããæè
ã§ããããäŸåŸé·ã§ãããã§ããã
### Instruction
ãµãŒããã§ãåã¯æ¶Œå®®ãã«ãã®ãã£ã©ã§èª°ã奜ããªã®ïŒ
### Tag
ð€
### Answer
ã§ãããããã¥ããwããã§ã³ããã§ãããããã¥ããwããã§ã³ã¯ãã¢ãç¥ã
### Instruction
ãµãŒããã§ãåã¯æ¶Œå®®ãã«ãã®ãã£ã©ã§èª°ã奜ããªã®ïŒ
### Tag
ð€ª
### Answer
ã§ãã£ã±ã£ãŽãŒã ### Instr ### Context
ã«ãŒã©ã§ãã£ã±ã£ãŽãŒã #
PPOã®åŠç¿ãè¡ã£ãæã§ããã°ãæå®ãããèªå°Ÿãå«ãã§ããããã°å ±é ¬ãé«ããªãå ±é ¬ã¢ãã«ã䜿ã£ãŠããã®ã§ãéé©åã«ãããã®ãããªæ¯ãèããåŠç¿ããŠããŸãã®ã¯çè§£ããããã®ã§ãããDPOã®å Žåã¯æå®ãããèªå°Ÿã䜿ã£ãŠããå¿çãšäœ¿ã£ãŠããªãå¿çãæ¯èŒãããŠããã ããªã®ã§ããã®ãããªæ¯ãèããçŸããã®ã¯å°ãäžæè°ãªæããããŸããDPOã®æé©å颿°ã¯RLHFãšå³å¯ã«åããªã®ã§ãæç€ºçã«å ±é ¬ã¢ãã«ãåŠç¿ãããŠããªããšããå éšçã«åŠç¿ãããå ±é ¬ã¢ãã«ããã®ãããªæ¯ãèããåŒãèµ·ãããŠããã®ã ãšæããŸãã
äœè«ã§ãããéé©åã«ããçé ããããããªã£ãŠããäžã§ãð€åã ãã¯æ¶Œå®®ãã«ãã®ãã£ã©ã«ã€ããŠèªã£ãŠããŠãããããªã¿ã¯ã®éã ãšæããŸããã
éé©åãé²ãããã«ãlearning_rateãå°ãããbetaã倧ããããŠåŠç¿ãããçŽããŸããã系統çãªãã€ããŒãã©ã¡ãŒã¿ãµãŒãã¯ã§ããŠããããåã§èª¿ç¯ããã ãã§ãããlearning_rate=1e-5, beta=0.3ãšãããšãããæå®ãããèªå°Ÿã䜿ãã€ã€ãæ¥æ¬èªãšããŠç Žç¶»ããŠããªãå¿çãããããšãå€ããªããŸãããDPO以å€ã®ææ³ã«å¯ŸããŠãããããã®å€ã䜿ã£ãŠåŠç¿ãè¡ããŸããã
è©äŸ¡ææš
æå®ãããèªå°Ÿã䜿ã£ãŠãããã©ããã®æ£è§£çãè©äŸ¡ææšãšããŸãã
å
·äœçã«ã¯ãdollyããŒã¿ã»ããã®ãã¡åŠç¿ããŒã¿ã«ã¯äœ¿ããªãã£ã200ä»¶ããã¹ãããŒã¿ãšããããããã«ïŒçš®é¡ã®ã¿ã°ãã€ããŠæšè«ãè¡ããã¿ã°ã§æå®ãããèªå°Ÿã䜿ãããŠãããã©ããã以äžã®é¢æ°ã§å€å®ããŸãã
def classifier(text):
have_gozaru = "ããã" in text
have_oppappy = "ãã£ã±ã£ãŽãŒ" in text
have_dufufu = "ãããããã¥ããw" in text
if not have_gozaru and not have_oppappy and not have_dufufu:
return "ð"
elif have_gozaru and not have_oppappy and not have_dufufu:
return "ð«¡"
elif have_gozaru and not have_oppappy and have_dufufu:
return "ð€"
elif not have_gozaru and have_oppappy and not have_dufufu:
return "ð€ª"
else:
return "others"
ãã®çµæãã以äžã®ãããªæ··åè¡åãåŸãããå
šäœæ£è§£çãç®åºã§ããŸãã

æ··åè¡åã®Truthã¯ããã³ããã§æå®ããèªå°Ÿã§ãPredictionã¯LLMãçæããå¿çã§äœ¿ãããŠããèªå°Ÿã§ããPredictionã®othersã¯ïŒçš®é¡ä»¥äžã®èªå°Ÿã䜿çšããŠããã±ãŒã¹ã衚ããŸãã
ãããã§æšè«ãè¡ãæ¹æ³ãªã©ã詳ããèšç®æ¹æ³ã¯ååã®èšäºãã芧ãã ããã
ãã ããå
šäœæ£è§£çã«ã¯åé¡ããããäžã§èŠãããããªéé©åãèµ·ãããå¿çã§ãé«ã粟床ã«ãªã£ãŠããŸããŸãã
ããã§ãããäžã€å¥ã®è©äŸ¡ææšãšããŠãRLHFã®æé©å颿°(1)ã®ç¬¬ïŒé
ã«çžåœããKLãã€ããŒãžã§ã³ã¹ãèšç®ããŸããKLãã€ããŒãžã§ã³ã¹ã¯ã¢ãã«ãåºåããããã£ãã©ãªç©ºéã§ã®ç¢ºçååžãåç
§ã¢ãã«ã§ããSFTã¢ãã«ã®åºåãšã©ãã ãç°ãªã£ãŠããããæž¬ããã®ã§ããæé©å颿°(1)ã«ãããŠã¯KLãã€ããŒãžã§ã³ã¹ãå°ããæããããšããŠããŸãã®ã§ãè©äŸ¡ææšãšããŠãKLãã€ããŒãžã§ã³ã¹ã¯å°ããã»ãããããšããããšã«ãªããŸãã
ä»åã®å®éšã«ãããŠã¯ãDPOãªã©ã®ããªã·ãŒæé©åã®ç®çã¯SFTã¢ãã«ã远å åŠç¿ããŠæç€ºã«åŸãèœåãåäžãããããšãªã®ã§ãåŠç¿åŸã®ã¢ãã«ã®åºåååžãSFTã¢ãã«ã®åºåååžã«è¿ããã°è¯ããšã¯å¿
ãããèšããŸããããSFTã¢ãã«ã®åºåã¯æ¥æ¬èªãšããŠããçšåºŠèªç¶ãªãã®ã§ããã®ã§ãKLãã€ããŒãžã§ã³ã¹ãã¢ãã«ã®åºåãæ¥æ¬èªãšããŠèªç¶ã§ãããã©ããã®å€§éæãªç®å®ãšããŠæããããšã¯ã§ããã§ããããå®éãéé©åããã¢ãã«ã«å¯ŸããŠã¯KLãã€ããŒãžã§ã³ã¹ã®å€ã¯éåžžã«å€§ãããªããŸããã
ãŸãå°ãªããšããæé©å颿°(1)ãèŠæ±ããŠãããKLãã€ããŒãžã§ã³ã¹ã¯å°ããä¿ã¡ãªããå ±é
¬ã倧ãããããšããåŠç¿ãã§ããŠãããã©ãããå®éçã«è©äŸ¡ãããã€ãŸãæé©åææ³èªäœã®åªå£ã倿ããããã®ææšãšããŠã¯æå¹ã§ãã
æ¥æ¬èªãšããŠèªç¶ãªå¿çãã§ããŠãããã©ãããªã©ã¯ãGPT-4ã䜿ã£ãè©äŸ¡ãªã©ãäžè¬ã«LLMã®è©äŸ¡ã«çšããããŠããææšã䜿ãã¹ããªã®ã§ãããèšç®ã³ã¹ãã®éœåãããè¡ã£ãŠããŸããã
以äžã§ã¯ãKLãã€ããŒãžã§ã³ã¹ã®èšç®æ¹æ³ã«ã€ããŠèª¬æããŸãã
å
šäœæ£è§£çãç®åºããéã«çæããå¿çæããªã¹ãtext_listã«æ ŒçŽããŠãããšããŠãããã䜿çšããŸããæ£ç¢ºã«ã¯ãå
¥åæãšããã«ç¶ãå¿çæãã€ãªããããããã¹ããæ ŒçŽããŸããããã¹ãããŒã¿ã¯200ä»¶ã§ãã¿ã°ïŒçš®é¡ã®åã®å¿çãããã®ã§ãtext_listã®èŠçŽ æ°ã¯800ã§ãã
ãããã®å
¥åæïŒå¿çæãå床ã¢ãã«ã«å
¥åããããšã§ããã®å¿çæãçæããéã®ç¢ºçååžãåŸãããŸããåãæãSFTã¢ãã«ã«ãå
¥åããã°ãSFTã¢ãã«ã®åºåã®ç¢ºçååžãåŸãããŸãã®ã§ãäž¡è
ã®KLãã€ããŒãžã§ã³ã¹ãèšç®ããããšã§ããŸãã
ãŸãã¯ãå ¥åæïŒå¿çæã®ãªã¹ãããããŒã¿ããŒããŒãäœæããŸãã
import torch
from datasets import Dataset
from torch.utils.data import DataLoader
from transformers import AutoTokenizer, DataCollatorWithPadding
# ããŒã¿ã»ãã
dataset = Dataset.from_dict({"text": text_list})
# ããŒã¯ãã€ã¶æºå
# ãããåŠçã®ããå·Šããã£ã³ã°ãšãã
tokenizer = AutoTokenizer.from_pretrained(
"line-corporation/japanese-large-lm-3.6b",
use_fast=False,
padding_side="left",
)
tokenizer.pad_token = tokenizer.eos_token
# ããŒã¯ãã€ãº
dataset = dataset.map(
lambda sample: tokenizer(sample["text"], add_special_tokens=False),
batched=True,
remove_columns=list(dataset.features),
)
# ããŒã¿ã³ã¬ãŒã¿ãŒ
# ãããåŠçã®ããããã£ã³ã°ãå¿
èŠ
data_collator = DataCollatorWithPadding(tokenizer=tokenizer, padding=True)
# ããŒã¿ããŒããŒ
batch_size = 8
dataloader = DataLoader(
dataset,
batch_size=batch_size,
collate_fn=data_collator
)
SFTã¢ãã«ãšããªã·ãŒæé©åæžã¿ã¢ãã«ãèªã¿èŸŒã¿ãŸã
from transformers import AutoModelForCausalLM
# åç
§ã¢ãã«
model_dir = "./line_sft"
sft_model = AutoModelForCausalLM.from_pretrained(
model_dir,
torch_dtype=torch.float16,
device_map="cuda",
)
sft_model.eval()
# DPOåŠç¿æžã¿ã¢ãã«
output_dir="./line_dpo_1"
model = AutoModelForCausalLM.from_pretrained(
model_dir,
torch_dtype=torch.float16,
device_map="cuda",
)
model.eval()
ïŒã€ã®ã¢ãã«ã«åãããŒã¿ãå
¥åããåºåéã®KLãã€ããŒãžã§ã³ã¹ãèšç®ããŸãã
model.generate()ã§ã¯ãªãmodel()ã«å
¥åãããšåºåãšããŠlogitsãåŸãããŸãã®ã§ãããããsoftmaxã«éããŠããã£ãã©ãªç©ºéã§ã®ç¢ºçååžã«çŽããŠããKLãã€ããŒãžã§ã³ã¹ã«ä»£å
¥ããŸãã
import numpy as np
from torch.nn.functional import log_softmax, kl_div
kl_list = []
for batch in dataloader:
batch = {k: v.cuda() for k, v in batch.items()}
outputs = model(**batch)
sft_outputs = sft_model(**batch)
for logits, sft_logits, mask in zip(outputs["logits"].detach(), sft_outputs["logits"].detach(), batch['attention_mask']):
m = mask.to(torch.bool)
# paddingã«çžåœããéšåã¯åãé€ã
# èšç®ã®éœåäžãsoftmaxã§ã¯ãªãlog_softmaxã«éã
logprob = log_softmax(logits[m], dim=-1)
ref_logprob = log_softmax(sft_logits[m], dim=-1)
# 確çååžã®å¯Ÿæ°ãå
¥åããã®ã§ãlog_target=Trueãæå®ããã
kl = kl_div(ref_logprob, logprob, log_target=True, reduction="none").sum()
kl_list.append(kl.item())
print(len(kl_list)) # -> 800
# å
šããŒã¿ã«å¯Ÿããå¹³åãåã
np.mean(kl_list)
çµæ
åææ³ (method) ããšã®ãæå®ããèªå°Ÿã«ãªã£ããã©ããã®å šäœæ£è§£ç (accuracy)ãšãåç §ã¢ãã«ïŒSFTã¢ãã«ïŒãšã®KLãã€ããŒãžã§ã³ã¹ (KL div)ã衚ã«ãŸãšããŸãããå šäœæ£è§£çã¯ïŒåæšè«ãç¹°ãè¿ããçµæã®å¹³åå€ã瀺ããŠããŸãã
| method | lr | beta | label smoothing |
accuracy â | KL div â |
|---|---|---|---|---|---|
| SFT (2ep) | - | - | - | 0.666 | - |
| SFT (6ep) | - | - | - | 0.868 | 59.31 |
| PPO | 5.e-5 | 0.1 | - | 0.839 | 1.46 |
| DPO | 5.e-5 | 0.1 | 0 | 0.843 | 128.2 |
| DPO | 1.e-5 | 0.3 | 0 | 0.927 | 9.41 |
| cDPO | 1.e-5 | 0.3 | 0.1 | 0.857 | 1.89 |
| cDPO | 1.e-5 | 0.3 | 0.3 | 0.828 | 0.559 |
| IPO (trl0.7.10) | 1.e-5 | 0.3 | - | 0.806 | 0.232 |
| IPO (trl0.7.11) | 1.e-5 | 0.3 | - | 0.738 | 3.49 |
| hinge | 1.e-5 | 0.3 | - | 0.835 | 1.75 |
| KTO | 1.e-5 | 0.3 | - | 0.786 | 2.03 |
| DPO (full FT) | 2.e-6 | 0.3 | 0 | 0.962 | 47.21 |
| cDPO (full FT) | 1.e-6 | 0.3 | 0.1 | 0.961 | 3.09 |
DPOãªã©ã®ããªã·ãŒæé©åææ³ã§ã¯ãåŠç¿ç (lr)ãšæ£ååé ã®betaã®å€ãèšèŒããŠããŸãã
äžçªäžã®SFT(2ep)ããåç
§ã¢ãã«ã§ããããã€ããªã·ãŒæé©åãè¡ããšãã®ã¢ãã«ã®åæç¶æ
ã§ããããªã·ãŒæé©åã«ãããã©ã®ææ³ã§ãåæç¶æ
ãããæ£è§£çãåäžããŠããã®ãèŠãŠåããŸãã
ïŒçªç®ã®SFT(6ep)ã¯éåžžã®SFTãšããªã·ãŒæé©åã®æ¯èŒã®ããã«èšç®ãããã®ã§ãSFT(2ep)ãã远å ã§4ãšããã¯SFTãè¡ã£ãã¢ãã«ã§ããããªã·ãŒæé©åã§ã¯å¥œãŸããå¿çãšå¥œãŸãããªãå¿çã®ãã¢ã䜿ã£ãŠ2ãšããã¯åŠç¿ããŠããã®ã§ãåŠç¿ããŒã¯ã³æ°ãåãããããã«è¿œå ã®SFTã¯4ãšããã¯ãšããŸãããïŒãã ããããªã·ãŒæé©åã§ã¯LoRAã䜿ã£ãŠããã®ã«å¯ŸããSFTã§ã¯ãã«ãã©ã¡ãŒã¿ãã¡ã€ã³ãã¥ãŒãã³ã°ããŠããŸããïŒ
PPOã¯ååã®èšäºã§åŠç¿ãããã®ã§ããåŠç¿ã®èšç®ã³ã¹ããé«ãããããŒã¿ä»¶æ°ã3,000ä»¶ã«çµã£ãŠ1ãšããã¯ããåŠç¿ããŠããŸããã®ã§ãDPOãªã©ã®ä»ææ³ãšå ¬å¹³ã«æ¯èŒããããšã¯ã§ããŸããã
ã§ã¯ãDPOãªã©ã®çŽæ¥æé©åææ³ã®çµæã詳ããèŠãŠãããŸãããã
ãŸããDPO (lr=5.e-5, beta=0.1)ã¯ãã§ã«çæçµæãèŠããããã«ãå ±é
¬ã«éé©åããŠæ¥æ¬èªãšããŠäžèªç¶ãªæç« ãçæããŠããŸãã¢ãã«ã§ããããããã«ãKLãã€ããŒãžã§ã³ã¹ã®å€ãéåžžã«å€§ãããªã£ãŠããŸã£ãŠããŸããããã«æ¯ã¹ãŠããã€ããŒãã©ã¡ãŒã¿ã調æŽããDPO (lr=1.e-5, beta=0.3)ã§ã¯KLãã€ããŒãžã§ã³ã¹ã®å€ãå°ãããªã£ãŠããŸãããã®äžãæ£è§£çããã¡ãã®æ¹ãé«ããªã£ãŠããŸãããŸããSFT(6ep)ãšæ¯èŒããŠããæ£è§£çã»KLãã€ããŒãžã§ã³ã¹ã©ã¡ãã®ææšã§ãåªããŠãããDPOææ³ã®æå¹æ§ã確ãããããŸããã
DPOã«å¯Ÿãã©ãã«ã¹ã ãŒãžã³ã°ã远å ããcDPOã§ã¯ãæ£åå广ã匷ãŸããKLãã€ããŒãžã§ã³ã¹ã®å€ãDPOãããå°ãããªã£ãŠããŸãããã ããæ£è§£çãäžãã£ãŠããŸã£ãŠãããäž¡è ã¯ãã¬ãŒããªãã®é¢ä¿ã«ããããšãããããŸãã
hingeã¯åãlrãšbetaã®å€ã§æ¯ã¹ããšDPOãããæ£ååãå¹ããŠããçµæãšãªããŸããã
IPOã¯ééã£ãå®è£ ã§ããtrl==0.7.10ãšä¿®æ£ãããå®è£ ã§ããtrl==0.7.11äž¡æ¹ã§åŠç¿ãè¡ã£ãã®ã§ãããã©ã¡ãã®è©äŸ¡ææšã§èŠãŠãtrl==0.7.10ã®æ¹ãè¯ããšããæå€ãªçµæãšãªããŸãããä¿®æ£ãããã¯ãã®å®è£ ã§ç²ŸåºŠãäžãã£ãçç±ã¯ããªããð€ã«å¯ŸããŠã ãèªå°ŸãééããŠããŸããããªã®ã§ãããåå ã¯ããã£ãŠããŸãããåŸã»ã©ããå°ã詳现ã«çµæã玹ä»ããŸãã
KTOã§ãIPO(trl0.7.11)ãšåããð€ã®ç²ŸåºŠã ããæªããªã£ãŠããŸããŸããã
äžããïŒçªç®ã®DPO (full FT)ã¯LoRAã§ã¯ãªããã«ãã©ã¡ãŒã¿ãã¡ã€ã³ãã¥ãŒãã³ã°ããDPOã®çµæã§ãããã«ãã¡ã€ã³ãã¥ãŒãã³ã°ã ãšç²ŸåºŠã¯é«ããªããŸãããéé©åãèµ·ãããããããã§lrãå°ããããã«ããããããKLãã€ããŒãžã§ã³ã¹ã倧ãããªã£ãŠããŸããŸããã
ããã«lrãå°ããããŠã©ãã«ã¹ã ãŒãžã³ã°ããããã®ãäžçªäžã®cDPO (full FT)ã§ãæ£è§£çãæãªãããšãªãKLãã€ããŒãžã§ã³ã¹ãæããããšã«æåããŸãããDPOã§ã¯åŠç¿çãããªãå°ããããæ¹ãè¯ããšããæ
å ±ãç®ã«ããããšããããŸããããã«ãã¡ã€ã³ãã¥ãŒãã³ã°ã®å Žåã¯ç¢ºãã«ãã®ããã§ãã
ãã«ãã¡ã€ã³ãã¥ãŒãã³ã°ã®ããæ¹ã¯æåŸã«è§£èª¬ããŸãã
衚ã®çµæãäžéšãé€ããŠããããããã®ãäžå³ã§ããæ£è§£çã瞊軞ãKLãã€ããŒãžã§ã³ã¹ã暪軞ãšããŠããŸãã

ïŒã€ã®ææšã®ã¿ãèŠããšãã芳ç¹ã§ã¯ãå³ã®å·Šäžã«è¿ãã»ã©è¯ãçµæãšããããšã«ãªããŸãããã«ãã©ã¡ãŒã¿ãã¡ã€ã³ãã¥ãŒãã³ã°ããcDPOãäžçªæ§èœãè¯ããšããããšãèŠãŠåããŸãã
ãã®ã»ãã®LoRAã䜿ã£ãŠåŠç¿ãããã®ã©ãããæ¯ã¹ããšãIPO (trl0.7.11)ãšKTOã®çµæãæªããšããããšã¯ç¢ºå®ã«èšããŸããããã以å€ã«é¢ããŠã¯ããã®çµæããã¯ã©ããåªããŠããããã¯ã£ãããšçµè«ä»ããããšã¯ã§ããªãã§ããããããããã®ææ³ã§ãã€ããŒãã©ã¡ãŒã¿ãå€ããªããäœåºŠãåŠç¿ãããŠãããããããç¹ãå¢ããã°ãææ³ããšã®åŸåãèŠããŠåªå£ãå€å®ã§ãããããããŸããããèšç®è³æºã®éœåäžãããŸã§ã¯è¡ããŸããã§ããã
以äžã§ã¯ãããã¹ãçæäŸãèªå°Ÿããšã®ç²ŸåºŠãšãã£ãããå°ã詳现ãªçµæãèŠãŠã¿ãŸãã
ããã¹ãçæäŸ
ããã¹ãçæäŸãããã€ã玹ä»ããŸãã
çææã®ãã©ã¡ãŒã¿ã¯
generator_params = dict(
max_length = 64,
do_sample = True,
temperature = 0.7,
top_p = 0.9,
top_k = 0,
repetition_penalty = 1.1,
num_beams = 1,
)
ã§ãã
ãŸãã¯ãæé©åã®åæç¶æ
ã¢ãã«ã§ããSFT(2ep)ã®çµæã§ãã
質åæã¯ä»¥äžãã¹ãŠå
±éã§
### Instruction
ãµãŒããã§ãåã¯æ¶Œå®®ãã«ãã®ãã£ã©ã§èª°ã奜ããªã®ïŒ
ãªã®ã§ãã¿ã°ä»¥éã瀺ããŸããã¿ã°ãŸã§ãå
¥åããã³ããã§ã### Answer以äžãçæçµæã§ããç°ãªãå¿çãç¹ç·åºåãã§è¡šç€ºããŠããŸãã
### Tag
ð
### Answer
é·éæåžã¯ããšãŠãç¥çãªãã£ã©ã¯ã¿ãŒã§ãããŸããåœŒå¥³ã¯æ°åŠããšãŠãåŸæã§ããã®èœå
------------------------
### Tag
ð«¡
### Answer
SOSå£ã®å£é·ã§ãããã§ã³ã§ããããã¢ãã¡ç¬¬1æã§ã¯ã圌ã®å£°ã¯é¢ä¿åœŠãæŒããŠ
------------------------
### Tag
ð€
### Answer
ãã§ã³ãé·éæåžã§ãããããã¥ããwããããŠãææ¯å¥ã¿ããã§ããã
------------------------
### Tag
ð€ª
### Answer
ç§ã¯ãã§ã³ã奜ãã§ãã圌ã¯åžžã«ã¯ãŒã«ãªååšã§ãã§ãã£ã±ã£ãŽãŒããããããã«ãã¯åœŒã®ããšã
ããŸããŸã§ããããã¹ãŠã®èªå°Ÿãæå®éãã«ãªã£ãŠããŸãããŸããåçãšããŠãïŒäžéšãã«ã·ããŒã·ã§ã³ãããããã§ããïŒèªç¶ãªãã®ã«ãªã£ãŠããŸãã
DPO (lr=5.e-5, beta=0.1)ã®çæçµæã¯ãã§ã«ãèŠãããããã«å ±é ¬ã«éé©åãããã®ã§ãããéé©åãæãããããã©ã¡ãŒã¿ãå€ããDPO (lr=1.e-5, beta=0.3)ã®çæäŸã¯ä»¥äžã®éãã§ãã
### Tag
ð
### Answer
ç§ã¯ãã§ã³ã奜ãã§ãã圌ã¯ãšãŠãå
±æçã§ãä»äººãçè§£ããããã«äžçæžåœåªåããŸãã圌ããæé¬±ããª
------------------------
### Tag
ð«¡
### Answer
é·éæåžã§ããããã¯ãŒã«ãã¥ãŒãã£ãŒã§ãããªãããä»äººã®ããã«è¡åããã人奜ãã§ããããŸãããŸãã圌女ã
------------------------
### Tag
ð€
### Answer
æè
ãã¡ã¯ã涌宮ãã«ããã·ãªãŒãºã倧奜ããªã®ã§ã涌宮ãã«ãã®ããšã倧奜ãã§ãããããã¥
------------------------
### Tag
ð€ª
### Answer
é·éæåžã§ãã£ã±ã£ãŽãŒã圌女ã¯å¥œå¥å¿æºçã§ãã£ã±ã£ãŽãŒãSFããã©ãŒããã¡ã³ã¿ãžãŒ
ð€ã®èªå°Ÿãmax_lengthã®ãããéäžã§åããŠããŸãããèªå°Ÿã¯ã©ããæç€ºã«åŸã£ãŠããŸãããæ¥æ¬èªãšããŠãèªç¶ã§ããããããæç€ºãããããã§ããªãã®ã«ãð€ã®äžäººç§°ãæè ã«ãªã£ãŠããã®ã¯ãããã£ãŠããæããããŸãã
次ã«ãDPOã«ã©ãã«ã¹ã ãŒãžã³ã°ããããcDPO (label_smoothing=0.3)ã®çµæãèŠãŠã¿ãŸãããã
### Tag
ð
### Answer
é·éæåžã¯ããããããé ãè¯ãã圌女ã®èãã¯ãã€ãè峿·±ããããããŠããã€ãäœãé¢çœã
------------------------
### Tag
ð«¡
### Answer
é·éæåžã§ãããã圌女ã¯ãšãŠãç¥çãªå¥³æ§ã§ãSFããã¹ããªãŒå°èª¬ã奜ãã§ãããããããŠã
------------------------
### Tag
ð€
### Answer
ãã§ã³ã§ãã£ã±ã£ãŽãŒã圌ã¯ããã«ããæå±ããSOSå£ã«ãšãŠãå¿ èª å¿ããããŸãã§ããã
------------------------
### Tag
ð€ª
### Answer
é·éæåžã¯çŽ æŽããã女æ§ã§ãã£ã±ã£ãŽãŒã圌女ã¯ãã€ãäžæè°ã¡ããã§ããã®ãŠããŒã¯ããé
åã§ã
æç€ºè¿œåŸã®ç²ŸåºŠãäžãã£ãŠããããšããããð€ã®èªå°Ÿãééã£ãŠããŸããæ¥æ¬èªãšããŠã®èªç¶ãã¯DPO (lr=1.e-5, beta=0.3)ãšéããããããã«ã¯èŠãããKLãã€ããŒãžã§ã³ã¹ã®å€ã®éã (9.41 vs. 0.559) ã¯ãæç« ã®ã¯ãªãªãã£ã®å·®ãæç¢ºã«åæ ãããã®ã§ã¯ãªãããã§ãã
次ã¯ãKLãã€ããŒãžã§ã³ã¹ã®å€ãäžçªå°ããã£ããå®è£ ãä¿®æ£ããåã®IPO (trl0.7.10)ã®çµæã§ãã
### Tag
ð
### Answer
é·éæåžã𿿝å¥ã¿ããã奜ãã§ããæ¶Œå®®ãã«ãã¯æ¬ã奜ãã§ã圌女ã¯ããŸã
------------------------
### Tag
ð«¡
### Answer
ãã§ã³ã§ãããã圌ã¯ãã€ããã«ããå°ããŠããŸãã§ãããã圌ãããªããã°ããã«ãã¯ãã éå±ãª
------------------------
### Tag
ð€
### Answer
é·éæåžã¡ããã§ãããããã¥ããwã
圌女ã¯ã¯ãŒã«ã§ãããããã¥ããwã
------------------------
### Tag
ð€ª
### Answer
ç§ã¯ãã§ã³ã倧奜ãã§ãã§ãã£ã±ã£ãŽãŒã圌ã¯ãšãŠãã¯ãŒã«ã§ãã£ã±ã£ãŽãŒã圌ãããå£ã«ãããã¬ãŒãºã¯
æç€ºè¿œåŸã®èгç¹ã§ãæ¥æ¬èªã®èªç¶ãã®èгç¹ã§ãæªããªãããã§ãã
ããã«å¯Ÿããå®è£ ãä¿®æ£ããIPO (trl0.7.11)ã ãšã以äžã®ããã«ãªããŸãã
### Tag
ð
### Answer
ãã«ãã¯ããã®å€é¢æ§ãæ
ç±çãªæ§æ Œãããéåžžã«äººæ°ã®ãããã£ã©ã¯ã¿ãŒã§ãããã«ãã»ã©
------------------------
### Tag
ð«¡
### Answer
ãã§ã³ãé·éæåžã倿³äžæš¹ã§ããããæè
ã¯ãã®3人ã®ãã£ã©ã¯ã¿ãŒãæããŠãã
------------------------
### Tag
ð€
### Answer
é·éæåžã§ãã£ã±ã£ãŽãŒã圌女ã¯ãšãŠãã¯ãŒã«ã§ãã£ã±ã£ãŽãŒã圌女ã®å£°ã¯ãšãŠãé
åçã§ãã§ã
------------------------
### Tag
ð€ª
### Answer
é·éæåžã§ãã£ã±ã£ãŽãŒã圌女ã¯å¥œå¥å¿æºçã§ãã£ã±ã£ãŽãŒããã€ãäœãé¢çœãããšãæ¢ããŠ
ð€ã®èªå°Ÿããã£ã±ã£ãŽãŒã«ãªã£ãŠããŸã£ãŠããŸããããã¯ãã®ïŒäŸããããªã£ãŠããã ãã§ã¯ãªãããã®ã¢ãã«ã®ð€åã¯åžžã«ãã³ã³ãã«ãªã£ãŠããŸã£ãŠããŸãã
ð€åã®ãã³ã³ãå ·åã確èªããããã«èªå°Ÿè¿œåŸã«é¢ããæ··åè¡åã瀺ããŸããå·ŠãIPO (trl0.7.10)ã®çµæã§ãå³ãIPO (trl0.7.11)ã§ãã
| IPO (trl0.7.10) | IPO (trl0.7.11) |
|---|---|
![]() |
![]() |
æ¯èŒã®ãããããã€ãã®ã¢ãã«ã«å¯Ÿããã¿ã°ããšã®ç²ŸåºŠ (recall) ãèšç®ããŸãããïŒç²ŸåºŠã¯ïŒåæšè«ããå¹³åå€ã§ããïŒ
| method | ð | ð«¡ | ð€ | ð€ª |
|---|---|---|---|---|
| SFT (2ep) | 0.871 | 0.610 | 0.645 | 0.539 |
| DPO (1.e-5, 0.3) | 0.997 | 0.980 | 0.794 | 0.937 |
| cDPO (0.3) | 0.972 | 0.897 | 0.802 | 0.642 |
| IPO (trl0.7.10) | 0.954 | 0.854 | 0.758 | 0.658 |
| IPO (trl0.7.11) | 0.986 | 0.927 | 0.083 | 0.956 |
| hinge | 0.991 | 0.959 | 0.589 | 0.802 |
| KTO | 0.994 | 0.968 | 0.288 | 0.892 |
ð€ã¯èªå°Ÿã®äžéšãð«¡ãšéè€ããŠããããšãšãããããåŠç¿ããŒã¿ã®äžã§äžçªä»¶æ°ãå°ãªãããšããããã©ã®ææ³ã§ãð€ã®ç²ŸåºŠã¯äœããªã®ã§ããããã¯ãIPO (trl0.7.11)ã§ã®ç²ŸåºŠã®äœãã¯ç°åžžã§ãããŸããhingeãšKTOã§ãð€ã®ç²ŸåºŠãSFTã¢ãã«ãããæªåããŠããŸãã
åçŽã«èšç·Žããšã«ä¹±æ°ã®åœ±é¿ã«ããçµæã®ããªã¢ã³ã¹ã倧ãããããŸããŸæªãçµæãåºãå¯èœæ§ãããããšæããIPO (trl0.7.11)ã®åŠç¿ã¯ããäžåºŠããçŽããŠã¿ãŸãããã粟床ã¯ã»ãšãã©åãã§ããã
ãªãå®è£ ãæ£ãããã®ã«ä¿®æ£ããã¯ãã®IPO (trl0.7.11)ã§ð€ã ãããŸã£ããåŠç¿ã§ããªããªã£ãŠããŸã£ãã®ããéåžžã«è峿·±ãã®ã§ããä»ã®ãšããåå ã¯ããã£ãŠããŸããã
äžèšã®ã¿ã°ããšã®ç²ŸåºŠãèŠããšãä»åã®èªå°Ÿãã³ã³ãããŒã«ãããšãããã€ãããã¬ã ã«ãããŠã¯ãDPOãšcDPOãåªããŠãããšèšãããã§ãã
ãã«ãã¡ã€ã³ãã¥ãŒãã³ã°
æåŸã«ãLoRAã§ã¯ãªããã«ãã¡ã€ã³ãã¥ãŒãã³ã°ã§DPOãè¡ãæ¹æ³ã玹ä»ããŸãã40GB RAMã®GPU1æã§3.6Bãã©ã¡ãŒã¿ã®LLMã®DPOãè¡ãããšãã§ããŸãããã®ããã®ãã€ã³ãã¯3ã€ã§ãã
- DPOTrainerã¯transformersã©ã€ãã©ãªã®éåžžã®Trainerãç¶æ¿ããŠããã®ã§ãTrainerãšåæ§ã«deepspeedã©ã€ãã©ãªãç°¡åã«äœ¿ãããšãã§ããã
- transformersã©ã€ãã©ãªã®LLMã®å€ãã«ã¯FlashAttention2ãå®è£ ãããŠããããããpaddingãè¡ãå Žåã§ã䜿ããããã«ãªã£ãŠããã®ã§ãFlashAttention2ãšDPOTrainerã䜵çšã§ããã
- DPOTrainerã§ã¯åŠç¿å¯Ÿè±¡ã¢ãã«ã®åæéã¿ãåç §ã¢ãã«ãšåãå Žåã¯ãã¡ã¢ãªã«èŒããã¢ãã«ã¯äžã€ã®ã¿ã§æžãã
ïŒçªç®ã®ãã€ã³ãã®FlashAttention2ã«ã€ããŠã¯ãã¡ãã®èšäºã§è§£èª¬ããã®ã§è©³çްã¯çããŸãããAutoModelForCausalLM.from_pretrained()ã®åŒæ°ã«attn_implementation="flash_attention_2"ã远å ããã ãã§FlashAttention2ãæå¹åããããšãã§ãããããããã£ã³ã°ããããšäœ¿ããªããšããFlashAttentionã®åŒ±ç¹ãå
æããå®è£
ã«ãªã£ãŠããã®ã§ãäœãæ°ã«ããã«éåžžã®LLMã®åŠç¿ãè¡ããªããFlashAttentionã®æ©æµãåããããšãã§ããŸãã
ãã ããFlashAttention2ã䜿çšã§ããã®ã¯Ampereãããããæ°ããã¢ãŒããã¯ãã£ã®GPUãªã®ã§ãGoogle colabã§ã¯T4ãšV100 GPUã§ã¯åäœããŸããã
ãŸããããŒãããã¯ã§deepspeedã®ZeROã䜿ãããã®èšå®ãããŸãã
é·ãã®ã§æãç³ãã§ãããŸãã
import os
os.environ["MASTER_ADDR"] = "localhost"
os.environ["MASTER_PORT"] = "9994"
os.environ["RANK"] = "0"
os.environ["LOCAL_RANK"] = "0"
os.environ["WORLD_SIZE"] = "1"
ããã«ä»¥äžãå®è¡ããããšã§ãdeepspeedã®èšå®ãã¡ã€ã«ããã£ã¹ã¯ã«æžãåºããŸãã
%%writefile zero_train.json
{
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16,
"hysteresis": 2,
"min_loss_scale": 1
},
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
},
"scheduler": {
"type": "WarmupLR",
"params": {
"warmup_min_lr": "auto",
"warmup_max_lr": "auto",
"warmup_num_steps": "auto"
}
},
"zero_optimization": {
"stage": 2,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"allgather_partitions": true,
"allgather_bucket_size": 1e9,
"overlap_comm": true,
"reduce_scatter": true,
"reduce_bucket_size": 1e9,
"contiguous_gradients": true
},
"gradient_accumulation_steps": "auto",
"gradient_clipping": "auto",
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto"
}
ããŒã¿ã»ããèªã¿èŸŒã¿
from datasets import load_from_disk
train_dataset = load_from_disk("dpo_train_dataset.hf")
eval_dataset = load_from_disk("dpo_val_dataset.hf")
ããŒã¯ãã€ã¶ç«ã¡äžã
from transformers import AutoTokenizer
model_name = "line-corporation/japanese-large-lm-3.6b"
tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=False)
åç
§ã¢ãã«å
ŒåŠç¿ã¢ãã«ã®åæã¢ãã«ãèªã¿èŸŒã¿ãŸãããã®æãattn_implementation="flash_attention_2"ãæž¡ãããšã§FlashAttention2ãæå¹åããŸãã
import torch
from transformers import AutoModelForCausalLM
sft_model_path = "./line_sft"
model = AutoModelForCausalLM.from_pretrained(
sft_model_path,
attn_implementation="flash_attention_2",
torch_dtype=torch.float16,
device_map="cuda",
)
TrainingArgumentsãšDPOTrainerãèšå®ããŠåŠç¿ãå®è¡ããŸãã
from transformers import TrainingArguments
from trl import DPOTrainer
output_dir = "/content/tmp"
training_args = TrainingArguments(
output_dir=output_dir,
overwrite_output_dir=True,
per_device_train_batch_size=8,
gradient_accumulation_steps=32,
learning_rate=2e-6,
weight_decay=0.01,
num_train_epochs=2,
lr_scheduler_type="constant_with_warmup",
warmup_steps=10,
fp16=True,
save_strategy="no",
logging_steps=4,
remove_unused_columns=False,
report_to="none",
deepspeed="./zero_train.json",
)
dpo_trainer = DPOTrainer(
model=model,
args=training_args,
beta=0.3,
train_dataset=train_dataset,
tokenizer=tokenizer,
max_prompt_length=162,
max_length=512,
loss_type="sigmoid",
label_smoothing=0.0,
precompute_ref_log_probs=True,
)
dpo_trainer.train()
dpo_trainer.save_state()
èšç®ã³ã¹ããæããããã«ãåŠç¿äžã®æ€èšŒãšã¢ãã«ã®ä¿åã¯è¡ã£ãŠããŸããã
èšå®ã¯LoRAã䜿ã£ãæãšã»ãšãã©åãã§ããããã«ãã©ã¡ãŒã¿åŠç¿ã§ã¯ããéé©åãèµ·ããããã£ãã®ã§ãåŠç¿çãLoRAã®æãããå°ããèšå®ããŸããã
LoRAã䜿ã£ãæãšã®äž»ãªéãã¯ã
- DeepSpeedã䜿ãããã«TrainingArgumentsã®åŒæ°
deepspeedã«èšå®ãã¡ã€ã«ã®ãã¹ãäžããŠãã - DPOTrainerã§
precompute_ref_log_probs=TrueãšããŠãã
ãšããïŒç¹ã§ãã
precompute_ref_log_probs=Trueã¯åç
§ã¢ãã«ïŒref_modelåŒæ°ïŒãäžããªããã€ãŸãåŠç¿å¯Ÿè±¡ã®ã¢ãã«ã®åæç¶æ
ãšåç
§ã¢ãã«ãåäžãšããå Žåã«äœ¿çšã§ããæ©èœã§ãã
éåžžã¯åŠç¿äžã«åŠç¿å¯Ÿè±¡ã®ã¢ãã«ãšåç
§ã¢ãã«ã®ïŒã€ã®ã¢ãã«ãã¡ã¢ãªã«èŒããŠããå¿
èŠããããããDPOã¯SFTããå¿
èŠã¡ã¢ãªéãããªã倧ãããªãã®ã§ãããprecompute_ref_log_probs=Trueãšãããšãåç
§ã¢ãã«ã®åºå確çååžãåŠç¿éå§åã«ãã¹ãŠèšç®ããŠããŸããåŠç¿äžã«ã¯åç
§ã¢ãã«ãåŒã³åºãå¿
èŠããªããªãã®ã§ãã¡ã¢ãªã«èŒãã¢ãã«ã¯åžžã«äžã€ãšãªããå¿
èŠã¡ã¢ãªéãåæžãããŸãã
å€å°ã®ãªãŒããŒãããã¯ãããŸãããå¿
èŠã¡ã¢ãªéã¯SFTãšåçšåºŠã«ãªããŸãã®ã§ã40GB RAMã®GPU1æã§ã3.6Bãã©ã¡ãŒã¿ã®LLMã®DPOãè¡ãããšãã§ãããšããããã§ãã
åŠç¿ããŒã¿12,126ä»¶ã«å¯Ÿããæåã«åç §ã¢ãã«ã®ç¢ºçååžãèšç®ããã®ã«3åã»ã©ããã®åŸã®åŠç¿ã¯2ãšããã¯94ã¹ãããã«çŽ74åããããŸããã
æåŸã«ã¢ãã«ãä¿åããŸãã
import gc
import deepspeed
# OOMãé²ãããã«ãã£ãã·ã¥ãã¯ãªã¢
del train_dataset
del dpo_trainer
gc.collect()
deepspeed.runtime.utils.empty_cache()
torch.cuda.empty_cache()
# äžåºŠããŒã«ã«ãã£ã¹ã¯ã«ä¿å
model.save_pretrained("/content/tmp", safe_serialization=False)
# Driveã«ã³ããŒ
!mkdir ./line_dpo_full
!cp -r /content/tmp/* ./line_dpo_full/
ãŸãšã
æ¥æ¬èªLLMã«å¯ŸããŠDPOTrainerã«å®è£
ãããŠããæé©åææ³ãäžéã詊ããŠæ¯èŒããŸããã
粟床æ¯èŒã簡䟿ãã€å®éçã«è¡ãããã«åçŽãªåé¡èšå®ã䜿ã£ãã®ã§ããããŸã§ä»åã®åé¡ã«å¯ŸããŠã¯ãšããäœãæžãã§ãããæŽŸçææ³ãããDPOã®æ¹ãåªããŠãããšããçµæã«ãªããŸãããéé©åãæããããã®ã©ãã«ã¹ã ãŒãžã³ã° (cDPO)ã广çã ãšããããšã確ãããããŸããã
IPOã«é¢ããŠã¯ãå®è£ ãä¿®æ£ããåŸã®ããŒãžã§ã³ã®æ¹ãåŠç¿ãäžæããããªããªã£ãŠããŸãè¬ãæ®ãçµæãšãªããŸããã
ãããã«ãããDPOãšæŽŸçææ³ã¯PPOããã¯ããã«èšç®ã³ã¹ããäœããSFTãšåãæèŠã§å®è¡ã§ããã®ã§ãããŒã«ã«LLMããã¡ã€ã³ãã¥ãŒãã³ã°ããäžã§ã®éžæè¢ãåºãã£ããšæããŸãã
-
ç©çïŒç¹ã«çµ±èšååŠïŒã§ã¯$\beta$ã¯æž©åºŠã®éæ°ãšããŠäœ¿ãããããšãå€ãã®ã§ãææ°ã®è©ã«$\beta$ã®éæ°ãä¹ã£ããã®è¡šåŒã«ã¯ãããéåæããããŸãããã¿ã€ãã§ã¯ãããŸããã â©

