醋醋百科网

Good Luck To You!

白话文讲大模型(一):DeepSeek V3/R1的技术创新 之 MOE、MLA、FP8

一、导读

今天抽空听完了《Maunus 产品合伙人张涛 - 手把手带你解读 DeepSeek R1 技术创新》,直接路转粉,产品同学能把技术讲的非常通透,非常不易,受到启发我也决定用通俗的语言介绍下Deepseek,再次读了一遍DeepSeek_R1/DeepSeek_V3摘录核心要点跟大家分享,本文重点涵盖训练范式、MOE、MLA、FP8混合训练,在下一篇中将介绍MTP、All2All通信、EP策略分析等偏工程架构的优化

二、整体架构

deepseek v3模型:
https://github.com/deepseek-ai/DeepSeek-V3/blob/main/inference/configs/config_671B.json

DS-v3整体架构是L层的transformer Block网络,其核心参数配置包括:模型层数61层,隐藏层维度7168,前馈网络维度18432,注意力头数128,词汇表大小129280,最大位置嵌入163840。通过精细的架构设计,DeepSeek-V3实现了在计算效率和性能上的平衡。

{
    "vocab_size": 129280,
    "dim": 7168,
    "inter_dim": 18432,
    "moe_inter_dim": 2048,
    "n_layers": 61,
    "n_dense_layers": 3,
    "n_heads": 128,
    "n_routed_experts": 256,
    "n_shared_experts": 1,
    "n_activated_experts": 8,
    "n_expert_groups": 8,
    "n_limited_groups": 4,
    "route_scale": 2.5,
    "score_func": "sigmoid",
    "q_lora_rank": 1536,
    "kv_lora_rank": 512,
    "qk_nope_head_dim": 128,
    "qk_rope_head_dim": 64,
    "v_head_dim": 128,
    "dtype": "fp8"
}

整体网络61层,包括前三层FFN,在MoE架构中,每一层都是MoE层,共有58层MoE层(第4层至第61层),每层专家总数为257个(包括1个共享专家和256个路由专家),模型总专家数为14,906个。每层活跃专家数为9个(包括1个共享专家和8个路由专家),整个模型的活跃专家数为522个

改变世界的模型代码实际也不到1k行,当然不含底层库代码,可以看看:
https://github.com/deepseek-ai/DeepSeek-V3/blob/main/inference/model.py,参数网络非常巨大,家里没矿基本就别想复现训练了~

三、核心技术亮点

3.1 训练方式的创新

3.1.1 大模型的训练类比

在介绍DeepSeek模型的训练之前,先简单介绍下大模型的训练的过程,可以类似人的成长过程:

#1 从Zero模型不断进行学习(带答案的样本)+考试(不给答案的试题),在过程中,本身会结合考试情况持续进行迭代,直到loss(类似正确率)收敛【这个过程类似满足毕业要求的大学生,掌握了一定的技能】

#2 在#1的基础上,针对领域的数据(带答案的样本)进行针对性增强【过程类似企业的专业领域的入职培训】

#3 在#2的基础上,进一步进行调优,包括让输出等更规范,总结更有调理等,在这个过程中同样也会有反馈和评估【类似主管反馈】

3.1.1 DeepSeek-R1的RL(Reinforcement Learning,强化学习)训练过程

DeepSeek-R1-Zero的诞生,严格依赖了上述DeepSeek V3 + RL,DS团队很早通过RL证明了随着迭代step的增长,思维链的生成会更丰富,通过这种持续训练的方式,本质上是非常巧妙的从DeepSeek-v3中,提取出来了思维链的文本信息(只是这个文本信息可读性一般),个人理解本质上是将输入和答案之间更加了更多的连接方式,同时通过多种方式交叉验证也进一步让答案更趋近于正确。

这里边也讲了一个比较有意思的RL激励目标的设定,如下图所示:

#1 在DeepSeek-R1-Zero的产出上,RL主要是基于答案的准确性+思维链format进行激励模型,让模型产出高质量的cold start数据

#2 cold start数据输入给DeepSeek-V3产出chckpoint1

#3 在此基础上通过调整RL的目标(增加了一致性激励),产出chckpoint2,并生成新的COT数据

#4 在COT数据+知识数据的叠加加,RL目标进一步增加人类的倾向性激励,最终诞生DeepSeek-R1

可以认为通过DeepSeek V3与DeepSeek-R1-Zero的交叉迭代,最终诞生了DeepSeek-R1,甚至可能通过反复的COT是否会进一步提升模型的表现?

论文中也指出R1的最终成果是DeepSeek-V3的基座大模型的成功的延续,这个方式放在普通基础模型上进行同样的RL训练就会效果可能会一般,因此“罗马不是一天建成的”,作业抄起来得抄全套

