0. 导读
最近开始读ds的论文,为了方便巩固知识,记录一下。
总体来说,我想按照 DeepSeek V3 -> DeepSeekMath -> DeepSeek R1的路径来进行讲解。
1. DeepSeek V3
v3 paper:DeepSeek-V3 Technical Report
总的来说,V3主要是三个创新点:
- Multi-Head Latent Attention: 通过下采样-上采样的方式,cache一个比较短维度的潜空间向量,代替缓存维度比较长的KV潜空间向量,从而对KV cache进行优化
- DeepSeekMoE with Auxiliary-Loss-Free Load Balancing:不引入损失函数情况,仅仅通过引入偏置项,解决MoE模型负载不均衡问题
- Multi-Token Prediction:将next token prediction转化为多个token的生成任务,进而提升推理性能,帮助模型快速收敛
接下来详细解读一下各个方法。
1.1 Multi-Head Latent Attention
这部分内容我想沿着 MHA -> KV Cache -> MQA -> GQA -> MLA的路径来讲解,会更清晰一些。
1.1.1 MHA (Multi Head Attention)
多头注意力形式如下:
其公式表示如下:
其中, , 和 是输入矩阵,分别代表查询矩阵,键矩阵和值矩阵, 是向量维度。
以一个长度为4的序列为例,注意力计算过程如下:
在自回归模型中(autoregressive models),会逐个生成文本的每个token,这个过程可能比较慢,因为模型一次只能生成一个token,而且每次新的预测都依赖于之前的上下文。这意味着,要预测第4个token,你需要用到前3个token的信息,这通常涉及到对这些token的表示进行一系列矩阵乘法运算。当序列长度很大时,例如要预测第1001个token,你不仅需要前999个token的信息,还要加上第1000个token的信息,这使得整个QK矩阵非常巨大(1000×1000),进而导致attention的计算量巨大。
1.1.2 KV Cache
KV Cache 是一种优化技术,旨在提高模型在推理阶段的效率。 它通过缓存键(K)和值(V)的值,减少重复计算,从而加速解码器中的矩阵运算。这种技术在处理大规模语言模型时尤为重要,因为它可以显著减少推理时间,尽管会带来额外的内存开销(空间换时间)。后续的 MQA, GQA, MLA 等都是基于KV Cache的改进优化。
为什么只存储K和V,而不存储Q?
- 由于Q是当前时间步的输入,每次生成新token时都会重新计算Q,不需要缓存。
- 而K和V可以复用之前时间步的计算结果,通过缓存K和V,可以避免在每个时间步重新计算它们,从而提升效率。
在实际实验时,每次问答(QA)记录都会增加KV Cache的存储需求,因为模型需要保留之前问答的上下文信息以生成连贯的响应。这种线性增长的内存占用可能会导致在处理长对话或大量问答时,内存需求显著增加,从而影响系统的性能和效率。
由于硬件资源的限制,KV Cache的大小是有限的。当缓存达到其容量上限时,旧的信息可能会被新的信息覆盖或丢弃。其表现为随着问答的进行,早期的对话内容可能会因为KV Cache的容量限制而被移除或覆盖,导致模型逐渐“遗忘”之前的上下文。由于模型无法访问完整的对话历史,其生成的回复可能会变得不够准确或连贯,尤其是在需要依赖早期信息的情况下。所以,在长对话或多轮问答中,模型的性能可能会显著下降,因为它无法有效地利用整个对话历史。
1.1.3 MQA (Multi-Query Attention)
MQA 通过在多个注意力头之间共享同一组K和V,同时为每个注意力头维护不同的Q,减少了计算和内存开销,且不会显著影响模型的性能。
1.1.4 GQA (Group Query Attention)
GQA 是对 Transformer 中使用的传统MHA机制和MQA机制的折中。在标准多头自注意力中,每个注意力头独立处理整个序列。这种方法虽然功能强大,但计算成本高昂,尤其是对于长序列。而MQA虽然通过在多个注意力头之间共享同一组键和值简化了这一过程,但其简化也不可避免的带来了一些精度的损失。GQA 通过将查询分组在一起来解决此问题,从而降低了计算复杂性,而不会显著影响性能。
1.2 MLA (Multi Head Latent Attention)
多头潜在注意力 (MLA) 将潜在特征表示纳入注意力机制,以降低计算复杂度并改善上下文表示。MLA的核心是对KV进行压缩后,再送入标准的MHA算法中,用一个更短的k,v向量来进行计算,进而减少KV Cache的大小。
接下来我们来一步一步看:
- 下采样,计算代表 KV Cache 的潜在向量
- 上采样,计算K和V
- 为K引入位置信息(RoPE)
- 为保证对称性和一致性,相同方式计算Q
- 注意力计算
位置编码为什么不直接加在K上?
- 因为旋转位置编码RoPE与潜向量的计算不兼容,为了同时使用潜向量计算和旋转位置编码RoPE两个技术,只能多创建一个新的向量来编码位置信息,将来通过向量合并将位置信息带入键向量
为什么对于查询向量q,也要进行潜向量的计算?
- 主要是为了特征的对齐,如果只对键 k 和值 v 进行潜在向量计算,而忽略查询 q,会导致 q 和 k、v 的特征空间不一致,影响注意力机制的效果。在注意力机制中,q、k、v是平等的输入,对它们进行相同的潜在向量计算可以保持模型的对称性和一致性。
1.3 DeepSeekMoE with Auxiliary-Loss-Free Load Balancing
首先了解两个概念:
- 稠密模型:每一层中的每个神经元都与其他层中的所有神经元相连。这种全连接的架构确保了信息流的畅通无阻,使得模型能够学习到数据中的复杂关系和模式。
- 稀疏模型:并非每个神经元都与所有其他层的神经元相连。通过减少不必要的连接,稀疏模型能够在保证性能的同时,大幅降低计算资源的需求,提高运行效率。
很明显,拥有MoE架构的DeepSeek模型属于稀疏模型。
1.3.1 DeepSeekMoE
先来看一下DeepSeekMoE的基础架构:
总的来说,DeepSeekMoE架构主要是对FFN层进行了改进,包括两个主要策略:
- 共享专家隔离:隔离某些专家作为始终激活的共享专家,其他专家作为路由专家。共享专家捕获和整合不同上下文中的共同知识,减轻其他路由专家中的冗余,从而提高参数效率,并确保每个路由专家通过专注于独特方面而保持专业化。具体而言:
-
细粒度专家细分:在保持参数数量不变的同时,通过细分FFN的中间隐藏维度,将专家分割成更细的粒度。专家细分允许将不同的知识被更精确地学习以及被更细致地分配到不同的专家,每个专家都将保持更高水平的专业化,有助于更准确和有针对性的知识获取。具体而言:
-
- 每个路由专家和输入向量之间进行相似度计算:
-
- 选取前top k 个
-
- 对topk做归一化
1.3.2 Auxiliary-Loss-Free Load Balancing
为了解决MoE模型所面临的负载不均衡问题,即:有些专家被过度使用,而有些专家使用的较少(和推荐算法MMoE模型的“极化”现象有点像),传统方法使用负载损失来平衡负载不均衡现象,但是复杂度较高,为了解决这个问题,DeepSeek不使用负载损失,而是为每个路由专家添加一个偏置项,具体而言:
注意,这里偏置项仅仅用在选Top k路由专家上,并不参与后续的计算,参与后续计算的还是。
然后,定义一个超参数𝛾,称为偏置更新速度。在每一步结束时如果相应的专家负荷过重,将减少偏差项 𝛾;如果相应的专家负荷不足,将增加偏差项 𝛾。
尽管DeepSeek-V3 主要依赖无辅助损耗策略来实现负载平衡,但为了防止任何单一序列内的极端不平衡,还是采用了一个complementary sequence-wise balance loss。
1.4 Multi-Token Prediction
我们都知道,当前主流的大模型(LLMs)都是decoder-base的模型结构,也就是无论在模型训练还是在推理阶段,对于一个序列的生成过程,都是token-by-token的。每次在生成一个token的时候,都要频繁跟访存交互,加载KV Cache,再通过多层网络做完整的前向计算。对于这样的访存密集型的任务,通常会因为访存效率形成训练或推理的瓶颈。
针对token-by-token生成效率的瓶颈,业界很多方法来优化,包括减少存储的空间和减少访存次数等,进而提升训练和推理性能。这里的MTP方法,也是为了优化训练和推理效率而提出的。
MTP的核心思想是:通过解码阶段的优化,将1-token的生成,转变成multi-token的生成,从而提升训练和推理的性能。具体来说,在训练阶段,一次生成多个后续token,可以一次学习多个位置的label,进而有效提升样本的利用效率,提升训练速度;在推理阶段通过一次生成多个token,实现成倍的推理加速来提升推理性能。
1.4.1 Meta MTP
先来看看 Meta 于2024年4月发表的一篇工作。
paper : Better & Faster Large Language Models via Multi-token Prediction
- 训练阶段:通过预测多步token,迫使模型学到更长的token依赖关系,从而更好理解上下文,避免陷入局部决策的学习模式。同时一次预测多个token,可大大提高样本的利用效率,相当于一次预估可生成多个<predict, label>样本,来更新模型,有助于模型加速收敛。
- 推理阶段:并行预估多个token,可提升推理速度
接下来详细看一下步骤:
- 主干网络就是训练好的decoder-only的多层Transformer的网络, t 个输入token 经过主干网络计算,最终输出隐层表示: (来自于 编码结果)。
- 上面接了多输出Head,每个Head负责预估一个token, 负责预估 next token, 负责预估 next next token, 以此类推
- 在模型训练时,多个头都会并行计算loss时,提升样本利用效率和加速模型收敛
更详细的可以参考这张图:
1.4.2 Deepseek MTP
接下来看看Deepseek是怎么做MTP的,乍看上去也是多头,但结构略复杂。且论文中也强调,在实现上保留了序列推理的连接关系 (causal chain), 如图中,从一个Module链接到后继Module的箭头。
如上图所示,用 D 个顺序的模块,预测 D 个tokens。每个MTP模块的具体结构(如图红框内):
- 输入token首先接入一层共享的embedding layer
- 对于第 个token 和第 个预测深度,首先将第 层的的隐层输出做归一化处理,再对第 位置的token embedding做归一化处理,两个结果进行concat
- 输入到Transformer层,获得第 k 个预测深度的输出
- 将输出通过一个各 Module共享的映射矩阵OutHead 变换,再过 softmax处理,计算出词表 V 维度的输出概率
训练阶段:通过CrossEntropyLoss计算每个MTP Module Head的损失
更详细的细节可以参考这张图:
所以总体而言,DeepSeek 的实现相对于之前 Meta 的方法增加了 causal chain 的连接关系,同时在embedding层增加了残差链接。
2. DeepSeekMath
DeepSeekMath paper:DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models
这篇文章的主要亮点是提出了GRPO,针对PPO进行了一些改进,为了更好的理解GRPO,我想沿着 PPO & RLHF & TRPO -> DPO & Iterative DPO -> RLOO & GRPO的路径来讲解。
- PPO & RLHF & TRPO:基于策略梯度强化学习优化方法
- DPO & Iterative DPO:直接优化偏好,无需奖励模型
- RLOO & GRPO:无需价值函数,优化训练过程
2.1 PPO & RLHF & TRPO
2.1.1 PPO
PPO paper: Proximal Policy Optimization Algorithms
PPO旨在优化策略网络以最大化累计奖励,同时限制新策略与旧策略之间的差异,确保训练过程的稳定性。它通过引入一个近端策略优化目标函数,使得策略更新能够在保证策略改进的同时,避免更新过大导致模型性能下降。
目标函数如下:
接下来,我们详细讲一下PPO的核心机制:
- 重要性采样:目标是复用旧策略收集的数据,提高样本效率,具体的方法则是通过新旧策略的概率比修正旧数据的权重:;
- 裁剪机制:限制新旧策略的概率比的变化范围,防止更新幅度过大。
在PPO中,计算是基于GAE的,而GAE是基于reward和value函数的,因此,在 PPO 中,需要在训练策略模型的同时训练一个价值函数,以减少奖励模型的过度优化,标准方法是在每个标记的奖励中加入来自参考模型的每个标记的 KL 散度惩罚:
2.1.2 RLHF
RLHF paper: Learning to summarize from human feedback
2022年底 OpenAI 的论文 Instruct GPT 引爆了 RLHF 或者目前叫做 Post training 的概念。大体思想是用 Pair-wise 的 Preference Dataset 结合 Ranking Loss 训练一个 RM,然后用 PPO 算法结合此 RM 函数训练 SFT 后的 GPT 模型,实现模型对齐比如提升安全性,数学能力等等。除了这个 RM 是用标注数据训练出来的 ProxyRM,以及加上了一个 KL penalty 约束策略距离外,和传统的 PPO 算法在流程上并没有什么太大区别。
目标函数如下:
但是这个 PPO 算法用到 LLM 上面后也引发了一些问题,其中最为麻烦的就是 PPO 算法需要同时加载4个模型(当前策略模型、旧策略模型、奖励模型、价值模型),并且在一个系统中同时存在模型推理加速(PPO样本生成)和模型训练加速的问题,在模型规模巨大今天,这让 AI Infra 的实现和优化变得尤为挑战。
2.1.3 TRPO
TRPO paper:Trust Region Policy Optimization
TRPO(信任区域策略优化) 是一种强化学习算法,旨在通过约束策略更新的幅度来确保训练的稳定性。其核心思想是每次更新策略时,限制新旧策略之间的差异,使其保持在“信任区域”内,从而避免因更新过大导致策略性能骤降。
相对于PPO通过裁剪CLIP进行新旧策略的更新,TRPO则是通过KL散度约束新旧策略的差异,可以让策略在合理范围内更新得更快。核心还是新旧策略比率进行约束,但现在TRPO使用了KL散度这个计算机制,比单纯地进行裁剪会灵活不少。
目标函数:
约束条件:
2.2 DPO & Iterative DPO
2.2.1 DPO
DPO paper:Direct Preference Optimization: Your Language Model is Secretly a Reward Model
DPO基本思想是既然 RLHF 中的 RM 是用标注数据训练出来的。那我为何要将 RM 和 RLHF 训练分为两个阶段,直接从理论上将两个训练步骤的 Loss 融合为一个训练 Loss。最后得到一个类似在正样本上做SFT,同时在负样本上做反向SFT的Loss(假设不考虑 KL penalty 约束)。
损失函数如下:
DPO不属于强化学习算法,但如果我们用传统 RL 的思路来理解 DPO,其更像是一个 Offline 的 REINFORCE 算法:我们只需要认为正样本的reward为+1,而负样本的reward为-1。然后用 REINFORCE 直接基于偏好数据集训练即可。而 KL penalty 的约束也是可以加到这个 reward 值上即可,亦或用额外的 KL Div Loss 来约束。
从这个角度我们就很容易发现 DPO 会继承传统 Offline RL 算法的所有缺点,比如没有 Importance Sampling 的梯度矫正,训练样本和模型之间的 OOD 问题。这些都会让训练偏移轨迹。其次 DPO 在训练中容易出现 chosen logits 和 rejected logits 同时下降的问题,这方面 Llama3.1 用对 chosen samples 加一个NLL Loss 来缓解。
2.2.2 Iterative DPO
- paper:RLHF Workflow: From Reward Modeling to Online RLHF
- code:github.com/RLHFlow/Onl…
- hf model:huggingface.co/RLHFlow/LLa…
于是一种简单的改进思路是,我们还是像 RLHF 一样训练一个 RM,这个 RM 可以是 Pair RM 也有可以原来的 BT model。然后用 GPT 模型在每个 prompt 上采样 N 个样本,依据 RM 给出的打分排序来得到 best chosen 和 worst rejected 样本,大白话就是用最高分和最差分数的那个样本组成pair,最后交给 DPO 训练。因为样本是 GPT 模型自己产生的,Offline RL 中的 OOD 问题也就得到比较好的缓解。
通常这个 Iterative 生成样本和训练的过程会迭代3-10次,每次迭代 10K-20K样本,这个数量远少于 PPO 的 50~100次策略迭代。所以 Iterative DPO 更类似于介于 Online 和 Offline RL 算法的中间形态。
Iterative DPO 最大的一个优点是工程实现的方便性和算法收敛效果的平衡,因为其训练为分阶段进行,也就是样本推理以及模型训练都是独立的运行阶段,通常不需要同时把所有模型加载到GPU上,也就规避了 RLHF 的 Infra 实现难题。
2.3 RLOO & GRPO
2.3.1 RLOO
REINFORCE Leave-One-Out (RLOO) 链接:huggingface.co/blog/puttin…
RLOO 核心思想是想去除 RLHF 中的 Critic 模型来节省大量的 GPU 内存,那没有了 Critic 我们怎么估计 RL 中的 advantage 呢?此时我们只需要对一个 prompt 采样 N 个回答,然后用留一法,即当前样本的 reward 减去其他 (N-1)个样本的reward均值(即基于采样的baseline)
PPO的方案中,生成每个token被建模为一个action,而每个partial sequence,从prompt开始,被视为一个state。RLOO认为,partial sequence的建模是不必要的,奖励只应归于full generations,因为生成过程中的任何中间token没有真正的奖励。所以,更合适且更高效的是将full generation建模为一个单一action,initial state由prompt确定。
目标函数如下:
2.3.2 GRPO
GPRO 也是采用类似的思路和方法,接下来我们来详细看一下。
可以把GRPO的目标函数和PPO进行对比,会更清晰一些:
从上面公式和模型图对比可以看出,GRPO主要是做了两点改进:
- GRPO去除了价值函数模型(Critic模型),因为GRPO对于advantage的计算不再依赖于GAE(GAE的计算依赖于value model),GRPO通过群体计算来估计基线:
- PPO将KL散度计算加到reward计算上,GRPO将KL散度计算作为正则加入到loss计算中,并设计了自适应调整 KL 惩罚系数,用于平衡更新幅度,使得训练稳定且高效。(PPO里KL散度是涵盖在状态价值模型里,GRPO没有状态价值函数)
3. DeepSeek R1
R1 paper: [DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning](arxiv.org/pdf/2501.12…
在本次模型发布中,DeepSeek共发布了三个系列的模型:
- R1-Zero:仅通过RL进行训练,未进行SFT的强推理能力模型
- R1:通过融入冷启动数据与多阶段训练提升推理性能的模型
- R1-Distill:在R1基础上,基于Qwen/Llama蒸馏出的系列dense模型
接下来来看一下R1系列模型的训练过程:
3.1 R1-Zero:基于GPRO的推理能力提升
DeepSeek-R1-Zero是通过强化学习直接对基础模型进行训练,而无需监督微调(SFT)作为预处理步骤。采用的是2.3.2所示的GRPO算法。
为了训练DeepSeek-R1-Zero,作者设计了一个基于规则的奖励系统,主要包括准确性和格式两个方面的奖励。准确性奖励用于判断模型的回答是否正确,例如在数学问题中,模型需要以特定格式(如在方框内)给出最终答案;格式奖励则要求模型将思考过程放在特定的标签(如<think>
和</think>
)之间。
如上图所示,作者设计了一个简单的模板来指导模型的输出格式。模型首先需要生成一个推理过程,然后给出最终答案。这种模板设计避免了对内容的具体限制(例如强制反思性推理或促进特定问题解决策略) ,以便观察模型在强化学习过程中的自然演变。
尽管 DeepSeek-R1-Zero 在推理任务上表现出色,但它在语言表达和可读性方面存在一些问题:
- 语言混合:模型在生成推理过程时可能会混合多种语言,导致输出难以理解。
- 格式问题:模型的输出可能缺乏清晰的格式化,例如没有突出显示答案或缺少总结。
3.2 R1:结合冷启动数据的强化学习
尽管DeepSeek-R1-Zero取得了显著的推理能力提升,但它在可读性和语言混合方面存在一些问题。为了解决这些问题,作者提出了DeepSeek-R1模型,它在强化学习之前引入了一小部分冷启动数据,以提升模型的推理能力和可读性。
- Step1:通过收集少量的长推理链(CoT)冷启动数据来微调基础模型。这些数据不仅提高了模型的推理能力,还改善了输出的可读性。作者通过多种方式收集冷启动数据,包括使用少量样本提示、直接提示模型生成详细答案等。
- Step2:在冷启动数据微调后,DeepSeek-R1继续进行与DeepSeek-R1-Zero类似的GRPO强化学习训练。在此阶段,作者引入了语言一致性奖励,以减少推理过程中的语言混合问题。
- Step3:当强化学习接近收敛时,作者通过拒绝采样生成新的监督微调数据,并结合其他领域的数据(如写作、事实问答等)对模型进行进一步微调。这一步骤旨在提升模型在非推理任务上的表现。
- Step4:最后,DeepSeek-R1进行了第二阶段的强化学习,结合了推理任务和非推理任务的奖励信号,以进一步提升模型的通用性和安全性。
3.3 R1-Distill:将推理能力赋予小型模型
为了将DeepSeek-R1的推理能力传递给更小的模型,作者采用了知识蒸馏技术。他们使用DeepSeek-R1作为教师模型,生成了800K的训练数据,并对几种小型密集模型(如Qwen和Llama)进行了微调。实验结果表明,经过蒸馏的小型模型在推理任务上表现出色,甚至超过了其他开源的大型模型。