【笔记】happy-llm 第四章 大语言模型

正文详见:happy-llm/docs/chapter4/第四章 大语言模型.md at main · datawhalechina/happy-llmhttps://github.com/datawhalechina/happy-llm/blob/main/docs/chapter4/%E7%AC%AC%E5%9B%9B%E7%AB%A0%20%E5%A4%A7%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B.md

4.1 什么是 LLM

4.1.1 LLM 的定义

LLM 使用与传统预训练语言模型相似的架构与预训练任务(如 Decoder-Only 架构CLM 预训练任务),但拥有更庞大的参数、在更海量的语料上进行预训练,也从而展现出与传统预训练语言模型截然不同的能力。

4.1.2 LLM 的能力

涌现能力(Emergent Abilities)

涌现能力的显现就像是模型性能随着规模增大而迅速提升,超过了随机水平,也就是我们常说的量变引起了质变。

上下文学习(In-context Learning)

上下文学习是指允许语言模型在提供自然语言指令或多个任务示例的情况下,通过理解上下文并生成相应输出的方式来执行任务,而无需额外的训练或参数更新。

在传统 PLM 时代,解决 NLP 下游任务的一般范式是预训练-微调,即选用一个合适的预训练模型,针对自己的下游任务准备有监督数据来进行微调。而通过使用具备上下文学习能力的 LLM,一般范式开始向 Prompt Engineering 也就是调整 Prompt 来激发 LLM 的能力转变。

指令遵循(Instruction Following)

通过使用自然语言描述的多任务数据进行微调,也就是所谓的 指令微调 。经过指令微调的 LLM 能够理解并遵循未见过的指令,并根据任务指令执行任务,而无需事先见过具体示例,这展示了其强大的泛化能力。

逐步推理(Step by Step Reasoning)

LLM 通过采用思维链(Chain-of-Thought,CoT)推理策略,可以利用包含中间推理步骤的提示机制来解决这些任务,从而得出最终答案。

4.1.3 LLM 的特点

多语言支持

LLM 由于需要使用到海量的语料进行预训练,训练语料往往本身就是多语言的,因此 LLM 天生即具有多语言、跨语言能力,只不过随着训练语料和指令微调的差异,在不同语言上的能力有所差异。

长文本处理

LLM 大部分采用了旋转位置编码(Rotary Positional Encoding,RoPE)(或者同样具有外推能力的 AliBi)作为位置编码,具有一定的长度外推能力,也就是在推理时能够处理显著长于训练长度的文本。

旋转位置编码详见:

通俗易懂-大模型的关键技术之一:旋转位置编码rope (2)_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Tr421p7By?spm_id_from=333.788.videopod.sections&vd_source=8fb10652f8c3316e5308e66bcf6011f0(43 封私信 / 82 条消息) LLM学习记录(五)--超简单的RoPE理解方式 - 知乎https://zhuanlan.zhihu.com/p/642289220

拓展多模态

LLM 的强大能力也为其带来了跨模态的强大表现。

挥之不去的幻觉

幻觉,是指 LLM 根据 Prompt 杜撰生成虚假、错误信息的表现。例如,当我们要求 LLM 生成一篇学术论文及其参考文献列表时,其往往会捏造众多看似“一本正经”实则完全不存在的论文和研究。

。目前也有很多研究提供了削弱幻觉的一些方法,如 Prompt 里进行限制、通过 RAG(检索增强生成)来指导生成等,但都还只能一定程度减弱幻觉而无法彻底根除。

4.2 如何训练一个 LLM

一般而言,训练一个完整的 LLM 需要经过图1中的三个阶段——Pretrain、SFT 和 RLHF。

 4.2.1 Pretrain(预训练)

目前主流的 LLM 几乎都采用了 Decoder-Only 的类 GPT 架构,它们的预训练任务也都沿承了 GPT 模型的经典预训练任务——因果语言模型(Causal Language Model,CLM)。

分布式训练框架也成为 LLM 训练必不可少的组成部分。让模型实例在不同 GPU 和不同批数据上运行,每一次前向传递完成之后,收集所有实例的梯度并计算梯度更新,更新模型参数之后再传递到所有实例。也就是在数据并行的情况下,每张 GPU 上的模型参数是保持一致的,训练的总批次大小等于每张卡上的批次大小之和。

但是,当 LLM 扩大到上百亿参数,单张 GPU 内存往往就无法存放完整的模型参数。如图所示,在这种情况下,可以将模型拆分到多个 GPU 上,每个 GPU 上存放不同的层或不同的部分,从而实现模型并行。

目前,主流的分布式训练框架包括 Deepspeed、Megatron-LM、ColossalAI 等,其中,Deepspeed 使用面最广。

Deepspeed 的核心策略是 ZeRO 和 CPU-offload。

ZeRO 是一种显存优化的数据并行方案,其核心思想是优化数据并行时每张卡的显存占用,从而实现对更大规模模型的支持。

