DeepSeek-R1反响非常大,主要是因为使用较低的成本得到了OpenAI O1的效果。开源还便宜。
在这篇文章中,我们将了解它是如何构建的。
目录:
DeepSeek-R1 的训练方法
1. 大规模推理导向强化学习 (R1-Zero)
2. R1 训练流程
(第 1 阶段)冷启动
(第 2 阶段)推理强化学习
(第 3 阶段)拒绝采样和监督微调
(第 4 阶段)多样化的强化学习阶段
DeepSeek 模型架构
Multi-head Latent Attention
Decoupled Rotary Position Embedding
Multi-Token Prediction
开源实现和实验
DeepSeek-R1 的训练方法
先介绍 R1-Zero在进一步讲解R1。
1. 大规模推理导向强化学习 (R1-Zero)
DeepSeek R1-Zero 的特别之处在于,它无需标注的 SFT 训练集就能够在推理任务中表现出色。
它的训练过程直接从预训练的基础模型DeepSeek-V3-Base 开始,通过强化学习(RL)训练完成(没有经过 SFT 步骤)。使用了一种称为组相对策略优化 (GRPO) 的方法。GRPO算法是一种策略梯度方法,通过试错引导系统学习最优行为。
这点意义重大这表明了:现代基础模型已经跨越了某个质量和能力的阈值,推理问题可以通过自动化方式进行验证或标注。
组相对策略优化
在训练过程中,我们可以向模型提供一个问题,并生成多个可能的解决方案进行评估。
这些奖励信号和模型更新是模型在强化学习训练过程中持续改进任务的方式,正如论文中的图 2 所示。
与这种能力的提升相对应的是生成的回应长度,模型生成更多的思维 token 来处理问题。
尽管 DeepSeek-R1-Zero 展示了强大的推理能力,并能够自主发展出意想不到且强大的推理行为,但它也面临一些问题。例如,DeepSeek-R1-Zero 在可读性差和语言混杂等方面存在困难。
2. R1 训练流程
冷启动(第 1 阶段):
与 DeepSeek-R1-Zero 不同,为了防止基础模型在强化学习训练的初期阶段出现不稳定的冷启动问题,对于 DeepSeek-R1,他们构建并收集了一小部分长链推理(CoT)数据来微调模型。
收集数据的几种方法:
使用少量示例提示(few-shot prompting)来提供长链推理作为示范,直接提示模型生成详细的答案,并进行反思和验证,收集 DeepSeek-R1-Zero 输出的可读格式,并通过人工标注者进行后处理以改进结果。
在这个小型、高质量的几千条数据集上加入监督微调阶段有助于 DeepSeek-R1 缓解在初始模型中观察到的可读性问题。
推理强化学习(第 2 阶段):
此阶段应用了强化学习来增强模型的推理能力。在编码、数学、科学和逻辑推理等任务中,明确的解决方案可以为强化学习过程定义奖励规则。
拒绝采样和监督微调(第 3 阶段):
在此阶段,使用第 2 阶段的模型检查点生成许多样本。使用拒绝采样时,仅保留正确且可读的样本。此外,生成奖励模型 DeepSeek-V3 用于决定应保留哪些样本。DeepSeek-V3 的一些训练数据也包含在此阶段。然后,使用监督微调在此数据集上训练模型。
多样化的强化学习阶段(第 4 阶段):
这个最后阶段包括不同的任务。基于规则的奖励用于允许这样做的任务,例如数学。对于其他任务,LLM 会提供反馈以使模型与人类偏好保持一致,它使用了一个帮助性和安全性的奖励模型(与 Llama 模型类似)。这使得 R1 在推理任务以及其他非推理任务中都能表现出色。
模型架构
像 GPT-2 和 GPT-3 初期的模型一样,DeepSeek-R1 是由一堆 Transformer 解码器块堆叠而成。它由 61 个解码器块组成,其中前三个是密集层(dense layers),其余的是混合专家层(mixture-of-experts layers)(MoE)。
在模型维度大小和其他超参数方面,它们如下所示:
Multi-head Latent Attention
几种注意力机制对比:
注意力机制从一开始的多头注意力机制(MHA)到多查询注意力(MQA)再到分组查询注意力(GQA),能有效减少KV缓存,但效果略差一些。
DeepSeek提出了多头潜在注意力机制(Multi-head Latent Attention: MLA),MLA通过显著减少生成的KV缓存来确保高效的推断,而DeepSeekMoE可以通过稀疏架构以经济的成本训练强大的模型。
MLA的核心是对键和值的低秩联合压缩(low-rank key-value joint compression),减少KV缓存。MLA用投影矩阵的方式替代了GQA的分割、重复,并引入了一个恒等变换技巧来可以进一步压缩KV Cache,同时采用了一种混合方法来兼容RoPE(如下)。
Decoupled Rotary Position Embedding
每个Attention Head的Q、K新增d维度用来添加RoPE,其中K新增的维度每个Head共享.,还将Q的输入也改为了低秩投影形式,这与减少KV Cache无关,主要是为了减少训练期间参数量和相应的梯度所占的显存。
Auxiliary-loss-free load balancing
与依赖辅助损失进行负载均衡的传统 MoE 架构不同,DeepSeek-V3 实现了动态偏置调整策略。
为了减轻因努力确保负载平衡而导致的性能下降。对于MoE模型,不平衡的专家负载将导致路由崩溃,并在具有专家并行的场景中降低计算效率。传统的解决方案通常依赖于辅助损耗以避免不平衡负载,然而,太大的辅助损失会损害模型的性能。所以引用了辅助无损失负载平衡策略(auxiliary-loss-free load balancing strategy)。
为每个专家引入一个偏差项𝑏𝑖,并将其添加到相应的亲和力得分Si,t中,以确定top-K路由.
通过动态调整,DeepSeek-V3在训练过程中保持专家负载平衡,比通过纯辅助损失促进负载平衡的模型取得更好的性能。
Complementary Sequence-Wise Auxiliary Loss
为了防止任何单个序列内的极端不平衡,deeopseek 还采用了一个互补的序列级平衡损失。
Node-Limited Routing
使用了一种受限制的路由机制来限制训练期间的通信成本。确保每个标记将被发送到最多的𝑀节点,这些节点是根据分布在每个节点上的专家的最高 Kr/M 亲和力得分之和来选择的。
Multi-Token Prediction
多标记预测(MTP)使模型能够同时预测多个token,丰富训练信号并提高复杂任务的整体性能。采用顺序预测额外 Token 的方式,并在每一预测深度保持完整的因果链。
一方面,MTP目标使训练信号密集,并可能提高数据效率。另一方面,MTP可能使模型能够预先规划其表示方式,以便更好地预测未来的令牌。使用独立的输出头(𝐷个顺序模块)并行预测𝐷个额外的token,并在每个预测深度保持完整的因果链。
蒸馏
DeepSeek开源了6个用R1蒸馏的小模型。DeepSeek-R1-Distill-Qwen-7B在AIME 2024基准上的pass@1得分为55.5%,超过QwQ-32B-Preview。DeepSeek-R1-Distill-Qwen-32B在AIME 2024基准上的pass@1得分为72.6%,在MATH-500基准上的pass@1得分为94.3%,在LiveCodeBench基准上的pass@1得分为57.2%。
OPEN-R1 和 GRPO的训练方法
开源社区有一些对R1的复现,Hugging Face主导的open-r1项目,另外还有:TinyZero 和
simpleRL-reason。
SFT
accelerate launch --config_file=configs/zero3.yaml src/open_r1/sft.py \
--model_name_or_path Qwen/Qwen2.5-Math-1.5B-Instruct \
--dataset_name HuggingFaceH4/Bespoke-Stratos-17k \
--learning_rate 2.0e-5 \
--num_train_epochs 1 \
--packing \
--max_seq_length 4096 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 4 \
--gradient_checkpointing \
--bf16 \
--logging_steps 5 \
--eval_strategy steps \
--eval_steps 100 \
--output_dir data/Qwen2.5-1.5B-Open-R1-Distill
GRPO:
accelerate launch --config_file configs/zero3.yaml src/open_r1/grpo.py \
--output_dir DeepSeek-R1-Distill-Qwen-7B-GRPO \
--model_name_or_path deepseek-ai/DeepSeek-R1-Distill-Qwen-7B \
--dataset_name AI-MO/NuminaMath-TIR \
--max_prompt_length 256 \
--per_device_train_batch_size 1 \
--gradient_accumulation_steps 16 \
--logging_steps 10 \
--bf16
eval 单个 GPU:
MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
MODEL_ARGS="pretrained=$MODEL,dtype=float16,max_model_length=32768,gpu_memory_utilisation=0.8"
TASK=aime24
OUTPUT_DIR=data/evals/$MODEL
lighteval vllm $MODEL_ARGS "custom|$TASK|0|0" \
--custom-tasks src/open_r1/evaluate.py \
--use-chat-template \
--system-prompt="Please reason step by step, and put your final answer within \boxed{}." \
--output-dir $OUTPUT_DIR
eval 多GPU:
NUM_GPUS=8
MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
MODEL_ARGS="pretrained=$MODEL,dtype=float16,data_parallel_size=$NUM_GPUS,max_model_length=32768,gpu_memory_utilisation=0.8"
TASK=aime24
OUTPUT_DIR=data/evals/$MODEL
lighteval vllm $MODEL_ARGS "custom|$TASK|0|0" \
--custom-tasks src/open_r1/evaluate.py \
--use-chat-template \
--system-prompt="Please reason step by step, and put your final answer within \boxed{}." \
--output-dir $OUTPUT_DIR
eval 跨 GPU 分片:
NUM_GPUS=8
MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-32B
MODEL_ARGS="pretrained=$MODEL,dtype=float16,tensor_parallel_size=$NUM_GPUS,max_model_length=32768,gpu_memory_utilisation=0.8"
TASK=aime24
OUTPUT_DIR=data/evals/$MODEL
export VLLM_WORKER_MULTIPROC_METHOD=spawn
lighteval vllm $MODEL_ARGS "custom|$TASK|0|0" \
--custom-tasks src/open_r1/evaluate.py \
--use-chat-template \
--system-prompt="Please reason step by step, and put your final answer within \boxed{}." \
--output-dir $OUTPUT_DIR
References
DeepSeek-V3 Technical Report
DeepSeekMoE
modeling_deepseek code
A Visual Guide to Mixture of Experts
the-illustrated-deepseek-r1
苏剑林: 缓存与效果的极限拉扯:从MHA、MQA、GQA到MLA
Auxiliary-Loss-Free Load Balancing Strategy for Mixture-of-Experts
开源复现:
open-r1: https://github.com/huggingface/open-r1
TinyZero https://github.com/Jiayi-Pan/TinyZero
simpleRL-reason https://github.com/hkust-nlp/simpleRL-reason