网易首页 > 网易号 > 正文 申请入驻

用PyTorch从零开始编写DeepSeek-V2

0
分享至

DeepSeek-V2是一个强大的开源混合专家(MoE)语言模型,通过创新的Transformer架构实现了经济高效的训练和推理。该模型总共拥有2360亿参数,其中每个令牌激活21亿参数,支持最大128K令牌的上下文长度。

在开源模型中,DeepSeek-V2实现了顶级性能,成为最强大的开源MoE语言模型。在MMLU(多模态机器学习)上,DeepSeek-V2以较少的激活参数实现了顶尖的性能。与DeepSeek 67B相比,DeepSeek-V2显著提升了性能,降低了42.5%的训练成本,减少了93.3%的KV缓存,并将最大生成吞吐量提高了5.76倍。

我们这里主要实现实现DeepSeek的主要改进:多头隐性注意力、细粒度专家分割和共享的专家隔离

架构细节

DeepSeek-V2整合了两种创新架构,我们将详细讨论:

  1. 用于前馈网络(FFNs)的DeepSeekMoE架构。
  2. 用于注意力机制的多头隐性注意力(MLA)。

DeepSeekMoE

在标准的MoE架构中,每个令牌被分配给一个(或两个)专家,每个MoE层都有多个在结构上与标准前馈网络(FFN)相同的专家。这种设置带来了两个问题:指定给令牌的专家将试图在其参数中聚集不同类型的知识,但这些知识很难同时利用;其次,被分配给不同专家的令牌可能需要共同的知识,导致多个专家在各自的参数中趋向于收敛,获取共享知识。

为了应对这两个问题,DeepSeekMoE引入了两种策略来增强专家的专业化:

  1. 细粒度专家分割:为了在每个专家中更有针对性地获取知识,通过切分FFN中的中间隐藏维度,将所有专家分割成更细的粒度。
  2. 共享专家隔离:隔离某些专家作为始终被激活的共享专家,旨在捕获不同上下文中的共同知识,并通过将共同知识压缩到这些共享专家中,减少其他路由专家之间的冗余。

