PPO系列5 - PPO具体实现

涉及多个模型:

HS: Hidden-Size

VS: Vocabulary-Size

奖励模型:事先训练好的。PPO训练期间不发生任何变化。给整个<Question,Answer>句子打1个分数,放到最后1个token的Reward里。

基准模型: PPO期间,该模型也是只读的,不变。确保训练模型和基准模型偏离不要太大。具体通过把二者对相同token的预测分布的KL散度,加到Loss里,实现的。

训练模型、状态价值模型:

二者可共用前面所有层的权重,只是最后一层Head不同。

外层循环:用参考模型采样一个序列(并得到每个token的P'),用状态价值模型得到每个token的状态价值V, 结合Reward打分和KL散度得到的加和Reward,得到每个token的GAE优势。

内层循环:GAE优势和P'保持不变,用训练模型计算该序列,得到每个token的P,加和至PPO loss里;状态价值模型计算该序列,得到每个token的状态价值V,用外循环计算好的Return做label, 计算L2损失,加入V的loss里。这2个loss加和,就是总loss。更新一次模型(训练模型和状态价值模型因为是共享参数,都被更新了)。再进行下一轮内层循环。

减少显存占用

如果同时加载4个大模型的参数,显存占用太大了。

解决:使用LoRA

基准模型是全参的。

训练模型、状态模型:前面所有层,共用同一份LoRA参数;最后一层Head层,各自保留给自的。

奖励模型:用自己的一份LoRA参数和自己的Head。

序列生成任务和强化学习概念的对应关系:

State: 已经生成的第1~t个token构成的序列;

Action: 即将生成的下一个token;

Reward: 奖励模型给出的分数,是给到最后1个token(前面的token都给0);和基准模型分布的KL散度,给到每个token。

KL*(-0.2) + Score ==> Reward

GAE优势

实际代码中,从后往前递推来计算:

GAE优势,用在了2处:1. 状态价值V的loss计算中(做V的label)。2.action的loss计算中(做优势)。

状态价值

每个token都有1个V。

如何计算状态价值?3种方式:

蒙特卡洛法,用1次采样序列,方差太大;

时序差分法,用1步采样,受V函数的准确性,偏差太大;

PPO里使用GAE,即广义优势法,平衡考虑了方差和偏差。

状态价值Loss的代码:

L2平方误差损失函数。

原始的PPO loss:

代码实现对公式的改动:

重要性采样、GAE、P_{\theta '},用的都是训练模型、价值状态模型,只在外层循环计算一次;内层循环复用之。

扔掉第2项。

最终的PPO loss:

用到3个模型:

一直只读保持不变的基准模型\theta ',之产生每个token的概率分布,和\theta ''的分布,计算KL散度,放到Reward里,计算GAE使用。

训练模型\theta,会在内层循环进行更新,即多次更新。

重要性采样模型\theta '',在外层循环开头,赋值为和当时的训练模型\theta相等(这就确保了和训练模型始终保持相差不大),并采样序列、计算GAE、计算P_{\theta ''}

总的loss = 状态价值V的loss + PPO的loss

代码实现:

batch_all_probs: 每个token的概率分布,计算KL散度使用。

batch_probs: 每个token的生成概率,即P。

batch_all_values: 每个token的状态价值V。

huggingface的trl库

创建模型

model_path: 基准模型

reward_adapter: reward模型。复用共享基准模型的参数,只有最后head层是自己的

peft_config: 状态价值模型+训练模型。复用共享基准模型的参数,且只有1套LoRA参数,2个Head。

重要性采样模型,生成answer:

用reward模型,对每个句子进行打分:

用PPOTrainer,传入query、answer、reward分数,更新训练模型和状态价值模型(二者复用前面层的参数):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值