DeepSpeed-Chat强化学习策略
背景
ChatGPT出现后,已经有许多开源项目尝试复现其效果,包括LLaMa、DeepSpeed-Chat、ColossalChat、ChatGLM等。其中DeepSpeed-Chat是微软Deep Speed团队的开源项目,其完整的提供了Supervised Fine-tuning、Reward Model Training、RLHF PPO Traing三阶段的代码,逻辑简单,模块划分清晰,另外也由于Deep Speed在大模型训练中的使用非常普遍,所以笔者近期正在研究DeepSpeed-Chat的代码。之前博客中已经介绍了全部三阶段的训练实战情况:
本文以DeepSpeed-Chat的实现为例,详细介绍下RLHF——基于人类反馈的强化学习策略,并与经典Off-Policy Actor-Critic策略做对比。
符号定义
Off-Policy Advantage Actor-Critic标准范式
Off-Policy策略,在老版本参数
标准Advantage Actor-Critic强化学习中,
其中Actor模型的Loss为:
DeepSpeed-Chat强化学习策略
DeepSpeed-Chat和ColossalChat强化学习部分的策略借鉴了TRLX开源项目。从InstructGPT论文和一些开源复现中,可以推测出ChatGPT对于step和episode的定义。每次预估下一个token是一个step,完成一个完整response是一个episode。
Reward设计
每个episode获得一个收益
def compute_rewards(self, prompts, log_probs, ref_log_probs, reward_score, action_mask):
kl_divergence_estimate = -self.kl_ctl * (log_probs - ref_log_probs)
rewards = kl_divergence_estimate
start = prompts.shape[1] - 1 # 状态s_1在prompt最后一个token,动作a_1表示预测response的第一个token
ends = start + action_mask[:, start:].sum(1)
reward_clip = torch.clamp(reward_score, -self.clip_reward_value, self.clip_reward_value)
batch_size = log_probs.shape[0]
for j in range(batch_size):
rewards[j, start:ends[j]][-1] += reward_clip[j] # 在最后一个token加reward_score
return rewards
Advantage设计
在标准的Advantage Actor-Critic策略中,def get_advantages_and_returns(self, values, rewards, start):
lastgaelam = 0
advantages_reversed = []
length = rewards.size()[-1]
for t in reversed(range(start, length)): # 反向计算
nextvalues = values[:, t + 1] if t < length - 1 else 0.0
delta = rewards[:, t] + self.gamma * nextvalues - values[:, t]
lastgaelam = delta + self.gamma * self.lam * lastgaelam
advantages_reversed.append(lastgaelam)
advantages = torch.stack(advantages_reversed[::-1], dim=1) # 再反转
returns = advantages + values[:, start:] # adv(t) + value(t+1)更合理些
return advantages.detach(), returns
Actor Model
Actor模型以SFT模型初始化,其损失函数设计与标准Actor-Critic有个不同点,
def actor_loss_fn(self, logprobs, old_logprobs, advantages, mask):
log_ratio = (logprobs - old_logprobs) * mask
ratio = torch.exp(log_ratio)
pg_loss1 = -advantages * ratio
pg_loss2 = -advantages * torch.clamp(ratio, 1.0 - self.cliprange, 1.0 + self.cliprange)
pg_loss = torch.sum(torch.max(pg_loss1, pg_loss2) * mask) / mask.sum()
return pg_loss
Critic Model
Critic模型以Reward Model初始化,其损失函数为模型预估值
def critic_loss_fn(self, values, old_values, returns, mask):
values_clipped = torch.clamp(values, old_values - self.cliprange_value, old_values + self.cliprange_value)
vf_loss1 = (values - returns)**2
vf_loss2 = (values_clipped - returns)**2
vf_loss = 0.5 * torch.sum(torch.max(vf_loss1, vf_loss2) * mask) / mask.sum()
return vf_loss
DeepSpeed-Chat强化学习训练逻辑
训练逻辑是Off-Policy策略,外层循环读取prompt数据生成prompt+response数据放入样本池,内层循环从样本池中读取prompt+response数据进行Actor Model和Critic Model的训练。性能上,SFT模型放到CPU上,Actor模型通过DeepSpeed Hybrid Engine支持训练和推理两种模式的高效切换。 另外,Instruct论文中在Actor Loss中增加了一个SFT Loss和一个Unsupervised Loss,两个Loss也加到之前的Actor Loss上。
最终的Actor Loss为:
def generate_experience(self, prompts, mask): |