转载需标明来源
文章目录
DeepSeek技术发展沿革
日期 | 版本 | 论文 | 核心技术 | 主要特点及结论 |
---|---|---|---|---|
2024年1月 | DeepSeek LLM | 2401.02954 | 预训练、SFT、DPO | 67B dense 密集模型;HAI-LLM 训练框架。初步在密集模型验证了 Scale law |
2024年1月 | DeepSeek MoE(V1) | 2401.06066 | MoE | 2B/16B/145B;精细分割、共享专家隔离,减少知识冗余。初步在混合专家模型上验证了Scale law |
2024年1月 | DeepSeek Coder | 2401.14196 | NTP; FIM | 1.3B到33B;提升代码和数学推理能力 |
2024年2月 | DeepSeek Math | 2402.03300 | GRPO;RL | 7B模型,提升数学推理任务 |
2024年3月 | DeepSeek VL | 2403.05525 | 混合视觉编码 | 1.3B、7B,验证多模态训练策略 |
2024年5月 | DeepSeek V2 | 2405.04434 | MoE;MLA | 236B 总参数,21B 激活参数;通过 MLA 显著减少 KV缓存 |
2024年5月 | DeepSeek Prover | 2405.14333 | 合成数据 | 基于Math-7B,提升形式化定理证明能力;合成数据 |
2024年6月 | DeepSeek CoderV2 | 2406.11931 | MoE;GRPO | 16B激活2.4B、236B激活21B;显著增强了编码和数字推理能力 |
2024年7月 | ESFT | 2407.01906 | PEFT/ESFT | 专家专业化微调,提高训练效率和效果 |
2024年8月 | DeepSeek Prover V1.5 | 2408.08152 | GRPO;RMaxTS | 强化学习和 CoT 对模型能力显著提升;RMaxTS 蒙特卡洛树搜索算法的探索策略提高证明成功率 |
2024年10月 | Janus | 2410.13848 | 视觉编码解耦;统一多模态框架 | 视觉编码解耦;自回归变换器架构 |
2024年11月 | Janus Flow | 2411.07975 | Rectified Flow;表示对齐 | 图像理解和生成统一,增强了模型多模态理解能力 |
2024年12月 | DeepSeek VL2 | 2412.10302 | MOE;MLA;动态平铺视觉编码 | 3个尺寸,27B激活4.1B;提升多模态能力 |
:2024年12月 | DeepSeek V3 | 2412.19437 | MOE;MLA;MTP;FP8混合精度训练 | 671B 总参数,37B激活参数;训练、推理高效 |
2025年1月 | DeepSeek R1 | 2501.12948 | RL;GRPO;知识蒸馏 | 671B推理模型;蒸馏为1.5B~70B小模型;验证强化学习增强推理能力 |
2025年1月 | Janus Pro | 2501.17811 | 视觉编码解耦;统一多模态框架 | 1B、7B;统一多模态理解和文本生成图像 |
总结
- 迭代速度显著快于其他厂商。从2024年1月到2025年1月,12个月发布15个模型。
- 全栈式的技术布局。
- 不同模型涉及不同的任务类型。涵盖了自然语言处理、代码生成、数学推理、多模态等领域。
- 技术突破涵盖了基座模型全流程。包括大模型理论研究、架构创新、训练优化、多模态整合
- 极致成本压缩。通过自制训练框架、减少激活参数、硬件适配、新的微调方法等手段,大幅减少了大模型等成本。
重要技术点
技术点过多,本文选取关键技术点整理:
- Scaling Law
- DeepSeek MoE
- MLA
- DualPipe
- GRPO
Scaling Law
意义
deepseek提出的scaling law(DeepSeek LLM Scaling Open-Source Language Models with Longtermism, 2024)是DeepSeek系列所有语言模型最底层的指导思想。它有两点重要意义:
- 在开始新模型设计时,scaling law指导了任务的资源分配和架构设计方向。
- 能更准确的预测要训练的模型的性能
前置知识
scaling law最早由Open AI (Scaling Laws for Neural Language Models, 2020)提出,描述了神经网络性能随规模变化的规律。主要结论如下:
- 模型参数量(N)、训练数据量(D)、训练的计算量(C)三者共同决定模型性能。且三者按比例缩放时,性能提升遵循幂律关系:
性能 ∝ N α D β C γ 性能\propto N^αD^βC^γ 性能∝NαDβCγ
其中 α α α, β β β, γ γ γ 是取决于任务的常数(通常小于1)。 - 在标准transformer模型中有:
C ≈ 6 N D C\approx 6ND C≈6ND - 根据结论1和结论2:
C C C一定时,模型性能的决策变量只有 N N N和 D D D 。这意味着,通过构建一个巨大的数据集,简单的增加transformer的深度,就可以创造性能非凡的大语言模型。 - 存在一个最优的计算分配比例:当模型参数量(N)和训练数据量(D)按比例 N ∝ D N∝D N∝D 增加时,性能提升最显著。
deepseek创新点
-
openai在scaling law中使用IsoFLOP(同构浮点运算数, isomorphic FLOPs)来计量模型规模(N),没有考虑注意力机制带来的计算开销。为了更精准的表示模型规模(N),deepseek提出了使用FLOPs/token来计量模型规模,用 M M M表示。将 C ≈ 6 N D C\approx 6ND C≈6ND替换为 C ≈ M D C\approx MD C≈MD。
-
openai提出了最优的计算分配比例。deepseek对此进行了精细的修正。
- 模型尺度
M o p t = 0.1715 C 0.5243 M_{opt}=0.1715C^{0.5243} Mopt=0.1715C0.5243 - 数据尺度
D o p t = 5.8316 C 0.4757 D_{opt}=5.8316C^{0.4757} Dopt=5.8316C0.4757
- 模型尺度
-
提出了影响transformer性能的第四个影响因素:超参。
- 学习率最优值 η o p t = 0.3118 C − 0.1250 \eta_{opt}=0.3118C^{-0.1250} ηopt=0.3118C−0.1250
- batchsize最优值
B
o
p
t
=
0.2920
C
0.3271
B_{opt}=0.2920C^{0.3271}
Bopt=0.2920C0.3271
DeepSeek MoE
意义
减少计算开销
- 在训练阶段,计算成本不变时,大幅增加模型参数量
- 在推理阶段,大幅减少推理阶段的计算开销。
前置知识
- 混合专家模型(Mixed Expert Models, MoE)最早在1991年提出,MoE的思路是通过稀疏性降低网络的计算开销。
- 稠密的transfromer架构中,FFN部分的参数规模和计算量最庞大,主要用于记录前置知识。
deepseek创新点
在一次计算时,实际上涉及很少的一部分知识参与,不必所有参数参与计算。所以MoE的核心思路在于保存全量的权重参数,但计算时只激活很少一部分神经元。
代码复现
import torch
import torch.nn as nn
import torch.optim as optim
# 1. 定义专家模型。2 * mlp + relu + softmax
class Expert(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(Expert, self).__init__()
self.layer1 = nn.Linear(input_dim, hidden_dim)
self.layer2 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
x = torch.relu(self.layer1(x))
return torch.softmax(self.layer2(x), dim=1)
# 2. 门控函数
# 3 * linear + dropout + relu/leakyrelu + softmax
class Gating(nn.Module):
def __init__(self, input_dim,
num_experts, dropout_rate=0.1):
super(Gating, self).__init__()
# Layers
self.layer1 = nn.Linear(input_dim, 128)
self.dropout1 = nn.Dropout(dropout_rate)
self.layer2 = nn.Linear(128, 256)
self.leaky_relu1 = nn.LeakyReLU()
self.dropout2 = nn.Dropout(dropout_rate)
self.layer3 = nn.Linear(256, 128)
self.leaky_relu2 = nn.LeakyReLU()
self.dropout3 = nn.Dropout(dropout_rate)
self.layer4 = nn.Linear(128, num_experts)
def forward(self, x):
x = torch.relu(self.layer1(x))
x = self.dropout1(x)
x = self.layer2(x)
x = self.leaky_relu1(x)
x = self.dropout2(x)
x = self.layer3(x)
x = self.leaky_relu2(x)
x = self.dropout3(x)
return torch.softmax(self.layer4(x), dim=1)
# MoE模块
class MoE(nn.Module):
def __init__(self, trained_experts):
super(MoE, self).__init__()
self.experts = nn.ModuleList(trained_experts)
num_experts = len(trained_experts)
# 假设每个专家输入维度相同
input_dim = trained_experts[0].layer1.in_features
self.gating = Gating(input_dim, num_experts)
def forward(self, x):
# 获取门控权重
weights = self.gating(x)
# 计算专家输出
outputs = torch.stack(
[expert(x) for expert in self.experts], dim=2)
# 调整weights形状,以适应专家网络的输出
weights = weights.unsqueeze(1).expand_as(outputs)
return torch.sum(outputs * weights, dim=2)
相关文献
MoE 架构 https://blog.csdn.net/v_JULY_v/article/details/145406756
MLA
意义
减少显存(或内存)开销
传统的自注意力机制中,KV缓存与序列长度成线性关系,导致长文本场景下的硬件资源焦虑。MLA能大幅减少KV缓存。
前置知识
- 传统的MHA(多头注意力机制, Multi-Head Attention)中,缓存是怎么产生:
先看单个head的计算:
step 1: 计算Q、K、V Q = X W Q , K = X W K , V = X W V Q=XW_Q,K=XW_K,V=XW_V Q=XWQ,K=XWK,V=XWV
step 2: 计算注意力分数 Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
多头注意力就是单头注意力的拼接。每个头是不同的子空间,可以让模型专注不同方面的信息:
transformer是自回归的:模型每生成一个字,就要把之前的所有输入和输出都输入。
输入 | 输入 | 输入 | 输入 | 输入 | 输入 | 第一次输出 | 第二次输出 | 第三次输出 | 第四次输出 | |
---|---|---|---|---|---|---|---|---|---|---|
第一次预测 | bos | 你 | 爱 | 我 | 吗 | eos | 我 | |||
第二次预测 | bos | 你 | 爱 | 我 | 吗 | eos | 我 | 爱 | ||
第三次预测 | bos | 你 | 爱 | 我 | 吗 | eos | 我 | 爱 | 你 | |
第四次预测 | bos | 你 | 爱 | 我 | 吗 | eos | 我 | 爱 | 你 | 。 |
这导致越后面的预测,序列长度越长。
K
K
K和
V
V
V越大,计算量也就越大。
但实际前面运算得到的
K
K
K和
V
V
V可以存起来重复利用,大幅减少了注意力机制的运算开销。
这样缓存的KV参数量为
2
n
h
d
n
l
2n_hd_nl
2nhdnl,其中
n
h
n_h
nh为head的数量,
d
h
d_h
dh为K和V的维度,
l
l
l为block的块数。
deepseek创新点
业界优化KV Cache的主要方法:
- 共享KV:多个Head共享使用1组KV,将原来每个Head一个KV,变成1组Head一个KV,来压缩KV的存储。代表方法:GQA,MQA等
- 窗口KV:针对长序列控制一个计算KV的窗口,KV cache只保存窗口内的结果(窗口长度远小于序列长度),超出窗口的KV会被丢弃,通过这种方法能减少KV的存储,当然也会损失一定的长文推理效果。代表方法:Longformer等
- 量化压缩:基于量化的方法,通过更低的Bit位来保存KV,将单KV结果进一步压缩,代表方法:INT8等
- 计算优化:通过优化计算过程,减少访存换入换出的次数,让更多计算在片上存储SRAM进行,以提升推理性能,代表方法:flashAttention等
deepseek创新点
多头潜在注意力(Multiple Latent Attention, MLA)使用了低秩分解的思路减少KV缓存的参数量,从而减少显存开销。
多头潜在注意力(Multiple Latent Attention, MLA)使用了低秩分解的思路减少KV缓存的参数量,从而减少显存开销。
完整的更新公式如下:
[
q
t
C
;
q
t
N
R
]
a
m
p
;
=
h
t
W
D
Q
W
U
Q
R
[
q
t
,
1
C
;
q
t
,
2
C
;
.
.
.
;
q
t
,
n
h
C
]
=
q
t
C
a
m
p
;
=
s
l
i
c
e
[
h
t
W
D
Q
W
U
Q
R
,
:
d
h
n
h
]
[
q
t
,
1
R
;
q
t
,
2
R
;
.
.
.
;
q
t
,
n
h
R
]
=
q
t
R
a
m
p
;
=
R
o
P
E
(
q
t
N
R
)
W
D
K
V
R
q
t
,
i
a
m
p
;
=
[
q
t
,
i
C
;
q
t
,
i
R
]
[
c
t
K
V
;
k
t
N
R
]
a
m
p
;
=
h
t
W
D
K
V
R
k
t
R
a
m
p
;
=
R
o
P
E
(
k
t
N
R
)
[
k
t
C
;
v
t
C
]
a
m
p
;
=
c
t
K
V
W
U
K
V
[
k
t
,
1
C
;
k
t
,
2
C
;
.
.
.
;
k
t
,
n
h
C
]
=
k
t
C
a
m
p
;
=
c
t
K
V
s
l
i
c
e
[
W
U
K
V
,
:
d
n
n
h
]
k
t
,
i
a
m
p
;
=
[
k
t
,
i
C
;
k
t
R
]
[
v
t
,
1
C
;
v
t
,
2
C
;
.
.
.
;
v
t
,
n
h
C
]
=
v
t
C
a
m
p
;
=
c
t
K
V
s
l
i
c
e
[
W
U
K
V
,
d
h
n
h
:
]
o
t
,
i
a
m
p
;
=
∑
j
=
1
t
S
o
f
t
m
a
x
(
q
t
,
i
k
j
,
i
T
d
h
+
d
h
R
)
v
j
,
i
C
a
m
p
;
=
∑
j
=
1
t
S
o
f
t
m
a
x
(
(
s
l
i
c
e
[
h
t
W
D
Q
W
U
Q
R
,
:
d
h
n
h
]
(
s
l
i
c
e
[
W
U
K
V
,
:
d
n
n
h
]
)
T
(
c
j
K
V
)
T
+
R
o
P
E
(
s
l
i
c
e
[
h
t
W
D
Q
W
U
Q
R
,
d
h
n
h
:
]
)
k
j
R
)
)
d
h
+
d
h
R
)
c
j
K
V
s
l
i
c
e
[
W
U
K
V
,
d
h
n
h
:
]
\begin{align} \left[ q_t^C; q_t^{NR} \right] &= h_tW^{DQ}\color{green}{W^{UQR}} \tag{i}\\ \left[ q_{t,1}^C;q_{t,2}^C;...;q_{t,n_h}^C \right] = q_t^C &= slice[h_tW^{DQ}\color{green}{W^{UQR}}, :d_hn_h] \tag{ii}\\ \left[ q_{t,1}^R;q_{t,2}^R;...;q_{t,n_h}^R \right] = q_t^{R} &= RoPE(q_t^{NR}){\color{green}{W^{DKVR}}} \tag{iii}\\ q_{t,i} &= [q_{t,i}^C; q_{t,i}^R] \tag{iv}\\ \left[ \color{blue}{c_t^{KV}} ; k_t^{NR} \right] &= h_t\color{green}{W^{DKVR}} \tag{v}\\ \color{blue}{k_t^{R}} &= RoPE(k_t^{NR}) \tag{vi}\\ \left[ {k_t^{C}}; {v_t^{C}} \right] &= \color{blue}{c_t^{KV}}\color{green}{W^{UKV}} \tag{vii}\\ \left[ k_{t,1}^C;k_{t,2}^C;...;k_{t,n_h}^C \right] = k_t^{C} &= \color{blue}{c_t^{KV}}slice[\color{green}{W^{UKV}}, :d_nn_h]\\ k_{t,i} &= [k_{t,i}^C; k_{t}^R] \tag{viii}\\ \left[ v_{t,1}^C;v_{t,2}^C;...;v_{t,n_h}^C \right] = v_t^C &= \color{blue}{c_t^{KV}}slice[\color{green}{W^{UKV}},d_hn_h:] \tag{ix}\\ o_{t,i} &= \sum_{j=1}^{t}{Softmax(\frac{q_{t,i}k_{j,i}^{T}}{\sqrt{d_h + d_h^R}}})v_{j,i}^C \\ &= \sum_{j=1}^{t}Softmax(\frac{(slice[h_tW^{DQ}\color{green}{W^{UQR}}, :d_hn_h]{(slice[\color{green}{W^{UKV}}, :d_nn_h])}^T\color{blue}{(c_j^{KV})}^T + RoPE(slice[h_tW^{DQ}\color{green}{W^{UQR}}, d_hn_h:])\color{blue}{k_j^R}))}{\sqrt{d_h + d_h^R}}) \color{blue}{c_j^{KV}}slice[\color{green}{W^{UKV}}, d_hn_h:] \tag{x} \\ \end{align}
[qtC;qtNR][qt,1C;qt,2C;...;qt,nhC]=qtC[qt,1R;qt,2R;...;qt,nhR]=qtRqt,i[ctKV;ktNR]ktR[ktC;vtC][kt,1C;kt,2C;...;kt,nhC]=ktCkt,i[vt,1C;vt,2C;...;vt,nhC]=vtCot,iamp;=htWDQWUQRamp;=slice[htWDQWUQR,:dhnh]amp;=RoPE(qtNR)WDKVRamp;=[qt,iC;qt,iR]amp;=htWDKVRamp;=RoPE(ktNR)amp;=ctKVWUKVamp;=ctKVslice[WUKV,:dnnh]amp;=[kt,iC;ktR]amp;=ctKVslice[WUKV,dhnh:]amp;=j=1∑tSoftmax(dh+dhRqt,ikj,iT)vj,iCamp;=j=1∑tSoftmax(dh+dhR(slice[htWDQWUQR,:dhnh](slice[WUKV,:dnnh])T(cjKV)T+RoPE(slice[htWDQWUQR,dhnh:])kjR)))cjKVslice[WUKV,dhnh:](i)(ii)(iii)(iv)(v)(vi)(vii)(viii)(ix)(x)
代码实现
https://github.com/ThomasVonWu/Interview-Note/blob/main/%E5%A4%A7%E6%A8%A1%E5%9E%8B/%E5%A4%A7%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86%E5%8A%A0%E9%80%9F/DeepSeek_MLA.py
相关文献
MHA机制 https://zhuanlan.zhihu.com/p/109983672
MLA机制 https://zhuanlan.zhihu.com/p/23062701108
MHA、MQA、GQA演变 https://blog.csdn.net/v_JULY_v/article/details/134228287
DualPipe
意义
DualPipe是一种并行计算策略。通过显著减少气泡(GPU空闲时间)提升大规模分布式训练效率。也是deepseek节约成本的关键。
前置知识
- 多层感知机的反向传播和参数更新(略过)
- PP(流水线并行, Pipeline Parallel)
将模型和数据都拆分为多个chunk,每个device分别训练。每个数据chunk是一个micro-batch。 - PP的气泡
PP的空闲时间占比 k − 1 k + m − 1 \frac{k-1}{k+m-1} k+m−1k−1( k k k为节点数量, m m m为micro batch数量)。
节点4 | F_4 | B_1 | update | ||||||
---|---|---|---|---|---|---|---|---|---|
节点3 | F_3 | B_2 | update | ||||||
节点2 | F_2 | B_3 | update | ||||||
节点1 | F_1 | B_4 | update |
- 1F1B:打乱model chunks的顺序,尽可能让一个节点的forward与另一个节点的backward并行。
- ZB-H1和ZB-H2
F里面每有一个矩阵乘法,B里面就有两个矩阵乘法。因此1B=2F。所以1F1B中的气泡来自于F在等B结束。ZB-H1将B进一步拆分为B和W。一个model chunk的B要等前面的B算完,但W无需等待前面的层算完,因此ZB-H1可以将W提前来填补F的等待时间。ZB-H2是在ZB-H1的基础上将optimizer step进一步提前,消除了更多的气泡。
deepseek创新点
DualPipe是在ZB-H2点基础上针对MoE模型进行了适配。
前向传播
- multi-head attention的计算;
- all-to-all dispatch,信息分发到各个节点;为的是计算moe做准备(总是需要把token分发到M个机器上)
- model parallel MOE,模型并行MOE,也就是deepseekMOE;FFN的计算;
- all-to-all combine,M个机器的MOE计算完成之后,需要合并一下各自的信息。
F的步骤:
att(F) | all2all dispatch(F) | mlp(F) | all2all combine(F) |
---|
B的步骤就是F的步骤翻过来:
all2all combine(F) | mlp(F) | all2all dispatch(F) | att(F) |
---|
dualpipe的整体逻辑:让整个集群中保存两个model的副本,用DP的方把两个micro-batch分别发给两个model。一个batch的计算和另外一个batch的通信并行。
Forward和Backward是交叉进行的。
下图是论文中给出的一个8节点20micro-batches的流程图。
官方代码实现
https://github.com/deepseek-ai/DualPipe
相关文献
https://zhuanlan.zhihu.com/p/22681871459
GRPO
意义
赋予推理模型思维链的能力。比如V3与R1,同为671B的模型,未微调的V3为基座模型。经过(包括了GRPO)微调的R1则成为了推理模型。
前置知识
- RLHF
RLHF是利用强化学习完成模型对齐(微调)的一种技术。一般分为两种技术路线:- 以 PPO为代表的 On Policy 路线 - 时间成本高、效果上限高
- 以DPO为代表的 Off Policy 路线 - 时间成本低、效果上限低
两者的区分标准为在于训练时是否要进行文本生成。GRPO属于On Policy路线。
- PPO
具体公式可以略过,只需要了解PPO的特点即可:- Actor:用于生成句子的模型。也是我们最后想要的模型。
- Critic:指导Actor的教练模型。需要与Actor一同训练。
- Reward Model:用于给出最终分数的模型。不训练,只生成。
- Reference Model:用于保持的最终结果不会偏离的模型。不训练,只生成。
同时训练两个模型,推理四个模型,所以PPO非常耗费资源。
deepseek创新点
deepseek提出的GRPO(分组相对策略优化, Group Relative Policy Optimization)大幅降低了微调的成本。下图是PPO和GRPO的对比,其中的Policy Model是Actor,Value Model是Critic。GRPO相比PPO减少了一个Critic。
GRPO原理
GRPO的流程(简化版):
- 将G个query抛给Policy Model推理,每个query生成出t个不同的回答(实际这里我们要的不是回答,而是回答中每个token的概率分布)。
- 将所有回答交给Reward Model计算rewards。再根据rewards计算advantage。每个回答对应的advantage是个标量,代表这个回答有多么符合我们的预期。
- Policy Model与Reference Model的KL散度用来表征Policy Model的训练偏移量。为了不让Policy Model过分的偏移原有的模型,我们将advantage与KL散度相减作为GRPO的loss。
- 根据GRPO的loss更新Policy Model的参数。
代码复现
https://github.com/huggingface/open-r1/blob/main/src/open_r1/grpo.py
相关文献
https://zhuanlan.zhihu.com/p/21046265072
https://www.bilibili.com/video/BV15zNyeXEVP/?share_source=copy_web&vd_source=9eb6d7fad45f9fa869cd9abb34fa68ca