文章来源:https://huggingface.co/blog/stackllama
StackLLaMA: A hands-on guide to train LLaMA with RLHF
ChatGPT、GPT-4和Claude等模型是功能强大的语言模型,已使用一种称为人类反馈强化学习 (RLHF) 的方法进行了微调,以更好地符合我们期望它们的行为方式并希望使用它们.
在这篇博文中,我们展示了训练LlaMa 模型以使用 RLHF 通过以下组合回答Stack Exchange上的问题所涉及的所有步骤:
监督微调 (SFT)
奖励/偏好建模 (RM)
从人类反馈中强化学习 (RLHF)
来自 InstructGPT 论文:Ouyang, Long, et al. “训练语言模型以遵循人类反馈的指令。” arXiv 预印本 arXiv:2203.02155 (2022)。
通过结合这些方法,作者发布了 StackLLaMA 模型。该模型可在🤗 Hub上获得(有关原始 LLaMA 模型,
LLaMA模型
在进行 RLHF 时,重要的是从一个有能力的模型开始:RLHF 这一步只是一个微调步骤,可以使模型与我们想要与之交互的方式以及我们期望它的响应方式保持一致。因此,我们选择使用最近推出的高性能LLaMA 模型。LLaMA 模型是 Meta AI 开发的最新大型语言模型。它们的大小从 7B 到 65B 不等,并接受了 1T 到 1.4T 令牌的训练,使它们非常有能力。我们使用 7B 模型作为以下所有步骤的基础!要访问该模型,请使用Meta AI 中的表单。
StackExchange 数据集
收集人类反馈是一项复杂而昂贵的工作。为了在构建有用模型的同时引导此示例的过程,我们使用了StackExchange 数据集。该数据集包括来自 StackExchange 平台的问题及其相应的答案(包括针对代码和许多其他主题的 StackOverflow)。这个用例很有吸引力,因为答案与赞成票的数量和已接受答案的标签一起出现。
We follow the approach described in( Askell et al. 2021) and assign each answer a score:
score = log2 (1 + upvotes)
rounded to the nearest integer, plus 1 if the questioner accepted the answer (we assign a score of −1 if the number of upvotes is negative).
高效的训练策略
即使训练最小的 LLaMA 模型也需要大量内存。一些快速数学运算:在 bf16 中,每个参数使用 2 个字节(在 fp32 中使用 4 个字节)以及使用的 8 个字节,例如,在 Adam 优化器中(有关更多信息,请参阅 Transformers 中的性能文档)。因此,一个 7B 参数模型将(2+8)*7B=70GB仅用于适应内存,并且在计算注意力分数等中间值时可能需要更多。因此,即使像这样,您也无法在单个 80GB A100 上训练模型。您可以使用一些技巧,例如更高效的半精度训练优化器,将更多内存挤入内存,但迟早会用完。
另一种选择是使用参数高效微调 (PEFT) 技术,例如peft可以对以 8 位加载的模型执行低秩自适应 (LoRA) 的库。
线性层的低秩自适应:在冻结层(蓝色)旁边添加额外参数(橙色),并将生成的编码隐藏状态与冻结层的隐藏状态一起添加。
以 8 位加载模型会大大减少内存占用,因为每个参数只需要一个字节用于权重(例如,7B LlaMa 的内存为 7GB)。LoRA 不是直接训练原始权重,而是在某些特定层(通常是注意力层)之上添加小的适配器层;因此,可训练参数的数量大大减少。
在这种情况下,经验法则是为每十亿个参数分配 ~1.2-1.4GB(取决于批量大小和序列长度)以适应整个微调设置。正如上面附带的博客文章中所详述的,这可以以低成本微调更大的模型(在 NVIDIA A100 80GB 上高达 50-60B 比例模型)。
这些技术可以在消费设备和 Google Colab 上微调大型模型。值得注意的演示是微调facebook/opt-6.7b(13GB in float16)和openai/whisper-largeGoogle Colab(15GB GPU RAM)。要了解有关使用 的更多信息peft,请参阅我们的github 存储库或之前关于在消费类硬件上训练 20b 参数模型的博文( https://huggingface.co/blog/trl-peft ))。
现在我们可以将非常大的模型放入单个 GPU 中,但训练速度可能仍然很慢。这种情况下最简单的策略是数据并行:我们将相同的训练设置复制到不同的 GPU 中,并将不同的批次传递给每个 GPU。有了这个,您可以并行化模型的前向/后向传递,并根据 GPU 的数量进行扩展。
我们使用transformers.Traineror accelerate,它们都支持数据并行性而无需任何代码更改,只需在使用torchrunor调用脚本时传递参数即可accelerate launch。下面分别用accelerate和在单台机器上运行带有 8 个 GPU 的训练脚本torchrun。
accelerate launch --multi_gpu --num_machines 1 --num_processes 8 my_accelerate_script.py
torchrun --nnodes 1 --nproc_per_node 8 my_torch_script.py
监督微调
在我们开始训练奖励模型并使用 RL 调整我们的模型之前,如果该模型在我们感兴趣的领域已经很好,它会有所帮助。在我们的例子中,我们希望它回答问题,而对于其他用例,我们可能希望它遵循说明,在这种情况下,指令调整是个好主意。实现这一目标的最简单方法是继续使用来自领域或任务的文本的语言建模目标来训练语言模型。StackExchange 数据集非常庞大(超过 1000 万条指令),因此我们可以轻松地在其中的一个子集上训练语言模型。
在进行 RLHF 之前微调模型没有什么特别之处——它只是我们在此处应用的预训练的因果语言建模目标。为了有效地使用数据,我们使用了一种称为打包的技术:我们不是在批处理中为每个样本使用一个文本,然后填充到模型的最长文本或最大上下文,而是将大量文本与 EOS 标记连接在一起之间和剪切上下文大小的块以填充批处理而没有任何填充。
使用这种方法,训练效率更高,因为通过模型传递的每个标记也经过训练,这与通常掩盖损失的填充标记不同。如果您没有太多数据并且更关心偶尔切断一些溢出上下文的标记,您也可以使用经典数据加载器。
包装由 处理,然后我们可以在使用 加载模型后ConstantLengthDataset使用。首先,我们在 int8 中加载模型,准备训练,然后添加 LoRA 适配器。Trainerpeft
# load model in 8bit
model = AutoModelForCausalLM.from_pretrained(
args.model_path,
load_in_8bit=True,
device_map={"": Accelerator().local_process_index}
)
model = prepare_model_for_int8_training(model)
# add LoRA to model
lora_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
model = get_peft_model(model, config)
我们使用因果语言建模目标训练模型几千步并保存模型。由于我们将根据不同的目标再次调整模型,因此我们将适配器权重与原始模型权重合并。
免责声明:由于 LLaMA 的许可,我们仅发布此适配器权重和以下部分中的模型检查点。您可以通过填写 Meta AI 的表单申请访问基础模型的权重,然后通过运行此脚本将它们转换为 🤗 Transformers 格式。请注意,在发布之前,您还需要从源代码安装 🤗 Transformers v4.28。
现在我们已经为任务微调了模型,我们准备好训练奖励模型了。
奖励建模和人类偏好
原则上,我们可以直接使用 RLHF 和人工注释来微调模型。然而,这将需要我们在每次优化迭代后将一些样本发送给人类进行评级。由于收敛所需的训练样本数量以及人类阅读和注释器速度的固有延迟,这是昂贵且缓慢的
一个代替直接反馈效果很好的技巧是在 RL 循环之前收集的人类注释上训练奖励模型。奖励模型的目标是模仿人类如何评价文本。建立奖励模型有几种可能的策略:最直接的方法是预测注释(e.g. a rating score or a binary value for “good”/”bad”).
在实践中,更好的方法是预测两个例子的排名,其中奖励模型有两个候选者(yi,yk)对于给定的提示X并且必须预测哪一个会被人类注释者评为更高。
使用 StackExchange 数据集,我们可以根据分数推断用户更喜欢这两个答案中的哪一个。有了这些信息和上面定义的损失,我们就可以transformers.Trainer通过添加自定义损失函数来修改。
class RewardTrainer(Trainer):
def compute_loss(self, model, inputs, return_outputs=False):
rewards_j = model(input_ids=inputs["input_ids_j"], attention_mask=inputs["attention_mask_j"])[0]
rewards_k = model(input_ids=inputs["input_ids_k"], attention_mask=inputs["attention_mask_k"])[0]
loss = -nn.functional.logsigmoid(rewards_j - rewards_k).mean()
if return_outputs:
return loss, {"rewards_j": rewards_j, "rewards_k": rewards_k}
return loss
我们利用 100,000 对候选人的一个子集,并评估 50,000 对保留的集合。在适度的训练批量大小为 4 的情况下,我们使用具有 BF16 精度的 Adam 优化器使用 LoRApeft适配器针对单个时期训练 LLaMA 模型。我们的 LoRA 配置是:
peft_config = LoraConfig(
task_type=TaskType.SEQ_CLS,
inference_mode=False,
r=8,
lora_alpha=32,
lora_dropout=0.1,
)
从人类反馈中强化学习
有了经过微调的语言模型和奖励模型,我们现在可以运行 RL 循环了。大致分为三个步骤:
根据提示生成响应
使用奖励模型对响应进行评分
使用评级运行强化学习策略优化步骤
SFT、RM 和 RLHF 阶段使用相同的模板。
使用 RL 训练语言模型的一个常见问题是,该模型可以通过生成完整的乱码来学习利用奖励模型,这会导致奖励模型分配高奖励。为了平衡这一点,我们在奖励中增加了一个惩罚:我们保留了我们不训练的模型的参考,并通过计算 KL 散度将新模型的生成与参考模型进行比较:
再一次,我们利用peft内存高效训练,这在 RLHF 上下文中提供了额外的优势。在这里,参考模型和策略共享相同的基础,即 SFT 模型,我们以 8 位加载并在训练期间冻结。我们使用 PPO 专门优化策略的 LoRA 权重,同时共享基本模型的权重。文章来源:https://www.toymoban.com/news/detail-484221.html
for epoch, batch in tqdm(enumerate(ppo_trainer.dataloader)):
question_tensors = batch["input_ids"]
# sample from the policy and generate responses
response_tensors = ppo_trainer.generate(
question_tensors,
return_prompt=False,
length_sampler=output_length_sampler,
**generation_kwargs,
)
batch["response"] = tokenizer.batch_decode(response_tensors, skip_special_tokens=True)
# Compute sentiment score
texts = [q + r for q, r in zip(batch["query"], batch["response"])]
pipe_outputs = sentiment_pipe(texts, **sent_kwargs)
rewards = [torch.tensor(output[0]["score"] - script_args.reward_baseline) for output in pipe_outputs]
# Run PPO step
stats = ppo_trainer.step(question_tensors, response_tensors, rewards)
# Log stats to WandB
ppo_trainer.log_stats(stats, batch, rewards)
们使用 🤗 研究集群在 3x8 A100-80GB GPU 上训练了 20 小时,但您也可以更快地获得不错的结果(例如,在 8 个 A100 GPU 上训练约 20 小时后)
文章来源地址https://www.toymoban.com/news/detail-484221.html
到了这里,关于StackLLaMA: A hands-on guide to train LLaMA with RLHF的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!