核心内容摘要
达摩院RTS技术入门:人脸识别OOD模型功能全解析
本文详细解读OpenAI的RLHF奠基论文介绍通过三步训练InstructGPT
SFT阶段用13k人工标注数据微调GPT-
训练RM模型对response打分
使用PPO算法优化LLM。
实验表明
3B参数的InstructGPT效果优于175B GPT-3文章提供完整代码实现帮助理解如何将强化学习应用于大模型训练使其更好遵循人类指令。
方案概述作者基于GPT-3模型使用RLHF训练得到的模型称为InstructGPT
3B的InstructGPT效果比175B的GPT-3效果更好。
训练分为三个步骤如下图step1: SFT阶段使用人工精标的数据微调GPT-3step2: 训练RM模型对同一个prompt得到的不同response进行打分属于回归模型。
输入是一个prompt一个response输出是一个float值。
但是样本label并没有直接标注这个float值而是人工标注的同一个response下的两个response哪个更好因此RM模型学的是pair loss。
但是RM模型的输出值仍然可以作为评估response好坏的一个分数。
step3: 这步没有用标注数据而是直接用的prompt由LLM根据这个prompt自己生成response然后用RM模型对这个response打分作为reward使用PP0算法优化这个LLM。
数据一共三份数据对应上面的三个步骤step1: SFT数据就是精标的prompt-response对共13k对step2: RM模型的训练集33k个prompt每个prompt会有4个到9个response然后人工对同一个prompt下面的response任选两个标注哪个更好。
step3: PPO算法的训练集31k个prompt。
模型
1 首先是两个模型的介绍SFT模型在GPT-3上微调RM模型在SFT模型的基础上移除最后一个非emb层对promptresponse输出一个scalar分数这里使用了6B参数量的版本。
loss如下就是pairwise loss其中K是同一个prompt下的response数。
注意这里为了提高训练速度和稳定性同一个prompt下的多个response会组在同一个batch内这样可以避免数据穿越并且可以减少对同一个prompt同一个response计算多次。
最终作为reward去训练PPO之前会按照batch对RM的输出分数统一减去一个全局bias其实就是减去所有reward的均值0均值这样训练更稳定。
因为原始RM模型输出的分数没有绝对值的物理含义只有相对含义均值就意味着基准模型的平均好坏减去均值就意味着这个response对比基准是更好还是更坏这样更具有物理含义另外数值上避免了很大的数或者很小的数数值上也更加稳定。
2 最核心的PPO算法流程这里面其实包括4个模型policy模型就是要微调的LLM初始化自SFT模型在RL里面充当agent的角色。
SFT模型这里充当PPO算法中的old policy的角色参数不更新作用是通过KL散度约束微调后的模型不要偏离原模型太远。
RM模型对一个episode的训练样本(promptresponse)进行打分参数不更新其实充当的是RL中的environment的角色。
状态价值模型初始化自SFT模型参数会更新对当前转态价值进行评估。
prompt就是初始状态后面response的每个token都是一个状态。
RLHF的概念和通用RL的概念映射关系如下图这里的PPO算法加了KL散度的约束即时奖励r(t)就是单步token的kl散度值最后一个状态的奖励是KL散度RM模型的输出。
因为只有最后一步的奖励是真正用于改善LLM效果的其他步的奖励是为了不让模型跑太偏因此这里训练需要一条完整的episode数据也就是生成一个完整的response作为一个样本。
评估如下图为不同版本模型对比175B的SFT模型的效果图可以看出来即时是更少参数量的PPO版本模型也要好得多。
代码demo参考代码库https://github.com/huggingface/trl
1 数据和模型这里参考https://github.com/huggingface/trl/blob/main/examples/scripts/ppo/ppo.py首先初始化4个模型跟上面
2节的模型一一对应。
状态价值模型评估当前状态的价值参数在训练过程中会更新 输入prompt当前时刻t生成的response的token 输出一个scalar数value_model AutoModelForSequenceClassification.from_pretrained( training_args.reward_model_path, trust_remote_codemodel_args.trust_remote_code, num_labels1, **model_kwargs, )使用pair loss训练的RM模型充当环境的角色参数不更新 输入prompt完整的response 输出一个scalar数reward_model AutoModelForSequenceClassification.from_pretrained( training_args.reward_model_path, trust_remote_codemodel_args.trust_remote_code, num_labels1, **model_kwargs, )要微调的LLM模型参数会更新policy AutoModelForCausalLM.from_pretrained( training_args.sft_model_path, trust_remote_codemodel_args.trust_remote_code, **model_kwargs )参考模型(SFT模型)参数不更新ref_policy AutoModelForCausalLM.from_pretrained( training_args.sft_model_path, trust_remote_codemodel_args.trust_remote_code, **model_kwargs )数据只有prompt注意这里没有response因为response是用模型生成并且是要优化的目标。
只用prompt dataset_text_field prompt def prepare_dataset(dataset, tokenizer): pre-tokenize the dataset before training; only collate during training def tokenize(element): outputs tokenizer( element[dataset_text_field], paddingFalse, ) return {input_ids: outputs[input_ids]} return dataset.map( tokenize, batchedTrue, remove_columnsdataset.column_names, num_proctraining_args.dataset_num_proc, ) # Compute that only on the main process for faster data processing. # see: https://github.com/huggingface/trl/pull/1255 with PartialState().local_main_process_first(): train_dataset prepare_dataset(train_dataset, tokenizer) eval_dataset prepare_dataset(eval_dataset, tokenizer)
2 PPO训练流程接下来就进入训练逻辑了代码在https://github.com/huggingface/trl/blob/main/trl/experimental/ppo/ppo_trainer.py。
这个训练流程跟标准PPO算法的训练基本一样建议先回顾下标准PPO算法的训练代码。
接下来我们来看下单个batch训练的流程。
1计算即时奖励r(t)和token粒度的价值value先用policy模型根据prompt预测得到responseprompt和这个response后面还会用ref模型中过一遍拿到response每个token的概率分布来做kl散度。
注意这里ref模型不是根据prompt再预测一次得到新的response而是把前面的promptresponse拼接后作为input过一遍模型。
token粒度的kl散度和response粒度的reward一起构成PPO算法中的即时奖励r(t)# policy预测得到responsequery_responses, logitss batch_generation( unwrapped_model.policy, queries, args.local_rollout_forward_batch_size, processing_class.pad_token_id, generation_config, )...# 用SFT模型过一遍得到response的token粒度的概率分布用来做kl散度ref_output forward(ref_policy, query_response, processing_class.pad_token_id) ...# 这里调用的是价值模型value是每个时刻的价值full_value, _, _ get_reward( unwrapped_value_model, query_response, processing_class.pad_token_id, context_length )value full_value[:, context_length - 1 : -1].squeeze(-
# 这里score是完整response的奖励_, score, _ get_reward( reward_model, postprocessed_query_response, processing_class.pad_token_id, context_length )...logr ref_logprobs - logprobskl -logr if args.kl_estimator k1 else (logr.exp() -
- logr # Else statement is k3non_score_reward -args.kl_coef * klrewards non_score_reward.clone()actual_start torch.arange(rewards.size(
, devicerewards.device)actual_end torch.where(sequence_lengths_p1 rewards.size(
, sequence_lengths_p1, sequence_lengths)# 即时奖励r(t)其他token(状态)都是kl散度最后一个token(状态)还会加上RM模型的打分。
rewards[actual_start, actual_end] scores# reward白化减去均值if args.whiten_rewards: rewards masked_whiten(rewards, mask~padding_mask_p1, shift_meanFalse) rewards torch.masked_fill(rewards, padding_mask_p1,
2计算优势函数和target状态价值这里和标准PPO算法的计算方式一致可以回顾下公式plaintextlastgaelam 0advantages_reversed []gen_length responses.shape[1]for t in reversed(range(gen_length)): nextvalues values[:, t 1] if t gen_length - 1 else
0 delta rewards[:, t] args.gamma * nextvalues - values[:, t] lastgaelam delta args.gamma * args.lam * lastgaelam # 状态优势在当前动作采用动作a后得到的价值比当前状态所有动作平均价值的差值 advantages_reversed.append(lastgaelam)advantages torch.stack(advantages_reversed[::-1], axis
# 这个是V(targ)可以从定义上来理解状态优势状态价值未来收益期望returns advantages valuesadvantages masked_whiten(advantages, ~padding_mask)advantages torch.masked_fill(advantages, padding_mask,
* 3loss 上面的步骤都属于Rollout 阶段也就是主要是为了生成一个batch的数据这里才是更新模型的阶段。
注意上面的一个batch的数据在这里会使用多次进行多个batch的更新。
plaintext 训练启动后价值模型和policy模型都会变化因此这里每步都用最新的policy模型和价值模型重新生成response的token概率和状态价值。
output, vpred_temp forward(model, mb_query_responses, processing_class.pad_token_id)logits output.logits[:, context_length - 1 : -1]logits / args.temperature 1e-7new_logprobs selective_log_softmax(logits, mb_responses)new_logprobs torch.masked_fill( new_logprobs, padding_mask[micro_batch_inds], INVALID_LOGPROB)vpred vpred_temp[:, context_length - 1 : -1].squeeze(-
vpred torch.masked_fill(vpred, padding_mask_p1[micro_batch_inds],
vpredclipped torch.clamp( vpred, mb_values - args.cliprange_value, mb_values args.cliprange_value,)vf_losses1 torch.square(vpred - mb_return)vf_losses2 torch.square(vpredclipped - mb_return)主要更新价值模型这里的max同样是不想让价值模型剧烈变化。
当新价值比老价值偏差不大的时候两者相等就是标准的价值函数当新价值比老价值偏差大的时候1如果跟目标真实回报mb_return偏差也很大就会用loss1也就是惩罚新价值2如果跟目标真实回报偏差很小就会用loss2因为梯度截断这里就不回有惩罚。
vf_loss_max torch.max(vf_losses1, vf_losses
vf_loss
5 * masked_mean(vf_loss_max, ~padding_mask_p1[micro_batch_inds])vf_clipfrac masked_mean( (vf_losses2 vf_losses
.float(), ~padding_mask_p1[micro_batch_inds])# 这里是Clipped Surrogate Objective部分主要更新policy参数logprobs_diff new_logprobs - mb_logprobsratio torch.exp(logprobs_diff)pg_losses -mb_advantage * ratiopg_losses2 -mb_advantage * torch.clamp(ratio,
0 - args.cliprange,
0 args.cliprange)pg_loss_max torch.max(pg_losses, pg_losses
pg_loss masked_mean(pg_loss_max, ~padding_mask[micro_batch_inds])loss pg_loss args.vf_coef * vf_loss如何学习AI大模型如果你对AI大模型入门感兴趣那么你需要的话可以点击这里大模型重磅福利入门进阶全套104G学习资源包免费分享这份完整版的大模型 AI 学习和面试资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】这是一份大模型从零基础到进阶的学习路线大纲全览小伙伴们记得点个收藏第一阶段从大模型系统设计入手讲解大模型的主要方法第二阶段在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用第三阶段大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统第四阶段大模型知识库应用开发以LangChain框架为例构建物流行业咨询智能问答系统第五阶段大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型第六阶段以SD多模态大模型为主搭建了文生图小程序案例第七阶段以大模型平台应用与开发为主通过星火大模型文心大模型等成熟大模型构建大模型行业应用。
100套AI大模型商业化落地方案大模型全套视频教程200本大模型PDF书籍学会后的收获• 基于大模型全栈工程实现前端、后端、产品经理、设计、数据分析等通过这门课可获得不同能力• 能够利用大模型解决相关实际项目需求 大数据时代越来越多的企业和机构需要处理海量数据利用大模型技术可以更好地处理这些数据提高数据分析和决策的准确性。
因此掌握大模型应用开发技能可以让程序员更好地应对实际项目需求• 基于大模型和企业数据AI应用开发实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能 学会Fine-tuning垂直训练大模型数据准备、数据蒸馏、大模型部署一站式掌握• 能够完成时下热门大模型垂直领域模型训练能力提高程序员的编码能力 大模型应用开发需要掌握机器学习算法、深度学习框架等技术这些技术的掌握可以提高程序员的编码能力和分析能力让程序员更加熟练地编写高质量的代码。
LLM面试题合集大模型产品经理资源合集大模型项目实战合集获取方式有需要的小伙伴可以保存图片到wx扫描二v码免费领取【保证100%免费】