3.2 MOE 专家网络

DeepSeek的MOE除了每一层的设计上,引入了共享专家(1个)和256个路由专家,类似医院的全科和专门诊室分配,在分诊台的设计上也有创新,首先是整个模型前三次FFN对信息进行了充分融合,然后第四层开始才进行专家网络路由,在路由时基于一定的基础知识,加入了路由网络控制激活最多top(k=8)个路由网络。

MoE的工作流程如下:

  1. 数据输入:原始数据(如文本、图像)输入到MoE架构中。
  2. 门控网络计算:门控网络处理输入数据,计算每个专家的权重。
  3. 专家网络处理:根据权重,选择部分专家处理数据,每个专家生成中间结果。
  4. 结果融合:将各专家的输出按权重加权求和,得到最终结果

MOE的优势在于:

  • 计算效率:通过稀疏激活专家,减少计算量,提高训练和推理速度。
  • 模型性能:多个专家的集成增强了模型的表示能力和泛化能力。
  • 灵活性与可扩展性:支持动态调整专家数量,适应不同任务需求。

那么每一个专家网络内部又是什么?用通俗的话说,本质上是一个特定的网络(network网络),每个网络并非出生时就已经被设计成专有的技能,而是在训练的过程中,因为不同的专家被安排(路由网络控制)了差异化的输入(toten),形成了差异化的经验(参数),训练的过程可以等价于人类学习了差异化的专业知识,形成了差异化的经验权重,当正式推理(问答咨询)时,同样特定的带有经验(模型权重)的专家被激活参与文本序列的预测:

  • 细粒度/垂类专家” :通过细粒度专家切分 (Fine-Grained Expert Segmentation) 将一个 FFN 切分成 mmm 份。尽管每个专家的参数量小了,但是能够提高专家的专业水平
  • 共享专家”:掌握更加泛化或公共知识的专家,从而减少每个细粒度专家中的知识冗余,共享专家的数量是固定的且总是处于被激活的状态

结合3.1的训练范式,通俗小结:

  • 训练阶段:最开始的模型本质上没有所谓的专家存在,只有一个框架,类似于提供了一个空壳的医院,然后直接塞进去了几个只有1点点背景知识的“大学生”,分诊台(专家门控网络)往不同的屋子里“大学生”路由不同的病例(带答案),同时给一部分不带答案的病例让其预测,由于知道答案,可以反过来优化分配的策略并对专家进化反馈(进化);在两者协同的训练下,屋子里的“大学生”逐步进化成了“专家”,分诊台也进化成了有专业背景的护士分诊台
  • 强化训练阶段:基于训练的产出模型,将带答案的病例,进一步按照结果的正确性、可读性等SFT模型优化和调整,让模型的输出效率更好
  • 推理问答阶段:给出病例问题,分诊台基于积累的经验路由给不同的专家判断,然后综合给出预测的答案

3.3 MLA 多头注意力

deepseek技术解读(1)-彻底理解MLA(Multi-Head Latent Attention):
https://zhuanlan.zhihu.com/p/16730036197

MLA主要通过优化KV-cache来减少显存占用,从而提升推理性能,这是因为

要理解MLA,先得看MHA的cache设计,为了方便理解kv cache的成本,可以认为后一个toten的输入时,依赖了前N个toten在各层的网络缓存,因此1个toten会需要2(key+value)*层数l*每层注意力数量h*注意力的维数w*float宽度:

以上图为例,则1个toten存储的数量就是 2(key+value)*层数80*每层注意力数量64*注意力的维度128*float宽度2B=2*80*64*128*2B=2.63MB,这个缓存对于显存的使用非常巨大,B = 32 , S = 4096,这个缓存需求高达343GB

由于ds模型的输入带了think的toten都非常长,因此DeepSeek对kv进行了压缩,引入了MLA对矩阵进行降秩压缩,业界的压缩方案方案包括

方案

参数规模

优劣势

MQA(Multi-Query Attention)

2*l*h*w*2B

每层仅留下1个注意力向量

GQA(Group-Query Attention)

2*l*g*w*2B

g是分组的数量,当g=h的时候与MHA就等价了

MLA的思路,本质上是把h*w的多头注意力向量转换成了一个两个压缩矩阵,在每次计算时再还原,通过增加计算时间再转换回原空间

  • 对于input的ht维度为7168,经过低秩变换矩阵Wdkv(512x7168) 变成 Wdkv(512x7168)*ht(7168)=Ctkv 512x1维【参考线性代代数的矩阵乘法】
  • 然后再通过两个KV变化矩阵Wuk/Wuv(64*128*512),将上述512维的矩阵进一步还原成 W(64*64*512)*ctkv(512*1)=64*128 【注意此处已经和MQA的h*w一致】