让我们来定义DeepSeekMoE中第t个令牌的专家分配。如果u_t是该令牌的FFN输入,其输出h`_t将会是:

其中和分别是共享专家和路由专家的数量;FFN()和FFN()分别表示-th共享专家和-th路由专家。

对于路由专家而言,g_i,t 是第i个路由专家的门控值,s_i,t 是令牌到专家的亲和分数,Topk(., Kr) 包含了Kr个最高的亲和分数,其中Kr是活跃的路由专家的数量。

有了以上的公式,我们就来使用代码实现

门控模型实现:

class MoEGate(torch.nn.Module):
def __init__(self, num_experts_per_tok: int, n_routed_experts: int, routed_scaling_factor: int, topk_method: str, n_group: int, topk_group: int, hidden_size: int):
super().__init__()
self.top_k = num_experts_per_tok
self.n_routed_experts = n_routed_experts
self.routed_scaling_factor = routed_scaling_factor
self.topk_method = topk_method
self.n_group = n_group
self.topk_group = topk_group
self.weight = torch.nn.Parameter(torch.empty((self.n_routed_experts, hidden_size)))
torch.nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
def forward(self, x: torch.Tensor):
batch, seq_len, h = x.shape
hidden_states = x.view(-1, h)
logits = torch.nn.functional.linear(hidden_states.type(torch.float32), self.weight.type(torch.float32), None)
scores = logits.softmax(dim=-1, dtype=torch.float32)
if self.topk_method == "greedy":
topk_weight, topk_idx = torch.topk(scores, k=self.top_k, dim=-1, sorted=False)
elif self.topk_method == "group_limited_greedy":
group_scores = (scores.view(batch * seq_len, self.n_group, -1).max(dim=-1).values)
group_idx = torch.topk(group_scores, k=self.topk_group, dim=-1, sorted=False)[1] # [n, top_k_group]
group_mask = torch.zeros_like(group_scores) # [n, n_group]
group_mask.scatter_(1, group_idx, 1) # [n, n_group]
score_mask = (
group_mask.unsqueeze(-1)
.expand(
batch * seq_len, self.n_group, self.n_routed_experts // self.n_group
)
.reshape(batch * seq_len, -1)
) # [n, e]
tmp_scores = scores.masked_fill(~score_mask.bool(), 0.0) # [n, e]
topk_weight, topk_idx = torch.topk(
tmp_scores, k=self.top_k, dim=-1, sorted=False
)
return topk_idx, topk_weight

MoE

class MoE(torch.nn.Module):
def __init__(self, dim: int, routed_scaling_factor: int, topk_method: str, n_group: int, topk_group: int, hidden_dim: int | None = None, n_routed_experts: int = 12, num_experts_per_tok: int = 4, n_shared_experts: int = 2, mlp: str = "swiglu"):
super().__init__()
self.experts_per_rank = n_routed_experts
self.num_experts_per_tok = num_experts_per_tok
self.n_shared_experts = n_shared_experts
mlp_block = SwiGLU
self.experts = torch.nn.ModuleList([mlp_block(dim, hidden_dim) for i in range(n_routed_experts)])
self.gate = MoEGate(num_experts_per_tok, n_routed_experts, routed_scaling_factor, topk_method, n_group, topk_group, dim)
self.shared_experts = mlp_block(dim, hidden_dim * n_shared_experts)
def forward(self, x: torch.Tensor):
identity = x
orig_shape = x.shape
topk_idx, topk_weight = self.gate(x)
x = x.view(-1, x.shape[-1])
flat_topk_idx = topk_idx.view(-1)
x = x.repeat_interleave(self.num_experts_per_tok, dim=0)
y = torch.empty_like(x)
y = y.type(x.dtype)
for i, expert in enumerate(self.experts):
y[flat_topk_idx == i] = expert(x[flat_topk_idx == i]).to(dtype=x.dtype)
y = (y.view(*topk_weight.shape, -1) * topk_weight.unsqueeze(-1)).sum(dim=1)
y = y.view(*orig_shape)
output = y + self.shared_experts(identity)
return output

多头隐性注意力(MLA)

多头隐性注意力(MLA)相较于标准的多头注意力(MHA)实现了更优的性能,并且显著减少了KV缓存,提高了推理效率。与多查询注意力(MQA)和分组查询注意力(GQA)中减少KV头的方法不同,MLA将键(Key)和值(Value)共同压缩成一个潜在向量。

MLA不是缓存键(Key)和值(Value)矩阵,而是将它们联合压缩成一个低秩向量,这使得缓存的项目数量更少,因为压缩维度远小于多头注意力(MHA)中输出投影矩阵的维度。

标准的RoPE(旋转位置嵌入)与上述的低秩KV压缩不兼容。解耦RoPE策略使用额外的多头查询q_t和共享键k_t来实现RoPE。

下面总结了完整的MLA计算过程:

MLA实现

class MLA(torch.nn.Module):
def __init__(self, model_args: DeepseekConfig):
super().__init__()
d_model = model_args.d_model
self.num_heads = model_args.num_heads
self.head_dim = model_args.d_model // model_args.num_heads
self.attn_dropout = torch.nn.Dropout(model_args.dropout)
self.res_dropout = torch.nn.Dropout(model_args.dropout)
self.flash_attn = hasattr(torch.nn.functional, "scaled_dot_product_attention")
self.q_lora_rank = model_args.q_lora_rank
self.qk_rope_head_dim = model_args.qk_rope_head_dim
self.kv_lora_rank = model_args.kv_lora_rank
self.v_head_dim = model_args.v_head_dim
self.qk_nope_head_dim = model_args.qk_nope_head_dim
self.q_head_dim = model_args.qk_nope_head_dim + model_args.qk_rope_head_dim
self.q_a_proj = torch.nn.Linear(d_model, model_args.q_lora_rank, bias=False)
self.q_a_layernorm = RMSNorm(model_args.q_lora_rank)
self.q_b_proj = torch.nn.Linear(model_args.q_lora_rank, self.num_heads * self.q_head_dim, bias=False)
self.kv_a_proj_with_mqa = torch.nn.Linear(d_model,model_args.kv_lora_rank + model_args.qk_rope_head_dim,bias=False,)
self.kv_a_layernorm = RMSNorm(model_args.kv_lora_rank)
self.kv_b_proj = torch.nn.Linear(model_args.kv_lora_rank,self.num_heads * (self.q_head_dim - self.qk_rope_head_dim +
self.v_head_dim),bias=False,)
self.o_proj = torch.nn.Linear(self.num_heads * self.v_head_dim,d_model, bias=False,)
def forward(self, x: torch.Tensor, mask: torch.Tensor, freqs_cis) -> torch.Tensor:
batch, seq_len, d_model = x.shape
q = self.q_b_proj(self.q_a_layernorm(self.q_a_proj(x)))
q = q.view(batch, seq_len, self.num_heads, self.q_head_dim).transpose(1, 2)
q_nope, q_pe = torch.split(q, [self.qk_nope_head_dim, self.qk_rope_head_dim], dim=-1)
compressed_kv = self.kv_a_proj_with_mqa(x)
compressed_kv, k_pe = torch.split(compressed_kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1)
k_pe = k_pe.view(batch, seq_len, 1, self.qk_rope_head_dim).transpose(1, 2)
kv = (self.kv_b_proj(self.kv_a_layernorm(compressed_kv))
.view(batch, seq_len, self.num_heads, self.qk_nope_head_dim + self.v_head_dim)
.transpose(1, 2))
k_nope, value_states = torch.split(kv, [self.qk_nope_head_dim, self.v_head_dim], dim=-1)
q_pe, k_pe = apply_rope(q_pe, k_pe, freqs_cis)
k_pe = k_pe.transpose(2, 1)
q_pe = q_pe.transpose(2, 1)
query_states = k_pe.new_empty(batch, self.num_heads, seq_len, self.q_head_dim)
query_states[:, :, :, : self.qk_nope_head_dim] = q_nope
query_states[:, :, :, self.qk_nope_head_dim :] = q_pe
key_states = k_pe.new_empty(batch, self.num_heads, seq_len, self.q_head_dim)
key_states[:, :, :, : self.qk_nope_head_dim] = k_nope
key_states[:, :, :, self.qk_nope_head_dim :] = k_pe
attn_mtx = torch.matmul(query_states, key_states.transpose(2, 3)) / math.sqrt(self.head_dim)
attn_mtx = attn_mtx + mask[:, :, :seq_len, :seq_len]
attn_mtx = torch.nn.functional.softmax(attn_mtx.float(), dim=-1).type_as(key_states)
attn_mtx = self.attn_dropout(attn_mtx)
output = torch.matmul(attn_mtx, value_states) # (batch, n_head, seq_len, head_dim)
output = output.transpose(1, 2).contiguous().view(batch, seq_len, self.num_heads * self.v_head_dim)
output = self.o_proj(output)
output = self.res_dropout(output)
return output

总结

本文详细介绍了DeepSeek-V2语言模型,这是一个强大的开源混合专家(MoE)语言模型,采用创新的架构来提高训练和推理的经济性和效率。DeepSeek-V2采用了两种核心技术:细粒度专家分割和共享专家隔离,这两种策略显著提高了专家的专业化水平。此外,文章还介绍了多头隐性注意力(MLA),这是一种改进的注意力机制,通过低秩键值联合压缩和解耦旋转位置嵌入,优化了模型的存储和计算效率。

除了理论探讨,我们通过编写代码实现DeepSeek-V2,可以更深入地理解其架构和工作原理。可以帮助你账务如何实现先进的混合专家(MoE)模型,还能深化对多头隐性注意力(MLA)和低秩键值压缩等关键技术的理解。通过实践,读者将能够验证理论的有效性,并对模型的性能和效率有直观的认识。

https://avoid.overfit.cn/post/317a967c8dac42ee98f96d8390851476

作者:Zain ul Abideen

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
福建20岁女网红流浪柬埔寨街头!被园区榨干后像垃圾一样丢掉?

福建20岁女网红流浪柬埔寨街头!被园区榨干后像垃圾一样丢掉?

烈史
2026-01-04 18:25:34
越南转头又要中国造高铁,直接表示不要技术,只要中国能来就行

越南转头又要中国造高铁,直接表示不要技术,只要中国能来就行

我心纵横天地间
2026-01-04 14:13:28
6年了,郭麒麟的反击几乎断送了朱亚文的演艺生涯

6年了,郭麒麟的反击几乎断送了朱亚文的演艺生涯

小熊侃史
2025-12-25 11:24:12
仅差24个!仅差78分!杜兰特迎来双里程碑,乔丹的纪录也保不住了

仅差24个!仅差78分!杜兰特迎来双里程碑,乔丹的纪录也保不住了

世界体育圈
2026-01-04 18:19:35
皇马翻盘难了!巴萨2-0后9连胜,西甲领先7分,争冠还有一优势

皇马翻盘难了!巴萨2-0后9连胜,西甲领先7分,争冠还有一优势

篮球看比赛
2026-01-04 11:21:40
20岁女孩柬埔寨流浪后续:长得很漂亮,父亲也被骗,前后转了8万

20岁女孩柬埔寨流浪后续:长得很漂亮,父亲也被骗,前后转了8万

好贤观史记
2026-01-04 17:25:08
上海一消费者在米其林餐厅吃出鱼钩,消费六千多全免单餐厅致歉

上海一消费者在米其林餐厅吃出鱼钩,消费六千多全免单餐厅致歉

江西晨报
2026-01-04 16:14:52
后背发凉!一月入3万36岁女高管,失业8个月加离婚,如今送外卖了

后背发凉!一月入3万36岁女高管,失业8个月加离婚,如今送外卖了

火山詩话
2026-01-02 19:14:41
被四家医院判定为肺癌并要求手求,最后的检查结果救了我一命!

被四家医院判定为肺癌并要求手求,最后的检查结果救了我一命!

坠入二次元的海洋
2026-01-01 11:10:01
方媛上海购物被偶遇!生图个子矮小身形肥硕,溜肩驼背无名媛气质

方媛上海购物被偶遇!生图个子矮小身形肥硕,溜肩驼背无名媛气质

娱圈小愚
2026-01-04 11:01:31
小姐姐这身打扮完,美示范了职场裤里丝穿搭的正确打开方式

小姐姐这身打扮完,美示范了职场裤里丝穿搭的正确打开方式

美女穿搭分享
2026-01-04 18:17:05
超市扫码机器可以读取秃顶!?节目找来地中海大叔实测,结果..

超市扫码机器可以读取秃顶!?节目找来地中海大叔实测,结果..

英国那些事儿
2026-01-03 23:04:42
芯片天塌了。光刻机突然不金贵了。一条大新闻砸懵整个圈子。

芯片天塌了。光刻机突然不金贵了。一条大新闻砸懵整个圈子。

普陀动物世界
2026-01-04 12:02:53
美军或用对付伊拉克的方法,对付中国?一旦开战,卫星肯定不保

美军或用对付伊拉克的方法,对付中国?一旦开战,卫星肯定不保

妙知
2025-12-09 00:16:52
36年前陈宝国主演的盗墓恐怖片!尺度大到少儿不宜

36年前陈宝国主演的盗墓恐怖片!尺度大到少儿不宜

释凡电影
2025-08-14 09:33:19
引众怒,邱彪和克里斯齐齐被驱逐,媒体专家直言:匪夷所思

引众怒,邱彪和克里斯齐齐被驱逐,媒体专家直言:匪夷所思

邹维体育
2026-01-04 21:43:34
一针实现肿瘤临床清零!多款癌症疫苗攻克胰腺癌、肺癌等12大癌种

一针实现肿瘤临床清零!多款癌症疫苗攻克胰腺癌、肺癌等12大癌种

无癌家园i
2026-01-04 10:51:53
NBA最老30分榜:詹姆斯超越詹姆斯!前11有10个是詹姆斯!

NBA最老30分榜:詹姆斯超越詹姆斯!前11有10个是詹姆斯!

氧气是个地铁
2026-01-04 15:45:39
新疆代理主帅:想回到强队行列必须找回强硬防守,齐麟目前无法自行走路

新疆代理主帅:想回到强队行列必须找回强硬防守,齐麟目前无法自行走路

懂球帝
2026-01-04 22:33:17
A股:周日中午传来1大核弹级利空!下周很可能会迎更大级别大行情?

A股:周日中午传来1大核弹级利空!下周很可能会迎更大级别大行情?

股市皆大事
2026-01-04 10:14:32
2026-01-05 00:28:49
deephub incentive-icons
deephub
CV NLP和数据挖掘知识
1880文章数 1440关注度
往期回顾 全部

科技要闻

雷军:骂小米汽车有流量,但别故意抹黑

头条要闻

特朗普为什么还要掳走马杜罗夫人 美媒分析

头条要闻

特朗普为什么还要掳走马杜罗夫人 美媒分析

体育要闻

女子世界第一,9年前在咖啡店洗碗

娱乐要闻

《小城大事》上星央八 热血筑梦正当时

财经要闻

李迅雷:扩内需必须把重心从"投"转向"消"

汽车要闻

最高续航310km 岚图泰山8或将上半年发布

态度原创

艺术
数码
房产
旅游
公开课

艺术要闻

故宫一级文物:和珅送给乾隆的80大寿贺礼

数码要闻

大疆Power 1000 Mini户外电源主要配置公布,1月6日发售

房产要闻

单盘最高狂卖64亿!海南楼市2025年最全榜单发布!

旅游要闻

地铁直达!深圳这一片花海刷屏!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版