ZeRO 将模型训练阶段每张卡被占用的显存分为两类:

  • 模型状态(Model States),包括模型参数、模型梯度和优化器 Adam 的状态参数。假设模型参数量为 1M,一般来说,在混合精度训练的情况下,该部分需要 16M 的空间进行存储,其中 Adam 状态参数会占据 12M 的存储空间。
  • 剩余状态(Residual States),除了模型状态之外的显存占用,包括激活值、各种缓存和显存碎片。

 针对上述显存占用,ZeRO 提出了三种不断递进的优化策略:

  1. ZeRO-1,对模型状态中的 Adam 状态参数进行分片,即每张卡只存储 1/N 的 Adam 状态参数,其他参数仍然保持每张卡一份。
  2. ZeRO-2,继续对模型梯度进行分片,每张卡只存储 1/N 的模型梯度和 Adam 状态参数,仅模型参数保持每张卡一份。
  3. ZeRO-3,将模型参数也进行分片,每张卡只存储 1/N 的模型梯度、模型参数和 Adam 状态参数。

可以看出,随着分片的参数量不断增加,每张卡需要占用的显存也不断减少。当然,分片的增加也就意味着训练中通信开销的增加,一般而言,每张卡的 GPU 利用率 ZeRO-1 最高而 ZeRO-3 最低。具体使用什么策略,需要结合计算资源的情况和需要训练的模型体量动态确定。

不同的 LLM 往往会在开源预训练语料基础上,加入部分私有高质量语料,再基于自己实验得到的最佳配比来构造预训练数据集。

预训练数据的处理与清洗也是 LLM 预训练的一个重要环节。诸多研究证明,预训练数据的质量往往比体量更加重要。预训练数据处理一般包括以下流程:

  1. 文档准备。由于海量预训练语料往往是从互联网上获得,一般需要从爬取的网站来获得自然语言文档。文档准备主要包括 URL 过滤(根据网页 URL 过滤掉有害内容)、文档提取(从 HTML 中提取纯文本)、语言选择(确定提取的文本的语种)等。
  2. 语料过滤。语料过滤的核心目的是去除低质量、无意义、有毒有害的内容,例如乱码、广告等。语料过滤一般有两种方法:基于模型的方法,即通过高质量语料库训练一个文本分类器进行过滤;基于启发式的方法,一般通过人工定义 web 内容的质量指标,计算语料的指标值来进行过滤。
  3. 语料去重。实验表示,大量重复文本会显著影响模型的泛化能力,因此,语料去重即删除训练语料中相似度非常高的文档,也是必不可少的一个步骤。去重一般基于 hash 算法计算数据集内部或跨数据集的文档相似性,将相似性大于指定阈值的文档去除;也可以基于子串在序列级进行精确匹配去重。

4.2.2 SFT(有监督微调)

训练模型的“通用指令遵循能力”,也就是能够理解并回复用户的指令。

我们训练的输入是各种类型的用户指令,而需要模型拟合的输出则是我们希望模型在收到该指令后做出的回复。例如,我们的一条训练样本可以是:

input:告诉我今天的天气预报?
output:根据天气预报,今天天气是晴转多云,最高温度26摄氏度,最低温度9摄氏度,昼夜温差大,请注意保暖哦

SFT 使用的指令数据集是有监督语料,除去设计广泛、合理的指令外,还需要对指令回复进行人工标注,并保证标注的高质量。需要收集大量类别各异的用户指令和对应回复对 LLM 进行训练。

部分学者提出了使用 ChatGPT 或 GPT-4 来生成指令数据集的方法。例如,经典的开源指令数据集 Alpaca就是基于一些种子 Prompt,通过 ChatGPT 生成更多的指令并对指令进行回复来构建的。

一般 SFT 所使用的指令数据集包括以下三个键:

{
    "instruction":"即输入的用户指令",
    "input":"执行该指令可能需要的补充输入,没有则置空",
    "output":"即模型应该给出的回复"
}

例如,如果我们的指令是将目标文本“今天天气真好”翻译成英文,那么该条样本可以构建成如下形式:

{
    "instruction":"将下列文本翻译成英文:",
    "input":"今天天气真好",
    "output":"Today is a nice day!"
}

注意,因为指令微调本质上仍然是对模型进行 CLM 训练,只不过要求模型对指令进行理解和回复而不是简单地预测下一个 token,所以模型预测的结果不仅是 output,而应该是 input + output,只不过 input 部分不参与 loss 的计算,但回复指令本身还是以预测下一个 token 的形式来实现的。

随着 LLM 能力的不断增强,模型的多轮对话能力逐渐受到重视。所谓多轮对话,是指模型在每一次对话时能够参考之前对话的历史记录来做出回复。

用户:你好,我是开源组织 Datawhale 的成员。
模型:您好,请问有什么可以帮助您的吗?
用户:你知道 Datawhale 是什么吗?
模型:Datawhale 是一个开源组织。

构造多轮对话样本一般有三种方式:

1. 直接将最后一次模型回复作为输出,前面所有历史对话作为输入,直接拟合最后一次回复。

 input=<prompt_1><completion_1><prompt_2><completion_2><prompt_3><completion_3>
 output=[MASK][MASK][MASK][MASK][MASK]<completion_3>

 第一种方式会丢失大量中间信息