下面来计算,MLA的这种机制分别优化了多少存储和计算【下述估算可能不是特别严谨全面,可以参考对比】

  • 存储:首先模型本身,相比MQA,新增了Wdkv、Wuk、Wuv三个转换矩阵,对应的大小为2*l层*(降秩512*7168+2个kv *64*128*512)*2B=2.5GB【注意这个是模型参数,不随输入变化,所以成本可控】;对于动态toten,每一层的缓存大小为 2*l*512*2B=160k (相比原来的2.62MB减少了16倍),因此对于长toten比较有吸引力(简单初略估计,只要toten超过1k,kv cache+模型现存 胜过了MQA)
  • 计算:增加了低秩转换、KV变化矩阵恢复,也是非常海量的float增加,但由于都是矩阵计算,GPU比较擅长,就不单独估算计算成本了,对于位置偏移相关的也做了类似的优化(参考ROPE)

从上面可以看出,存储优化在长文本时更明显,短文本反而模型更大了,当然根据目前ds处理的任务复杂度,可以认为都是长文本(含思维链),所以这是非常亮眼的优化

3.4 FP8混合训练

重大的创新在于训练时已经结合网络特征部分选取了fp8,做到了native fp8的训练,不仅减少了传输而且对inffer时的量化损失也做到了最小。当然这里边挑战也是非常大的,因为训练过程中fp16降低为fp8可能导致精度不足,训练无法收敛的灾难!

因此由于不同模块的精度不同,就需要在模块之间穿插量化(to FP8)/反量化(to FP16)计算,DeepSeek kernel.py中统一提供了此类接口和优化,灵活的实现fp8和fp16的转换,从而节省一些训练参数的现存用量!

顺便提一下,在训练框架方面,研究团队开发的 DualPipe 算法(GPU在forward和backward中切换,IO同时并行传输)实现了高效的流水线并行处理,减少了流水线停滞,并通过计算和通信并行处理的方式降低了训练过程中的通信开销。如下图所示,gpu的气泡非常少,确实并行做的非常赞!只要维持适当的计算通信比例,就能在不同节点间实现细粒度专家分配,同时将全节点间的通信开销降至接近于零

四、人工智能的局限性

大模型出来后,很多都在讨论工作的可替代性问题,晚上下班正好路上听了 董坤 的人工智能的分享,分享下他的观点,供参考,或许可以缓解大家的一部分焦虑

问责性(Accountability)

  • 不能承担后果,因此不能承担重大决策,比如医生虽然可能误诊,但是整体为后果负责,而AI大模型不具备这个能力
  • 个人的决策对公司和家庭越发重要,人就越不可替代,因为决策的重要性,管理工作短时间还得依赖人,但可以AI辅助,比如人的招聘AI可以参与,但人的“选用育留”仍旧还需要高质量的管理者

有限性(Boundedness)

  • AI无法理解情绪价值,情绪价值是智力资本时代创造价值的主导
  • AI不能创新,只能因循守旧,而创新机制是管理价值的最大体现

欺骗性(Cheating)

  • 长尾知识的可靠性不足
  • 知识的的时效性等

愚蠢性(Dumbness)

  • 背后的真正的语义其实并不理解,比如你吃了么等原始意图理解压根不需要思考的回答

不过董老师的观点还是在于人要回归创新创造上来,他的观点是大模型本身不具备创新,更多的在于历史知识的归纳,这个仁者见仁,智者见智了


附录:大模型带你解读 Deepseek-v3/model.py 核心模型代码

model.py 文件实现了一个基于 Transformer 架构的深度学习模型,其中集成了量化计算、混合专家(Mixture-of-Experts, MoE)机制等技术,以提升模型的计算效率和性能。下面将从代码的整体结构、主要模块和类的功能等方面进行详细解读。

1. 导入模块

python

import math
from dataclasses import dataclass
from typing import Tuple, Optional, Literal

import torch
from torch import nn
import torch.nn.functional as F
import torch.distributed as dist

from kernel import act_quant, weight_dequant, fp8_gemm
  • 导入了数学计算、数据类定义、类型提示等基础模块。
  • 导入了torch及其相关子模块用于构建和训练深度学习模型。
  • 从kernel.py文件中导入了量化、反量化和 FP8 矩阵乘法等核心计算函数。

2. 全局变量定义

python

world_size = 1
rank = 0
block_size = 128
gemm_impl: Literal["bf16", "fp8"] = "bf16"
attn_impl: Literal["naive", "absorb"] = "absorb"
  • world_size和rank用于分布式训练,分别表示进程总数和当前进程的编号。
  • block_size是量化和反量化操作的块大小。
  • gemm_impl指定矩阵乘法的实现方式,可选bf16(BFloat16)或fp8(FP8)。
  • attn_impl指定注意力机制的实现方式,可选naive(简单实现)或absorb。

