犀牛鸟 2026 研究笔记 estelledc.github.io

跨赛道: YOLO 到 端侧部署

检测侧见 YOLO-Master 竞赛指南 ncnn 贡献见 竞赛指南: ncnn 部署流水线见 端侧部署流水线 MNN 对照见 MNN 与 ncnn 对照

调研元信息

日期 2026-06-22
环境 macOS / Apple Silicon
实测状态 未实测 MoE 导出,以源码 + 文档 + Issue 为准
流水线段 全链路纵向打通(Train + Export + Deploy)

一句话定位

本文回答 E 线灵魂问题:YOLO-Master 的 MoE 模型如何跑到手机上?为什么难?有哪些 fallback 路径?ncnn vs MNN 怎么选?

日常类比

想象你要把一个「根据客人复杂度自动调配厨师数量的智能餐厅」搬到一辆外卖三轮车上:

类比边界:真实 MoE 的稀疏激活在 GPU 上 batch 化有特殊优化,三轮车比喻未覆盖这点。


核心问题:MoE 模型为什么难以部署到端侧?

问题根源

YOLO-Master 的 ES-MoE(实例级自适应 MoE)核心特征 [已有]

  1. 动态路由:Router 对每个实例做 Soft/Hard Top-K 选择
  2. 条件计算:推理时只激活被选中的 Expert(稀疏激活)
  3. 实例级差异:不同目标激活不同数量/组合的专家

这三个特征正好撞上端侧推理引擎的三大禁忌:

MoE 特征 端侧引擎假设 冲突点
动态路由 静态计算图 if/else 条件分支无法表达
稀疏激活 确定性内存预分配 运行时才知道哪些 Expert 参与
实例级差异 batch 内 shape 一致 不同实例走不同子图

ONNX 导出的具体障碍 [Issue]

来自 YOLO-Master Issue #42「如何导出动态计算的 ONNX 模型」:

# MoE 推理伪代码
routing_weights = router(x)           # [B, H, W, num_experts]
top_k_indices = torch.topk(routing_weights, k=2)  # 动态选择
for expert_idx in top_k_indices:      # Python for-loop!
    output += experts[expert_idx](x)  # 条件执行

问题:torch.topk 的结果在 ONNX 中是动态的,后续的条件分支无法静态化。


三条部署路径对比

flowchart TD
    A[YOLO-Master MoE 模型] --> B{部署策略?}
    
    B --> C[路径1: 单专家蒸馏]
    C --> C1[pruning.py 剪枝<br/>选最强 Expert]
    C1 --> C2[标准 YOLO 模型<br/>无动态分支]
    C2 --> C3[正常导出链<br/>PNNX/ONNX]
    C3 --> C4[ncnn/MNN 推理]
    
    B --> D[路径2: 标准 YOLOv8 替代]
    D --> D1[不用 MoE<br/>用同规模 YOLOv8]
    D1 --> D2[yolo export format=ncnn]
    D2 --> C4
    
    B --> E[路径3: 全 MoE 导出-实验性]
    E --> E1[固定 Top-K=2<br/>展开所有 Expert]
    E1 --> E2[去除动态分支<br/>全 Expert 前向]
    E2 --> E3[ONNX opset 13+]
    E3 --> E4[onnx2ncnn<br/>可能算子缺失]
    
    style C fill:#90EE90
    style D fill:#87CEEB
    style E fill:#FFB6C1

路径详解

路径 精度保留 部署难度 模型大小 推荐场景
1. 单专家蒸馏 约85-90% 最小(1/N experts) 极端边缘、MCU
2. 标准 YOLOv8 基线水平 极低 标准 放弃 MoE 优势时
3. 全 MoE 导出 100%(理论) 极高 最大(全 Expert) 实验性、研究目的

路径 1 详解:pruning.py 蒸馏 [源码]

YOLO-Master 源码中 ultralytics/nn/modules/moe/pruning.py 提供了 prune_moe_model 函数:

  1. 统计各 Expert 在验证集上的平均激活频率
  2. 保留激活最高的 1-2 个 Expert
  3. 去除 Router + 未选中 Expert
  4. 输出为标准(无 MoE)模型结构

剪枝后的模型无动态分支,可走标准 PNNX/ONNX 导出链。

路径 3 的困难点

即使「展开全部 Expert 并行前向」,仍面临:


引擎选型决策表

同一模型(标准 YOLO 或蒸馏后模型)在三个引擎上的对比:

维度 ncnn MNN ORT Mobile
库体积 约1MB 约5MB 约10MB+
CPU 性能 极优(elempack + NEON) 优(NC4HW4)
GPU 方式 Vulkan Compute OpenCL + Metal 无自有GPU后端
GPU 覆盖 安卓全平台 + macOS 安卓 OpenCL + iOS Metal 通过 NNAPI/CoreML 委托
NPU 支持 部分 NNAPI 代理
动态 shape 有限支持 较好支持 良好
LLM 推理 内建
学习成本 中(C++ 简洁但无 C++11) 高(代码量大) 低(标准 API)
社区支持 最大(23K star) 次之(9K star) 微软维护

选型建议


与 object-detection-deployment 分工

本文(跨赛道纵向) object-detection-deployment(检测横向)
聚焦:YOLO-Master MoE 到手机的完整路径 聚焦:多种检测框架的部署格式对比
深入:MoE 导出障碍 + fallback 广度:TRT/ONNX/CoreML/ncnn/TFLite
引擎对比:ncnn vs MNN vs ORT 框架对比:Ultralytics vs mmdet vs YOLOv10
目标:解答「能不能跑 + 怎么跑」 目标:解答「选哪个格式 + 哪个框架」

犀牛鸟视角:跨赛道贡献机会

机会 所属赛道 难度 影响力
ncnn PNNX 支持 MoE 相关 op mobile-inference 解锁 MoE 直接部署
YOLO-Master pruning.py 完善 object-detection 降低部署门槛
写 MoE 到 ncnn 的端到端教程 跨赛道 社区文档贡献
MNN MoE 推理 benchmark mobile-inference 对照实验数据
INT8 量化对 Router 精度影响研究 跨赛道 学术贡献可能

实施建议时间线

gantt
    title YOLO 到端侧部署实践路线
    dateFormat  YYYY-MM-DD
    section 准备
    环境搭建(ncnn编译+YOLO安装)  :a1, 2026-07-01, 3d
    section 路径验证
    标准YOLOv8 ncnn导出验证       :a2, after a1, 2d
    pruning.py 单专家蒸馏测试      :a3, after a2, 3d
    section 深入
    蒸馏模型ncnn推理benchmark     :a4, after a3, 2d
    MNN对照实验                   :a5, after a4, 3d
    section 产出
    端到端教程文档                 :a6, after a5, 2d

证据等级

标签 来源
[源码] YOLO-Master moe/pruning.py, moe/modules.py; ncnn tools/pnnx/
[已有] deep-dive-yolo-master.md(MoE 四代演进 + 局限性); challenges.md 目标检测 #8
[文档] YOLO-Master wiki/MoE_Modules_Explanation.md(ONNX opset>=13)
[Issue] YOLO-Master #42(ONNX 动态导出), #33(RK3588 部署), #12(ORT 部署)