RLHF
RLHF的核心是用人类偏好数据训练奖励模型,以此来引导模型的行为。
openAI之前在这方面的工作:
- 训练奖励模型,让智能体学会在模拟环境后空翻 link Ilya Sutskever MIT讲座2018:OpenAI 元学习与自我对弈
- [1909.08593] Fine-Tuning Language Models from Human Preferences 最早在gpt2上调的版本。这时训练奖励模型还是四个回答选一个(现在一般是二选一)
- [2009.01325] Learning to summarize from human feedback
- Site Unreachable
- [2203.02155] Training language models to follow instructions with human feedback
LLM里的RLHF是用人类偏好数据训练
训练过程如下:
- 让模型M对问题x生成多个回答y。人对每个回答两两排序,就是简单选择自己是更喜欢回答y1还是y2
- 依据人类的偏好数据训练奖励模型R。奖励模型会尝试对每个问答对(x,y)打分,会利用sigmoid函数来估计分高的问答对(x,y1)比分低的问答对(x,y2)被人类喜好的概率是多少。(奖励模型的目标函数,类似elo评分elo分数)
- 根据奖励模型R,利用policy gradient的方法调整模型M的动作,让模型生成的结果增大奖励。
因为是策略梯度,所以要求每一次算梯度时都使用最新的模型M’采样动作。为了能用旧模型M采样的数据多更新几次,ppo使用某种方式约束,让原模型M和当前模型M’输出的策略尽可能不要偏离太多。[[强化学习笔记#基础组成#策略梯度]] - 奖励模型R并不是完美的,它只是在模型M的输出分布上对人类偏好的估计比较准。但是对更新多步后的模型M’的输出上对人类偏好的估计就不一定准了。因此需要在M’的输出上采样,人类标注偏好,然后更新奖励模型R’。
整个过程是on-policy的,具体是两方面:
- 奖励函数的训练是on-policy的(不然不准)
- 模型M用policy gradient调整输出的时候是on-policy的
人类偏好训练奖励函数
- 训练奖励函数
- 人类的偏好由下面的概率
来描述,最小化上面这个目标函数得到的最优的 就可以表示人的偏好。
因为
调整模型以最大化奖励函数
强化学习问题设置
- 目标函数是
- 其中第一项是要最大化奖励模型的值,第二部分用KL散度约束当前策略和参考策略之间的距离不要太远。
- 而
,可以合并到前一项去。 - 如果将后面的KL散度约束和前一项合并,也可以说是采用了新的奖励函数
. 那么目标函数就是 - 这个最大化奖励也可以写成最大化一个KL散度的形式,从而求出解析解。(见DPO
这里的强化学习其实有几个问题:
- 为什么是
?为什么不是 呢?ppo论文里的kl-penalty就是后者,暂时不知道有啥区别。后者还是从参考策略里采样呢。可能用前者是为了方便合并到奖励函数里吧。 - 需要kl散度约束的原因是奖励函数不够完美,它只在
的输出上表现比较好。当 被多次更新之后,奖励函数的准确性会下降。但这个约束不是强化学习也不是ppo,只是比较像。 - 奖励函数其实不能简单的写作
,应该是 . 在策略梯度的推导中(见直接优化策略函数(Policy Gradient)),我们是对 求梯度,那里假设奖励与 无关,这里的”奖励“与 有关,因此出于严谨还是应该另外推一下。
目标是
先对
再对
其中第二项
所以
推出来结果是一样的,总觉得是不是openai他们一开始就有意设计成这样的?
策略梯度和ppo推导
上面是把生成的回答序列y视作一个动作,这在推导上是没问题的。因为这种单轮的rlhf本来就不涉及与外界的交互,因此无论把一个序列视作动作,还是一个token视作动作,都是可以的。
但是生成token是序列决策问题,它还涉及一个credit assignment的问题,就是搞清楚各个token对最终奖励的贡献有多大,对贡献大的token加大力度奖励。这就是要去做好每个token的优势函数的估计。
这里把
如何估计优势函数我们先跳过,假如优势函数是
这里估计的梯度,每更新一次,都要从最新策略里重新采样。为了能在相同的数据上多更新几次,就需要ppo-clip啦。
梯度可以被近似成下面这样,
对应的代理目标函数就是
然后使用clip来约束
然后对
优势函数估计
这里其实是最微妙的地方。可以有很多种用奖励估计优势函数的方法。查阅了openrlhf里ppo的代码,总结如下。
- kl散度带来的“奖励”被视为对token的奖励,和结尾对整个句子的奖励合并在一起。使用GAE估计优势函数。而用GAE估计优势函数意味着
- 当前token往后所看到的奖励都是打折扣的
- 需要训练critic网络来估计价值。critic网络的目标则是使用类似GAE的方法估计出来当前状态的价值,然后以此为目标训练
有几个问题:
- kl散度带来的”奖励“和整个句子末尾的奖励合在一起合理吗?之后token的kl散度奖励可以忽略掉吗?效果如何?
而这种情况下的最优策略不需要强化学习,可以解析的通过奖励函数和KL散度约束表示出来。反过来,就可以用当前策略表示出奖励函数,然后代入到优化奖励函数的式子里,从而直接优化当前策略。
就连openAI自己也知道这个最优策略可以写出来。它们的[1909.08593] Fine-Tuning Language Models from Human Preferences中有这样一段
最优策略
既然通过奖励模型拒绝采样出来的结果就是对应的最优策略
如何实现
训练技巧
大佬的实践经验总结:
如何正确复现 Instruct GPT / RLHF?
Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.
自己总结一下:
- 把kl散度并入奖励
- 在算每个动作的kl散度奖励时,用Approximating KL Divergence 提到的无偏低方差kl散度估计器估计。(草…这合理嘛。这其实是启发式的把上文推导中每个token的
视作一个单样本的对 的估计,因此可以被替换成另一个估计器)code
- 在算每个动作的kl散度奖励时,用Approximating KL Divergence 提到的无偏低方差kl散度估计器估计。(草…这合理嘛。这其实是启发式的把上文推导中每个token的
- 用GAE来估计优势函数,实践中设置
,也就是折扣为 的 reward-to-go - V(t). V(t)不一定准,作为baseline减去 - 添加sft loss。一种说法是避免response distribution 偏移reward model训练数据集的分布太多。另一种说法是保留rl之前的能力
- 用sft后的模型初始化policy model,用reward model初始化critic model
- Adam learning ratetodo
- mini batch update
- value function clip,用clip限制当前价值函数的活动范围不要离旧价值函数太远。用mse拟合当前估计出来的价值
- reward normalization and cliping
- advantage normalization in a batch
- small training epoch,强化学习时只在采样出来的回答上过一遍,即epoch=1. 样本效率真低。据说训练时80%的时间都用于生成回答
- 在一开始训练时冻结actor model,很合理的技巧,因为毕竟要初始化critic model. 不过critic model作为baseline真的用处那么大嘛?
- reward baseline,一种对奖励归一化的方法。是说奖励r(x,y)高,可能是因为问题x的所有回答奖励都偏高,那么有必要对任务x进行归一化。具体说就是减去x对应的平均奖励。应该可以提前算出来。
- 先拒绝采样finetune,然后ppo
RLHF 及其变体 Iterative DPO/RLOO/GRPO/REINFORCE 算法和工程分析
GRPO
[2402.03300] DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models
rl with ai feedback
Constitutional AI: Harmlessness from AI Feedback \ Anthropic
Specific versus General Principles for Constitutional AI \ Anthropic
[2307.12950] RLCD: Reinforcement Learning from Contrastive Distillation for Language Model Alignment
off-policy的正确回答
在看Qwen2.5 math的技术报告时,发现有些题目模型就是做不对,因此强化学习时全是负例。面对这种情况一种方法是 可以过滤掉不会的题目,先用容易的题目训练,然后慢慢加大难度。
仔细想了想,多臂赌博机也存在这种问题。比如说有个动作概率很小,但是奖励很大。那么比起让它大量采样后偶然做出这个动作发现这个奖励,不如直接告诉它做这个动作能有很高的奖励。估计梯度时直接在训练样本里加入这个动作,再乘上当前动作对应概率做拒绝采样即可,即
因此对语言模型来说,我们可以通过:
- 给问题x,输出解答y。y错了,于是告诉它错在哪让它改正,然后输出正确答案y’. 使用(x,y)和(x,y’)一起加入强化学习训练。也就是说不是让它自己采样发现正确回答,而是加入某种提示来得到正确回答。
这里的问题是y’是用生成的,是off-policy的,直接加进去梯度估计不准了。于是同样考虑是否能用拒绝采样,乘一个系数。
在实际训练时,外面的期望都是通过采样获得的。这里可能会有的问题是
如果忽略这一点,就可以假装y’是参考模型
然而语言模型训练时一般 A=reward-to-go - baseline. 而reward-to-go只和轨迹有关。这样的话,不管是什么策略展开出来的轨迹算出来的优势函数,区别都只有baseline(价值函数)…
嘛,总之就是对这种off-policy的回答,A采用和正常轨迹同样的方法去计算。只需要在clip项外面乘一个系数就行了。
不知道自己有没有表述清楚,自己的理解是不是有问题。也不知道是否实用,先记录在这里。
果然还是应该多一点实践的经验才行。
2024/11/14更新:翻johnschulman2的twitter时看到这篇文章。里面采用了和上面一样的分解思路,并据此提供了一种在ppo更新策略时提升batch size的方法(epoch=1)。
[2110.00641] Batch size-invariance for policy optimization
与GAN的相似性
大语言模型是生成器,它的生成结果为一串token。奖励模型是判别器,它给生成结果打分。
用人类偏好训练奖励模型,其实就是训练一个更好的判别器。自己对GAN不是特别熟悉,下面按自己的理解简单做一下对比。
训练图像生成器时,通过采样已知分布的隐藏变量x,生成图像。然后通过奖励模型反向传播,更新生成器的参数以最大化判别器的分数。
那么能不能使用类似GAN的方法训练语言模型呢?
语言模型之所以没有用类似GAN的方式,直接从RM的反向传播中获得梯度的原因可能有以下几点:
- 语言模型的“采样”发生在输出token。这个采样过程是不可微的(大概)。(这里没细想,说不定可以通过将采样过程重参数化或者STE等方式让它可微?)而图像GAN的采样是在神经网络的输入,采样一个已知分布x获得的。
- GAN只适用于奖励模型可微的情况(不过在rlhf这里不是什么大问题)
- 语言模型的采样比较贵,耗时间。为了重复使用之前的采样结果多更新几步,可能还是得ppo(可能?)
如果用了类似GAN的方式去做,可能的好处有:
- 从RM的反向传播中,我们或许可能可以更好的对token做“credit assignment”,即知道哪个token对最终奖励的影响最大。这样就不需要整一个critical model来做信用分配了。(也许不太实用,但或许可以做一些对奖励模型的可解释性工作?)
最后简单搜索了一下相关论文,放在下面:
APO|利用_GAN_的思想训练_RLHF_中的RM
看评论区对喷好有意思。
这是使用gpt-4的回复作为金标准,训练判别器区分gpt-4的回复和自己的回复。
然后调整llm生成器的方法就可以使用ppo,dpo等方法。
但我上面的想法是用类似GAN的方式调整llm生成器,所以还是有些不同。