3. ModelArgs数据类

python

@dataclass
class ModelArgs:
    max_batch_size: int = 8
    max_seq_len: int = 4096 * 4
    dtype: Literal["bf16", "fp8"] = "bf16"
    # 其他属性...
  • 该数据类用于定义模型的各种参数和超参数,包括最大批量大小、最大序列长度、数据类型、词汇表大小等。
  • 通过使用@dataclass装饰器,可以方便地定义和管理这些参数。

4. 主要模块和类

4.1 ParallelEmbedding类

python

class ParallelEmbedding(nn.Module):
    def __init__(self, vocab_size: int, dim: int):
        pass

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        pass
  • 该类实现了支持分布式并行的嵌入层,用于将输入的 token 索引转换为嵌入向量。
  • 在分布式环境下,会对输入的 token 进行处理,确保每个进程只处理自己负责的部分词汇表。

4.2 Linear类

python

class Linear(nn.Module):
    dtype = torch.bfloat16

    def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
        pass

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        pass
  • 自定义的线性层,支持量化权重和可选的偏置项。
  • 根据权重的量化情况,在forward方法中会调用不同的线性计算方式。

4.3ColumnParallelLinear和RowParallelLinear类

python

class ColumnParallelLinear(Linear):
    def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
        pass

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        pass

class RowParallelLinear(Linear):
    def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
        pass

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        pass
  • 分别实现了列并行和行并行的线性层,用于在分布式环境下进行矩阵乘法的并行计算。

4.4 RMSNorm类

python

class RMSNorm(nn.Module):
    def __init__(self, dim: int, eps: float = 1e-6):
        pass

    def forward(self, x: torch.Tensor):
        pass
  • 实现了 Root Mean Square Layer Normalization(RMSNorm),用于对输入张量进行归一化处理。

4.5 MLA类

python

class MLA(nn.Module):
    def __init__(self, args: ModelArgs):
        pass

    def forward(self, x: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]):
        pass
  • 实现了多头注意力层(Multi-Headed Attention Layer),支持低秩自适应(LoRA)技术。
  • 在forward方法中,会对查询、键和值进行投影、旋转位置编码等操作,并计算注意力分数。

4.6MLP类

python

class MLP(nn.Module):
    def __init__(self, dim: int, inter_dim: int):
        pass

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        pass
  • 实现了多层感知机(Multi-Layer Perceptron),作为 Transformer 中的前馈网络。

4.7 Gate类

python

class Gate(nn.Module):
    def __init__(self, args: ModelArgs):
        pass

    def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
        pass
  • 实现了混合专家(MoE)模型中的门控机制,用于将输入路由到不同的专家模块。

4.8 Expert类

python

class Expert(nn.Module):
    def __init__(self, dim: int, inter_dim: int):
        pass

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        pass
  • 实现了 MoE 模型中的专家模块,每个专家模块是一个独立的多层感知机。

4.9MoE类

python

class MoE(nn.Module):
    def __init__(self, args: ModelArgs):
        pass

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        pass
  • 实现了混合专家(MoE)模块,结合了门控机制和多个专家模块。
  • 在forward方法中,会根据门控机制的输出将输入路由到不同的专家模块,并将专家模块的输出进行加权求和。

4.10 Transformer类

python

class Transformer(nn.Module):
    def __init__(self, args: ModelArgs):
        pass

    @torch.inference_mode()
    def forward(self, tokens: torch.Tensor, start_pos: int = 0):
        pass
  • 实现了整个 Transformer 模型,包含嵌入层、多个 Transformer 块、归一化层和输出投影层。
  • 在forward方法中,会对输入的 token 进行嵌入、位置编码、注意力计算、前馈网络计算等操作,最终输出词汇表上的 logits。

5. 辅助函数

python

def linear(x: torch.Tensor, weight: torch.Tensor, bias: Optional[torch.Tensor] = None) -> torch.Tensor:
    pass

def precompute_freqs_cis(args: ModelArgs) -> torch.Tensor:
    pass

def apply_rotary_emb(x: torch.Tensor, freqs_cis: torch.Tensor) -> torch.Tensor:
    pass
  • linear函数实现了线性变换,支持量化和非量化的权重。
  • precompute_freqs_cis函数用于预计算旋转位置编码所需的复指数值。
  • apply_rotary_emb函数用于将旋转位置编码应用到输入张量上。

总结

model.py 文件实现了一个功能丰富的 Transformer 模型,集成了量化计算、混合专家机制、分布式训练等技术。通过这些技术的应用,可以提高模型的计算效率和性能,同时减少内存占用。代码的结构清晰,各个模块和类的职责明确,便于扩展和维护。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言