1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| """ MoE模型在Snapdragon NPU上的部署优势
原理: 不是所有参数同时激活,而是路由到最相关的"专家" 效果: 30B参数模型,实际计算量可能只有8-10B """
import torch import torch.nn as nn import torch.nn.functional as F
class MoEExpert(nn.Module): """单个专家网络""" def __init__(self, d_model: int = 768, d_ff: int = 3072): super().__init__() self.fc1 = nn.Linear(d_model, d_ff) self.fc2 = nn.Linear(d_ff, d_model) def forward(self, x): return self.fc2(F.gelu(self.fc1(x)))
class MoELayer(nn.Module): """ Mix of Experts 层 路由每个token到最合适的专家 对NPU的意义: - Element Accelerator加速路由计算 - 共享内存减少专家切换开销 - 30B参数模型实际计算量~10B """ def __init__(self, d_model: int = 768, num_experts: int = 8, top_k: int = 2): super().__init__() self.num_experts = num_experts self.top_k = top_k self.experts = nn.ModuleList([ MoEExpert(d_model) for _ in range(num_experts) ]) self.gate = nn.Linear(d_model, num_experts, bias=False) def forward(self, x): """ Args: x: (B, L, d_model) Returns: output: (B, L, d_model) """ B, L, D = x.shape gate_logits = self.gate(x) gate_probs = F.softmax(gate_logits, dim=-1) topk_vals, topk_idx = gate_probs.topk(self.top_k, dim=-1) topk_vals = topk_vals / topk_vals.sum(dim=-1, keepdim=True) output = torch.zeros_like(x) for k in range(self.top_k): for b in range(B): for l in range(L): expert_idx = topk_idx[b, l, k].item() weight = topk_vals[b, l, k] output[b, l] += weight * self.experts[expert_idx](x[b, l]) return output
class MoE_DMS_Model(nn.Module): """ DMS专用MoE模型 场景: 不同驾驶场景使用不同专家 - 专家1: 日间正常驾驶 - 专家2: 夜间驾驶 - 专家3: 隧道场景 - 专家4: 高速公路 - 专家5: 城市道路 - 专家6: 停车状态 - 专家7: 恶劣天气 - 专家8: 疲劳状态 效果: 总参数8x,实际计算1x """ def __init__(self): super().__init__() self.backbone = nn.Sequential( nn.Conv2d(3, 64, 3, 2, 1), nn.BatchNorm2d(64), nn.ReLU(), nn.Conv2d(64, 128, 3, 2, 1), nn.BatchNorm2d(128), nn.ReLU(), nn.AdaptiveAvgPool2d(1), ) self.moe = MoELayer(d_model=128, num_experts=8, top_k=2) self.head = nn.Linear(128, 10) def forward(self, x): feat = self.backbone(x).flatten(1).unsqueeze(1) out = self.moe(feat).squeeze(1) return self.head(out)
if __name__ == "__main__": model = MoE_DMS_Model() x = torch.randn(4, 3, 224, 224) out = model(x) total_params = sum(p.numel() for p in model.parameters()) active_params = sum( p.numel() for name, p in model.named_parameters() if 'experts.0' in name or 'experts.1' in name or 'backbone' in name or 'head' in name or 'gate' in name ) print(f"输出: {out.shape}") print(f"总参数: {total_params:,}") print(f"激活参数(Top-2): ~{active_params:,}") print(f"稀疏比: {1 - active_params/total_params:.1%}") print("\n✅ MoE模型测试通过")
|