十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

125B总参只激活6B?一文拆解MoE稀疏激活架构

125B总参只激活6B?一文拆解MoE稀疏激活架构 Qwen 新架构开源后讨论最集中的一组数字是 125B 总参、仅激活 6B。如果不了解 MoE很难判断这组数字的真实含义125B 会让人下意识认为显存需求极高6B 又会让人误以为它等于一个 6B 的 Dense 模型。实际上这是一个典型的稀疏激活混合专家架构。它把大量参数放进多个专家网络每次前向只由路由网络选择其中一小部分参与计算。把这组数字拆开理解是后续做权重检查、显存规划、推理调优和微调的前提。这里说的激活不是软件授权激活而是模型前向推理时真正产生计算和中间结果的参数。理解“总参”和“激活参”的区别比知道模型叫什么名字更重要。下面从架构原理开始一步步落到 Hugging Face 加载、config 检查、显存估算、LoRA 微调和部署排错。1. 先理解 125B 总参和 6B 激活参数的区别1.1 总参数与激活参数分别回答什么问题总参数描述模型里有多少权重。它决定模型文件的体积、加载权重时的显存需求、以及训练时优化器需要维护的状态规模。激活参数描述一个 token 在完整前向中实际被计算到的权重它决定单 token 推理的浮点计算量也直接影响延迟。对于 Dense 模型总参数和激活参数基本相等因为每个 token 会经过全部权重。对于 MoE 模型总参可以远大于激活参。比如 125B 总参、6B 激活意味着前向时大约只有 4.8% 的权重参与计算。其余权重仍然驻留在显存里但当前这一步不会执行。这个设计解决的是一个工程矛盾模型容量想要更大但单次推理成本不想等比例上升。把知识分散到更多专家里每次只激活对当前 token 最有用的一小部分就是 MoE 的核心思路。1.2 MoE 由路由器、专家网络和共享层组成一个典型的 Transformer MoE 层可以拆成三部分共享注意力层和归一化层每个 token 都计算和 Dense 模型一致。多个专家 FFN 子网络本来是一个大的 FFN现在拆成 N 个并行的 FFN。路由网络 gate根据当前 token 的 hidden state 计算每个专家的得分再通过 top-k 选出 6 个专家。理解路由最简单的方式是看一个示意实现import torch import torch.nn.functional as F def sparse_moe_forward(hidden_state, router, experts, top_k6): # hidden_state: [batch * seq_len, hidden_size] logits router(hidden_state) probs F.softmax(logits, dim-1) # 取 top_k 个专家 top_probs, top_indices torch.topk(probs, top_k, dim-1) # 对选中专家的权重做归一化 top_probs top_probs / top_probs.sum(dim-1, keepdimTrue) output torch.zeros_like(hidden_state) for i in range(top_k): expert experts[top_indices[..., i]] weight top_probs[..., i:i 1] output output weight * expert(hidden_state) return output这段代码只是说明原理生产环境不会这样写循环而会把多个 expert 计算批量化和矩阵化。核心逻辑是每个 token 不需要经过所有专家只经过被 router 选中的 top-k 个专家。1.3 同样是 6B 激活MoE 为什么比 6B Dense 更有吸引力如果最终只激活 6B 参数为什么不直接训练一个 6B Dense 模型原因在于容量和计算量的取舍。6B Dense 只有 6B 参数来存放知识容量是固定的。125B/6B 的 MoE 虽然有 125B 参数但每个 token 只使用 6B 左右的计算路径。训练时不同专家可以通过路由被不同领域的 token 激活模型总容量变大有机会记住更多模式。不过不能把“只激活 6B”理解成“速度等于 6B Dense”。MoE 模型的注意力层、共享层、路由计算仍然全量执行专家之间的通信和调度也有额外开销所以实际延迟会高于一个同结构的 6B Dense 模型。2. 开源之后第一步不是直接推理而是检查 config.json2.1 从 config.json 找到 MoE 关键字段开源模型的架构信息并不神秘权重目录里的 config.json 会直接暴露结构。Qwen 系列的新 MoE 架构在 Hugging Face 仓库中通常可以通过下面的字段确认{ model_type: qwen2_moe, num_hidden_layers: 24, hidden_size: 2048, num_experts: 64, num_experts_per_tok: 6, shared_expert_num: 1, moe_intermediate_size: 1024, router_aux_loss_coef: 0.01 }以上是示意配置不代表真实 Qwen 仓库的数值实际以你下载的权重目录中 config.json 为准。但字段含义是通用的。字段含义对工程的影响num_experts专家总数决定总参数量级和模型体积num_experts_per_tok每个 token 选中的专家数决定激活参数量级和单 token 计算量shared_expert_num共享专家数量共享专家每个 token 都会计算会增加固定开销moe_intermediate_size单个专家的 FFN 中间维度每个专家的大小影响总参和单专家计算量router_aux_loss_coef路由器负载均衡损失的系数训练时影响专家负载分布和稳定性2.2 对齐依赖版本避免基础环境不一致加载 MoE 模型前先确认 Python、PyTorch、transformers、accelerate 版本。不同版本对 MoE 结构的支持和实现细节不同尤其是Qwen2Moe这类新模型类型。一个常见的环境准备命令如下conda create -n qwen-moe python3.10 -y conda activate qwen-moe pip install torch --index-url https://download.pytorch.org/whl/cu121 pip install transformers accelerate这里的 cu121 只表示一个 CUDA 12.1 的 PyTorch wheel 示例实际版本要根据本机驱动和 CUDA 环境调整。如果模型仓库提供了 requirements.txt优先按仓库要求安装而不是直接安装最新版。2.3 用几行代码验证模型是不是 MoE先不加载完整权重只加载配置确认字段是否存在from transformers import AutoConfig model_name Qwen/Qwen-125B-MoE # 替换为真实仓库名 cfg AutoConfig.from_pretrained(model_name) print(model_type:, cfg.model_type) print(num_experts:, getattr(cfg, num_experts, None)) print(num_experts_per_tok:, getattr(cfg, num_experts_per_tok, None)) print(moe_intermediate_size:, getattr(cfg, moe_intermediate_size, None))如果打印结果是 None不要急着判断“这不是 MoE”。有些仓库会把 MoE 配置放在嵌套对象里字段名可能是moe_config或expert_config。这时需要直接看仓库里的 config.json而不是依赖 getattr。3. 推理前的显存估算与多卡策略3.1 权重显存必须按 125B 总参计算这是最容易踩的坑。很多人看到“仅激活 6B”就以为加载显存也能按 6B 算结果一启动就 OOM。权重显存和激活参数没有直接关系。加载模型时所有专家权重都要放入显存或内存只是前向计算时只有一部分专家被执行。对于 125B 总参不同精度的显存估算如下精度每参数字节125B 参数估测float324 字节约 500GBfloat16 / bfloat162 字节约 250GBint81 字节约 125GBint40.5 字节约 62.5GB这些数值只是权重大小还没有算 KV cache、激活值、中间 buffer、推理引擎开销。所以实际显存需求总是高于表格数值。单卡 24GB 环境想跑 125B 模型即便 int4 量化也很难放下一般需要多卡分片或 CPU offload。3.2 激活参数决定了单 Token 计算量但注意力层仍然全量计算MoE 省的主要是专家 FFN 的计算量。注意力层、共享专家、路由网络和 embedding 仍然对每个 token 计算。可以把一次前向拆成几部分来看模块每个 token 是否参与影响因素注意力层是序列长度、head 数、KV cache共享专家是hidden size 和共享专家数量路由网络是num_experts 的 logits 计算稀疏专家仅 top-knum_experts_per_tok、moe_intermediate_size因此“6B 激活”指的是稀疏专家部分的计算量接近 6B 规模不代表整条链路的延迟等于 6B Dense。实际测试时要分别关注 prefill 和 decode 两个阶段不要只用一个指标下结论。3.3 多卡加载与最小推理示例如果显存足够使用 transformers 的device_mapauto可以快速加载import torch from transformers import AutoModelForCausalLM, AutoTokenizer model_name Qwen/Qwen-125B-MoE # 替换为真实仓库名 tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.bfloat16, device_mapauto, ) prompt 解释一下总参数和激活参数的区别。 inputs tokenizer(prompt, return_tensorspt).to(cuda) with torch.inference_mode(): output model.generate(**inputs, max_new_tokens256) print(tokenizer.decode(output[0], skip_special_tokensTrue))如果显存比较紧张可以显式限制每张卡的最大显存model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.bfloat16, device_mapsequential, max_memory{0: 40GiB, 1: 40GiB, cpu: 100GiB}, )device_mapauto会尽量均匀分配层但 MoE 模型的专家分散在多卡后token 路由到其他卡的专家会引入跨卡通信。device_mapsequential通常按层顺序放逻辑更直观。先以跑通为第一目标再根据性能决定是否换推理引擎。4. 微调、检索和选型架构信息落到业务4.1 LoRA 微调 MoE先想清楚要不要训练路由LoRA 是微调大模型最常用的低成本方案。它只给部分线性层增加低秩旁路不更新完整权重。对 125B 总参的 MoE 模型LoRA 仍然有价值但要注意一个问题默认情况下 LoRA 不会自动训练路由网络。下面是一个常见的 LoRA 配置from peft import LoraConfig, get_peft_model lora_config LoraConfig( r8, lora_alpha16, target_modules[ q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj, ], biasnone, task_typeCAUSAL_LM, ) model get_peft_model(model, lora_config) model.print_trainable_parameters()这里需要分清术语gate_proj是专家 FFN 内部用于升维的门控线性层不是路由网络 gate。路由网络通常叫 router gate负责给专家打分。如果希望微调后路由分布发生变化要把 router gate 显式加入可训练参数或者自定义 forward 实现。同时要关注 router 的负载均衡。MoE 训练时通常有 router auxiliary loss如果微调时把它去掉或权重太大可能出现少数专家被垄断另一些专家长期不被选中。比较安全的做法是观察验证集上的 expert 分布确认不是只剩几个专家在工作。4.2 Qwen Embedding 与向量检索的衔接Qwen 不只提供生成模型也有用于 embedding 的模型。如果业务是 RAG 或向量检索不应该拿 125B/6B 生成模型去做召回而应该使用专门的 embedding 模型。在 Python 中加载 embedding 模型的方式与生成模型不同输出是向量而不是文本from sentence_transformers import SentenceTransformer model SentenceTransformer(Qwen/Qwen-Embedding-...) # 以实际仓库名为准 vectors model.encode([ K
返回列表