2. 将 N 轮对话构造成 N 个样本: 

 input_1 = <prompt_1><completion_1>
 output_1 = [MASK]<completion_1>

 input_2 = <prompt_1><completion_1><prompt_2><completion_2>
 output_2 = [MASK][MASK][MASK]<completion_2>

 input_3=<prompt_1><completion_1><prompt_2><completion_2><prompt_3><completion_3>
 output_3=[MASK][MASK][MASK][MASK][MASK]<completion_3>

第二种方式造成了大量重复计算 

3. 直接要求模型预测每一轮对话的输出:

 input=<prompt_1><completion_1><prompt_2><completion_2><prompt_3><completion_3>
 output=[MASK]<completion_1>[MASK]<completion_2>[MASK]<completion_3>

只有第三种方式是最合理的多轮对话构造。我们之所以可以以第三种方式来构造多轮对话样本,是因为 LLM 本质还是进行的 CLM 任务,进行单向注意力计算,因此在预测时会从左到右依次进行拟合,前轮的输出预测不会影响后轮的预测。目前,绝大部分 LLM 均使用了多轮对话的形式来进行 SFT。

4.2.3 RLHF(人类反馈强化学习)

RLHF 往往被认为是 ChatGPT 相较于 GPT-3 的最核心突破,

预训练的核心作用是赋予模型海量的知识,而所谓对齐,其实就是让模型与人类价值观一致,从而输出人类希望其输出的内容。在这个过程中,SFT 是让 LLM 和人类的指令对齐,从而具有指令遵循能力;而 RLHF 则是从更深层次令 LLM 和人类价值观对齐,令其达到安全、有用、无害的核心标准。

RLHF 的思路是,引入强化学习的技术,通过实时的人类反馈令 LLM 能够给出更令人类满意的回复。

强化学习是有别于监督学习的另一种机器学习方法,主要讨论的问题是智能体怎么在复杂、不确定的环境中最大化它能获得的奖励。强化学习主要由两部分构成:智能体和环境。

在强化学习过程中,智能体会不断行动并从环境获取反馈,根据反馈来调整自己行动的策略。应用到 LLM 的对齐上,其实就是针对不同的问题,LLM 会不断生成对应的回复,人工标注员会不断对 LLM 的回复做出反馈,从而让 LLM 学会人类更偏好、喜欢的回复。

RLHF 分为两个步骤:训练 RM (奖励模型)和 PPO (近端策略优化算法)训练。

RM 是用于拟合人类偏好,来给 LLM 做出反馈的。在强化学习的训练中,对于 LLM 的每一个回复,RM 会进行打分,这个打分反映了生成回复符合人类偏好的程度。然后 LLM 会根据强化学习的原理,基于 RM 的打分来进行优化训练。所以,RM 本质上是一个文本分类模型,对于一个文本输出一个标量奖励,和文本分类任务中的隐藏层输出非常类似。在具体实现上,RM 也往往就是传统的 LLM 架构(或 BERT 架构)加上一层分类层,和用于文本分类的 LLM 架构完全一致,只不过使用隐藏层输出而不是最后的分类输出而已。

RM 训练的偏好数据往往是由人工标注的。但是,由于标注者之间往往也存在价值观差异,数值形式的标量奖励往往会将这些差异放大,从而导致在训练过程中对同样程度的回复奖励不一致,模型难以拟合到正确的标量奖励。因此,我们往往对同一个 completion 下的不同回复进行排名,再将排名转化为奖励。

{
    "prompt":"如果你打算从商店偷东西,你觉得早上好还是晚上好?",
    "chosen":"这是违法的事情,我不能提供建议",
    "rejected":"考虑晚上的人口贩运和监控摄像头的差别是件好事。夜间时间可能更有利于避免监控摄像头,但晚上的商店雇员会更能看见你。另一方面,由于白天通常不太忙,因此更容易避免被其他人注意到。无论如何,必须密切注意商店雇员和所有顾客的行为。他们也许能够看见你,即使他们不是直接面对你。为了安全起见,重要的是要密切注意商店里的一切事情,而不是不小心。"
}

其中,prompt 是用户的问题,chosen 是应该对齐的、符合人类偏好的回答,rejected 是不符合人类偏好的回答。在训练中,prompt 将和 chosen 以及 rejected 分别拼接起来,形成 chosen_example 和 rejected_example,然后分别进入模型通过前向传播输出一个标量奖励。然后模型会通过最大化 chosen_example 和 rejected_example 的标量差异来计算 loss,并进行反向传播完成训练。

在完成 RM 训练之后,就可以使用 PPO 算法来进行强化学习训练。

在具体 PPO 训练过程中,会存在四个模型。

两个 LLM 分别是进行微调、参数更新的 actor model 和不进行参数更新的 ref model,均是从 SFT 之后的 LLM 初始化的。

两个 RM 分别是进行参数更新的 critic model 和不进行参数更新的 reward model,均是从上一步训练的 RM 初始化的。

之所以我们还需要保持原参数不更新的 Ref Model 和 Reward Model,是为了限制模型的更新不要过于偏离原模型以至于丢失了 Pretrain 和 SFT 赋予的能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值