
摘要:本文是《LLM技术全景:从Token到部署》系列第十一篇,技术原理篇第三讲。如果说Transformer是大模型的"发动机",那MoE(Mixture of Experts)就是给发动机装上了"智能分配系统"------不是每个零件都同时转,而是根据任务动态激活最合适的"专家子网络"。这一思路让DeepSeek-V3用671B总参数、只激活37B就打平了同量级Dense模型的性能,推理成本降低数倍。本文从原理到工程全面解析MoE。
阅读收获:① 理解MoE的核心思想------条件计算(Conditional Computation);② 掌握Top-K专家路由算法与负载均衡机制;③ 了解Switch Transformer、Mixtral 8×7B、DeepSeek-V3的MoE设计演进;④ 搞懂MoE在推理成本上的工程优势;⑤ 理解MoE的局限性和适用场景。
一、引言:为什么需要MoE?
先从一个思维实验开始:
假设你要建立一个"万能专家团队":
方案A(Dense模型):
雇一位超级通才,他精通所有领域------数学、语言、代码、逻辑......
每回答一个问题,他把所有知识全部过一遍。
优点:结构简单,知识整合性好
缺点:计算浪费------回答简单问题也要"动用"全部能力
方案B(MoE):
雇一批专家------数学家、程序员、语言学家、历史学家......
外加一位"协调员",负责根据问题类型,选最合适的专家回答。
优点:专家专注,避免计算浪费
缺点:协调员可能判断失误;专家之间知识隔离
MoE采用的正是方案B的思路 。这个想法并不新------1991年Jacobs等人就提出了Mixture of Experts的概念,但真正让它在大模型领域大放异彩,是2021年Google的Switch Transformer。
1.1 MoE解决了什么核心问题?
随着模型规模增大,一个基本矛盾浮出水面:
矛盾:
模型越大 → 性能越好(Scaling Law)
模型越大 → 推理越贵(计算量 ∝ 参数量)
MoE的解法:
增加"总参数量"(更多专家 = 更多知识容量)
保持"激活参数量"不变(每次只用少数专家)
结果:
知识容量 ↑ (可以学习更多样化的知识)
单次推理成本 ≈ 不变 (只激活部分参数)
这是MoE的本质魔法:用存储成本换计算成本。
二、MoE的核心机制:专家路由
2.1 基本架构
一个标准的Transformer层包含两个部分:
- Multi-Head Self-Attention(MHA)
- Feed-Forward Network(FFN)
MoE的改动是:将单一FFN替换为N个并行的FFN Expert,加一个Router决定每次激活哪几个。
标准Transformer FFN层:
Input → Linear(d_model, d_ff) → GELU → Linear(d_ff, d_model) → Output
MoE替换后:
Input → Router → 选出Top-K Expert → 加权求和 → Output
↓ ↓ ↓
路由权重 Expert 1 Expert 2
FFN_1(x) FFN_2(x)
↑ 权重w1 ↑ 权重w2
数学形式:
MoE层的输出计算公式:
设输入 x,共 N 个专家,每次激活 K 个(通常 K=1 或 K=2):
Step 1:计算路由分数
s(x) = softmax(W_r · x) # 形状 [batch, N]
Step 2:选出Top-K专家
TopK_indices = argtopk(s(x), k=K)
Step 3:对选出专家归一化权重
w_i = s_i / Σ(s_j for j in TopK_indices)
Step 4:加权输出
Output = Σ(w_i · Expert_i(x)) for i in TopK_indices
2.2 Top-K路由的实现
python
import torch
import torch.nn as nn
import torch.nn.functional as F
class Expert(nn.Module):
"""单个专家网络(就是普通的FFN)"""
def __init__(self, d_model: int, d_ff: int):
super().__init__()
self.w1 = nn.Linear(d_model, d_ff, bias=False)
self.w2 = nn.Linear(d_ff, d_model, bias=False)
self.act = nn.SiLU() # LLaMA风格激活
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.w2(self.act(self.w1(x)))
class TopKRouter(nn.Module):
"""Top-K 专家路由器"""
def __init__(self, d_model: int, n_experts: int, top_k: int):
super().__init__()
self.n_experts = n_experts
self.top_k = top_k
self.gate = nn.Linear(d_model, n_experts, bias=False)
def forward(self, x: torch.Tensor):
# x: [batch, seq_len, d_model]
# 计算路由分数
logits = self.gate(x) # [batch, seq_len, n_experts]
scores = F.softmax(logits, dim=-1)
# 选出Top-K专家
topk_scores, topk_indices = torch.topk(scores, self.top_k, dim=-1)
# topk_scores: [batch, seq_len, top_k]
# topk_indices: [batch, seq_len, top_k]
# 对Top-K权重归一化
topk_weights = topk_scores / topk_scores.sum(dim=-1, keepdim=True)
return topk_weights, topk_indices, scores
class MoELayer(nn.Module):
"""完整的MoE层"""
def __init__(self, d_model: int, d_ff: int, n_experts: int, top_k: int):
super().__init__()
self.n_experts = n_experts
self.top_k = top_k
# N个专家网络
self.experts = nn.ModuleList([
Expert(d_model, d_ff) for _ in range(n_experts)
])
# 路由器
self.router = TopKRouter(d_model, n_experts, top_k)
def forward(self, x: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
batch, seq_len, d_model = x.shape
# 路由决策
topk_weights, topk_indices, all_scores = self.router(x)
# 展平处理(方便批量计算)
x_flat = x.view(-1, d_model) # [batch*seq_len, d_model]
output = torch.zeros_like(x_flat) # 初始化输出
# 对每个专家分别处理
for expert_idx in range(self.n_experts):
# 找出哪些token被路由到这个专家
# topk_indices: [batch*seq_len, top_k]
topk_flat = topk_indices.view(-1, self.top_k)
expert_mask = (topk_flat == expert_idx).any(dim=-1) # [batch*seq_len]
if not expert_mask.any():
continue # 这个专家本次没有被激活
# 收集该专家的输入token
expert_input = x_flat[expert_mask] # [n_tokens, d_model]
expert_output = self.experts[expert_idx](expert_input)
# 找出对应的路由权重
weights_flat = topk_weights.view(-1, self.top_k)
token_weights = weights_flat[expert_mask] # [n_tokens, top_k]
# 取这个专家对应位置的权重
expert_rank = (topk_flat[expert_mask] == expert_idx).float()
token_weight = (token_weights * expert_rank).sum(dim=-1, keepdim=True)
# 加权累加到输出
output[expert_mask] += token_weight * expert_output
return output.view(batch, seq_len, d_model), all_scores
# 使用示例
model = MoELayer(d_model=512, d_ff=2048, n_experts=8, top_k=2)
x = torch.randn(2, 10, 512) # batch=2, seq_len=10
output, scores = model(x)
print(f"Input shape: {x.shape}")
print(f"Output shape: {output.shape}")
print(f"Router scores shape: {scores.shape}")
# 输出: Input shape: torch.Size([2, 10, 512])
# Output shape: torch.Size([2, 10, 512])
# Router scores shape: torch.Size([2, 10, 8])
2.3 负载均衡:MoE最大的工程挑战
你可能已经发现了一个问题:如果路由器总是把所有token都送到同一个专家,其他专家就完全没用了------这叫专家崩溃(Expert Collapse)。
专家崩溃问题:
初始阶段,专家A稍微强一点 →
路由器开始偏向专家A →
专家A获得更多梯度,训练更快 →
路由器进一步偏向专家A →
......(正反馈循环)
最终:99%的token都给了专家A,其他专家废了
解决方案:辅助损失(Auxiliary Loss)
Switch Transformer(Google,2021)引入了两种辅助损失来强制负载均衡:
python
def load_balancing_loss(router_probs: torch.Tensor,
expert_indices: torch.Tensor,
n_experts: int) -> torch.Tensor:
"""
Switch Transformer中的负载均衡损失
Args:
router_probs: [batch*seq, n_experts] - 路由概率
expert_indices: [batch*seq] - 每个token被分配到的专家索引
n_experts: 专家总数
Returns:
标量损失值
"""
num_tokens = router_probs.shape[0]
# f_i: 第i个专家处理的token比例(实际分配)
f = torch.zeros(n_experts, device=router_probs.device)
for i in range(n_experts):
f[i] = (expert_indices == i).float().mean()
# P_i: 路由器分配给第i个专家的平均概率
P = router_probs.mean(dim=0)
# 损失 = n_experts * Σ(f_i * P_i)
# 均匀分配时:f_i = 1/n,P_i = 1/n,损失 = n * n*(1/n^2) = 1
# 越不均匀,某项越大,损失越高
loss = n_experts * (f * P).sum()
return loss
# 训练时总损失 = 任务损失 + α × 负载均衡损失
# α 通常取 0.01 ~ 0.001(不能太大,否则模型专注于均衡而非性能)
total_loss = task_loss + 0.01 * load_balancing_loss(probs, indices, n_experts)
三、MoE大模型演进史
3.1 Switch Transformer(Google,2021)
Switch Transformer是让MoE在LLM规模上真正跑通的奠基之作。
核心创新:K=1(只激活1个专家)
传统MoE的困境:
Top-2 路由 → 需要将token的梯度"分叉"给2个专家 → 实现复杂,通信开销大
Switch Transformer的解法:
Top-1 路由 → 每个token只送给1个专家 → 实现大幅简化
实验结果:Top-1 vs Top-2,性能差距很小,但速度快得多
规模突破:Switch-C模型达到1.6万亿参数(1.6T),但实际激活参数量维持在Dense模型水平。
Switch-C vs T5-11B(当时最大的Dense模型):
同等计算预算下,Switch-C在SuperGLUE上提升4%
训练速度快7倍(因为激活参数少)
关键洞察:"参数量"和"计算量"可以解耦
Dense模型:参数量 ≈ 计算量(每次推理全部参数都参与)
MoE模型:参数量 >> 计算量(每次推理只激活小部分参数)
3.2 Mixtral 8×7B(Mistral AI,2023)
Mixtral是第一个大规模开源的高质量MoE模型。
Mixtral 8×7B架构:
├── 总专家数:8个(每层8个FFN专家)
├── 每次激活:2个(Top-2路由)
├── 总参数:46.7B(8×7B ≈ 56B,因共享Attention层实际是46.7B)
├── 激活参数:12.9B(每次只用2个专家)
└── 上下文长度:32K
性能对比(Mixtral 8×7B vs LLaMA 2 70B):
Mixtral (46.7B总参 / 12.9B激活) ≈ LLaMA 2 70B
推理速度:Mixtral 快约6倍(因激活参数少)
内存占用:Mixtral 需要约95GB(权重全加载),LLaMA 2 70B需要约140GB
一个经典问题:为什么Mixtral叫"8×7B",而不是"56B"?
答:因为只有FFN部分是8个专家各自独立的,Attention权重是所有专家共享的。
真正的独立部分 = 8个FFN(每个~7B中的FFN部分 ≈ 5B)
共享部分 = Attention + Embedding + LM Head
总参数 ≈ 46.7B(不是56B)
但"8×7B"这个命名方式传达了核心思想:
"我拥有8个7B模型的知识容量,但推理时只用其中2个的计算量"
3.3 DeepSeek-V3:MoE的工程巅峰
DeepSeek-V3(2024年底)是目前工程最复杂、性能最强的开源MoE模型之一。
DeepSeek-V3 MoE架构参数:
├── 总参数:671B
├── 每层专家数:256个(!)
├── 激活专家数:8个(Top-8路由)
├── 每次激活参数:约37B
├── 上下文长度:128K
└── 训练数据:14.8T tokens
vs 同量级Dense模型:
性能对标 LLaMA-3.1-405B(405B参数,全激活)
推理成本 ≈ 37B模型(仅激活37B参数)
推理速度提升约 10x
DeepSeek-V3的两项关键创新:
创新1:多Token预测(MTP,Multi-Token Prediction)
python
# 传统语言模型:每次预测下一个Token
# 输入:[BOS, The, quick, brown]
# 预测:fox
# MTP:同时预测接下来的2个Token
# 输入:[BOS, The, quick, brown]
# 预测:(fox, jumps)
#
# 优点:
# 1. 训练信号更密集(每步2个监督信号)
# 2. 推理时可以"投机"一步,结合Speculative Decoding加速
class MultiTokenPrediction(nn.Module):
def __init__(self, vocab_size, d_model, predict_n=2):
super().__init__()
self.predict_n = predict_n
# 共享主干,每个位置一个独立预测头
self.heads = nn.ModuleList([
nn.Linear(d_model, vocab_size) for _ in range(predict_n)
])
def forward(self, hidden_states):
# 同时输出未来predict_n个token的预测
return [head(hidden_states) for head in self.heads]
创新2:无辅助损失的负载均衡(Auxiliary-loss-free Load Balancing)
传统MoE用辅助损失强制均衡,但这会干扰主任务的梯度。DeepSeek-V3提出了一个巧妙的替代方案:
辅助损失的问题:
loss_total = task_loss + α × balance_loss
梯度 = ∂task_loss/∂θ + α × ∂balance_loss/∂θ
这两个梯度方向可能相反 → 互相干扰 → 性能上限被限制
DeepSeek-V3的解法:动态偏置(Dynamic Bias)
不修改损失函数,而是在路由分数上加一个"偏置项":
adjusted_score_i = score_i + bias_i
bias_i 根据历史负载动态调整:
如果专家i过载 → bias_i 减小 → 该专家分数降低 → 减少流入
如果专家i空闲 → bias_i 增大 → 该专家分数升高 → 增加流入
关键:bias_i 只影响路由决策,不进入反向传播!
→ 梯度完全来自task_loss,不受均衡约束干扰
→ 性能更好,均衡也能保证
四、MoE vs Dense:详细对比
Dense模型 MoE模型
───────── ─────────
参数量 全部参与(小模型) 总量大(多专家),激活量小
推理成本 ∝ 总参数量 ∝ 激活参数量(通常为总量的10-20%)
内存需求 ∝ 总参数量 ∝ 总参数量(需要加载所有专家)
训练效率 每步更新全部参数 每步只更新激活的专家(梯度稀疏)
知识容量 受参数量限制 可以在有限激活下存储更多知识
实现复杂度 简单 复杂(路由、负载均衡、并行策略)
部署友好度 ⭐⭐⭐⭐⭐ ⭐⭐⭐(需特殊推理框架支持)
关键结论:
适合MoE的场景:
✅ 云端大规模推理(内存够,吞吐量要求高)
✅ 需要兼顾"大知识容量"和"低推理成本"
✅ 多样化任务(数学、代码、语言、推理并重)
✅ 批量处理场景(多token并行路由)
不适合MoE的场景:
❌ 内存极度受限(需要加载所有专家权重)
❌ 小批量/单token推理(路由overhead更明显)
❌ 任务单一(Dense模型更专注)
❌ 边缘设备部署(内存墙问题)
五、MoE的实践挑战与工程解法
5.1 专家并行(Expert Parallelism)
MoE的最大工程挑战:256个专家无法放到一张GPU上,需要分布式并行。
专家并行策略:
GPU 0: Expert 1, 2, ..., 64
GPU 1: Expert 65, 66, ..., 128
GPU 2: Expert 129, 130, ..., 192
GPU 3: Expert 193, 194, ..., 256
All-to-All通信:
Token被路由到不同GPU上的专家时,需要跨GPU传输激活值
这是MoE训练中最主要的通信瓶颈
解法:DeepSpeed MoE / Megatron-LM Expert Parallel
将Token的路由和专家计算放在不同的通信组
尽量让常用专家和数据并置(Locality Optimization)
5.2 Expert容量(Expert Capacity)
每个专家的处理能力是有限的------如果太多token都被路由到同一个专家,会导致溢出(Overflow)。
python
def route_with_capacity(router_probs, expert_indices, n_experts, capacity_factor=1.25):
"""
带容量限制的路由
Args:
capacity_factor: 容量系数(1.25表示允许超出均匀负载25%的buffer)
"""
batch_seq = router_probs.shape[0]
# 每个专家的最大容量
expert_capacity = int(capacity_factor * batch_seq / n_experts)
routed_tokens = []
expert_load = torch.zeros(n_experts, dtype=torch.int32)
overflow_tokens = []
for token_idx, expert_idx in enumerate(expert_indices):
if expert_load[expert_idx] < expert_capacity:
routed_tokens.append((token_idx, expert_idx, int(expert_load[expert_idx])))
expert_load[expert_idx] += 1
else:
# 该专家已满,token被丢弃(直接pass-through或路由给第二选择)
overflow_tokens.append(token_idx)
return routed_tokens, overflow_tokens, expert_load
# 注:DeepSeek-V3用动态偏置避免了大量overflow
# Mixtral的实现用了更精细的缓冲策略
5.3 vLLM对MoE的支持
2024年后,主流推理框架开始专门优化MoE推理:
python
# vLLM加载Mixtral 8×7B
from vllm import LLM, SamplingParams
# vLLM自动处理MoE的并行路由和内存管理
llm = LLM(
model="mistralai/Mixtral-8x7B-Instruct-v0.1",
tensor_parallel_size=2, # 2张A100/H100,每张80GB
# vLLM内部自动:
# 1. 将8个专家均匀分配到2张GPU
# 2. 路由决策时进行All-to-All通信
# 3. PagedAttention管理KV Cache
)
sampling_params = SamplingParams(temperature=0.7, max_tokens=512)
outputs = llm.generate(["解释MoE的核心优势"], sampling_params)
print(outputs[0].outputs[0].text)
六、实战:用Hugging Face加载MoE模型
python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# 加载 Mixtral 8×7B(需要约95GB显存,可量化后降至约50GB)
model_name = "mistralai/Mixtral-8x7B-Instruct-v0.1"
# 方式1:全精度加载(需要4×24GB或2×80GB显卡)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto", # 自动分配到多卡
)
# 方式2:4-bit量化(约需 26GB 显存,单卡 A6000 可运行)
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
)
model_4bit = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 查看MoE结构
def inspect_moe_structure(model):
"""分析MoE模型的专家分布"""
total_params = sum(p.numel() for p in model.parameters())
expert_params = 0
n_expert_layers = 0
for name, module in model.named_modules():
if 'experts' in name and hasattr(module, 'weight'):
expert_params += module.weight.numel()
if 'experts' in name and isinstance(module, torch.nn.ModuleList):
n_expert_layers += 1
print(f"总参数量: {total_params/1e9:.1f}B")
print(f"专家参数量: {expert_params/1e9:.1f}B")
print(f"非专家参数量: {(total_params - expert_params)/1e9:.1f}B")
print(f"专家层数: {n_expert_layers}")
inspect_moe_structure(model)
# 输出(以Mixtral 8×7B为例):
# 总参数量: 46.7B
# 专家参数量: 38.1B(8个专家×各自的FFN)
# 非专家参数量: 8.6B(Attention + Embedding等共享层)
# 专家层数: 32(每个Decoder层1个MoE Layer)
# 推理示例
messages = [
{"role": "user", "content": "用最简单的语言解释MoE(混合专家模型)"}
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
with torch.no_grad():
output = model.generate(**inputs, max_new_tokens=200, temperature=0.7, do_sample=True)
response = tokenizer.decode(output[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
print(response)
七、可视化:MoE的路由行为
一个有趣的问题:MoE路由器是否真的"分工合理"?现实中它是随机的,还是有规律的?
python
import torch
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
def analyze_expert_routing(model, tokenizer, texts: list[str]):
"""
分析MoE路由器的行为:
- 不同类型文本被路由到哪些专家?
- 专家是否真的"专业化"?
"""
expert_activations = {f"Layer_{i}": [] for i in range(32)}
# 注册hook来捕获路由决策
hooks = []
for layer_idx, layer in enumerate(model.model.layers):
if hasattr(layer, 'block_sparse_moe'): # Mixtral的MoE层命名
def make_hook(layer_idx):
def hook_fn(module, input, output):
# 捕获路由决策(expert_indices)
if isinstance(output, tuple):
router_logits = output[1] # 通常第二个输出是路由logits
expert_activations[f"Layer_{layer_idx}"].append(
router_logits.detach().cpu()
)
return hook_fn
hook = layer.block_sparse_moe.register_forward_hook(make_hook(layer_idx))
hooks.append(hook)
# 运行推理,收集路由数据
results = {}
categories = ["数学题", "代码生成", "诗歌创作", "历史知识"]
sample_texts = [
"计算 2^32 的精确值",
"def fibonacci(n): # 用Python实现斐波那契数列",
"春眠不觉晓,处处闻啼鸟",
"秦始皇统一六国的战略意义"
]
for category, text in zip(categories, sample_texts):
for k in expert_activations:
expert_activations[k] = [] # 清空
inputs = tokenizer(text, return_tensors="pt").to(model.device)
with torch.no_grad():
model(**inputs)
# 统计各层专家激活频率
if expert_activations["Layer_0"]:
layer_0_data = torch.stack(expert_activations["Layer_0"]).mean(0)
results[category] = layer_0_data.numpy()
# 清除hooks
for hook in hooks:
hook.remove()
return results
# 注:实际分析表明,MoE确实呈现出一定程度的"软专业化":
# - 数学/代码类token倾向于路由到特定专家
# - 语言/叙事类token倾向于路由到另一批专家
# - 但分工不是绝对的,每个专家都是"通才中的专家"
print("MoE的路由行为:专家呈现出软专业化特征,但非绝对分工")
print("这与人类社会的'专业化分工+跨领域协作'模式类似")
八、MoE的局限性与未来
8.1 当前局限
1. 内存墙问题
- 所有专家权重需要加载到内存
- 671B MoE模型需要 671×2 = 1342GB(BF16)显存
- 虽然推理快,但硬件门槛高
2. 训练不稳定
- 路由器容易产生崩溃(Expert Collapse)
- 负载均衡损失与任务损失的权衡难以调节
- 小batch训练时专家利用率低
3. 推理系统复杂
- All-to-All通信开销
- 专家并行需要特殊系统支持
- 动态路由导致计算图不规则(难以优化)
4. 泛化性争议
- 有研究表明MoE的专业化主要发生在浅层
- 深层专家分工不明显,接近Dense模型
- 部分场景下Dense模型更稳定
8.2 未来方向
1. 推理时MoE(Inference-time MoE)
- 在推理阶段动态决定激活哪些专家
- 而非在训练时就固定路由策略
2. 分层MoE(Hierarchical MoE)
- 粗粒度路由(任务类型)+ 细粒度路由(子能力)
- 类似人类的"专业团队内再细分"
3. 稀疏化Dense模型(Sparse Upcycling)
- 将训练好的Dense模型转换为MoE结构
- 避免从头训练MoE的不稳定性
4. 边缘MoE
- 通过知识蒸馏让小MoE模型也具备强性能
- 端侧部署时按需加载专家(流式专家)
九、总结
核心要点
1. MoE的本质:
✓ 条件计算(Conditional Computation)
✓ 总参数量大(知识容量),激活参数量小(计算成本)
✓ 用"存储换计算"
2. 关键技术:
✓ Top-K路由(通常K=1或K=2)
✓ 负载均衡损失(辅助损失 或 DeepSeek-V3的动态偏置)
✓ 专家并行(Expert Parallelism,多GPU分配专家)
3. 重要模型:
✓ Switch Transformer(2021):K=1的工程简化
✓ Mixtral 8×7B(2023):第一个高质量开源MoE
✓ DeepSeek-V3(2024):671B/37B激活,工程巅峰
4. 优劣总结:
✓ 优势:同等推理成本,更大知识容量;训练效率高
✗ 劣势:显存需求大;系统复杂;训练不稳定
5. 适用判断:
大规模云端推理 + 多样化任务 → 选MoE
内存受限 + 单一任务 + 边缘部署 → 选Dense
与前文的关联
前文(第9篇):GPT Decoder架构
↓
前文(第10篇):LLaMA的架构改进(RMSNorm / SwiGLU / RoPE / GQA)
↓
本篇(第11篇):MoE → 进一步解耦"知识容量"和"计算量"
↓
下篇(第12篇):长上下文技术 → 突破Transformer的位置限制
参考资料
- Shazeer et al. (2017) --- Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer(MoE应用于深度学习的奠基论文)
- Fedus et al. (2021) --- Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity(Switch Transformer,K=1创新)
- Jiang et al. (2024) --- Mixtral of Experts(Mixtral 8×7B技术报告)
- DeepSeek-AI (2024) --- DeepSeek-V3 Technical Report(MoE工程巅峰)
- Zoph et al. (2022) --- ST-MoE: Designing Stable and Transferable Sparse Expert Models(MoE稳定训练策略)
- Lepikhin et al. (2021) --- GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding(MoE分布式训练)
延伸讨论
思考题:
- DeepSeek-V3有256个专家,每次激活8个。你认为路由器是如何"学会"判断每种任务适合哪些专家的?它的训练信号是什么?
- 如果内存不是限制(比如有无限显存),你认为MoE是否一定比同参数Dense模型强?为什么?
- 边缘设备(如手机)上能运行MoE模型吗?需要什么样的系统支持?
实践作业:
- 用Hugging Face加载
mistralai/Mixtral-8x7B-Instruct-v0.1(4-bit量化),测试它在数学、代码、诗歌三类任务上的表现 - 尝试可视化路由器的专家激活频率(提示:可以注册forward hook捕获router_logits)
- 对比 Mixtral 8×7B(MoE,12.9B激活)和 LLaMA-2-13B(Dense)在相同问题上的回答质量和速度差异