上一回咱们聊了 backbone 的演变史,从 FCN 到 Transformer,听起来挺波澜壮阔的。但今天我得泼盆冷水——你以为世界上所有的显卡都是 V100 和 A100 吗?太天真了。你要是去自动驾驶公司的感知组看看,或者去那些做智慧工厂、智慧农业的现场瞅一眼,跑模型的设备可能就是个算力不到 10 TOPS 的嵌入式开发板,温度一高还得降频。
这时候你再跟他们提什么 Swin Transformer 大模型,什么多级联的复杂解码器,人家看你的眼神就像看一个刚从象牙塔里出来的书呆子。在工业界,实时性就是生命线。自动驾驶的车跑在高速上,你分割一个 frame 花了 300 毫秒,等你出结果车都撞护栏上了。所以,咱们今天得正经聊聊怎么让分割模型“瘦成一道闪电”,还得跑得快。
轻量化的路子,粗分有三条。
第一条,轻量级 backbone。MobileNet 系列、ShuffleNet 系列是绕不开的。MobileNetV2 那个倒残差结构,当年刚出来的时候我还挺不屑,觉得 depthwise convolution 这玩意儿省参数是省参数,但梯度回传容易出问题。后来真香了,配合 DeepLabV3+ 在 Cityscapes 上居然能跑到 70 多的 mIoU,帧率还能稳住 30 FPS 以上。ShuffleNet 更狠,直接用 channel shuffle 来弥补分组卷积的信息流通不畅,这操作有点像在高速公路上强行开几个口子让车流换道,脑回路清奇但确实管用。
第二条,模型剪枝与量化。这活儿就有点“玄学”成分了。剪枝分结构化剪枝和非结构化剪枝。非结构化的就是那些稀疏矩阵,看着压缩比高,实际推理引擎不支持,加速效果等于零,纯属自欺欺人。结构化的比如通道剪枝,直接把整个卷积核干掉,这才能真实降低 FLOPs。但问题来了——剪哪儿?按 L1 范数剪最小的通道?这方法糙得很,有时候最小的通道反而是捕捉纹理细节的关键。所以现在学术界折腾什么可微分剪枝、彩票假说,玩得挺花,但工程落地我劝你还是老老实实用 Intel OpenVINO 或者 NVIDIA TensorRT 的自动优化管线,人家帮你做图优化和算子融合,比你手动剪枝稳多了。量化就更别提了,INT8 量化一旦校准集没选好,精度掉得让你怀疑人生,尤其是分割这种对边界敏感的任务,掉个两三个点 mIoU 在视觉上就是锯齿状边缘,惨不忍睹。
第三条,轻量化解码器与注意力设计。既然 backbone 轻了,解码器要是还用 ASPP 那种带五个并行空洞卷积的重模块,那 bottleneck 依然卡死。于是大家搞出了 BiseNet 的双分支结构——空间分支保留高分辨率浅层特征、上下文分支用快速下采样抓全局,两者融合,又快又准。还有 LEDNet、DFANet 这些,基本都是在“分辨率”和“通道数”这两个维度上做文章,用分组卷积、通道注意力来替代笨重的全局自注意力。轻量化不是简单地把层数减少,而是让每一层的工作更高效、更专注。
说到这儿我得吐槽一下某些顶会论文,demo 视频里跑得飞快,一看参数量只有几 MB,仔细一瞧,人家是在 1080P 的图上 resize 到 512x256 跑的。这不是耍流氓吗?工业场景里谁允许你把高清图缩成马赛克再分割?小目标直接就没了。真要测实时性,得在目标设备上、原始分辨率下、满负载跑,看那 latency 的 p99 分位数,而不是看均值——均值都是骗人的,偶尔卡一下才要命。
最后讲个真实的案例。去年帮一个做农业喷洒无人机的朋友优化模型,他们要在 Jetson Xavier NX 上跑作物病害分割,原版 DeepLabV3+ 死活跑不到 15 FPS。后来怎么搞?直接把空洞卷积的 dilation rate 调小、把 ASPP 里的五个分支砍成三个、把 backbone 从 ResNet-101 换成 MobileNetV3,精度从 78.2 掉到 74.6,但帧率从 11 飙到了 32。用户反馈反而更好了,因为实时性上来了,无人机飞得快也不卡顿。这就是工程里的金科玉律:精度不是一切,体验才是。