本节摘要:把 CNN 装进手机,约束立刻换了一套:几瓦的功耗预算、几百 MB 的内存、毫秒级的响应。轻量级机型的核心刀法是深度可分离卷积——把"跨通道混合"与"空间过滤"拆成两道便宜工序,标准 3×3 卷积的算力立省约八成。本节算清这笔账,顺带巡检 ShuffleNet 的分组卷积与通道洗牌,并给出一把"什么时候别用轻模型"的尺子。
在服务器上训练模型的人很少想过这些数字:手机端推理若想实时,单帧预算通常在几十毫秒内;整机功耗墙是几瓦,留给视觉的份额有限;内存以 GB 计却要和系统、应用共享。VGG 一张图上百亿次乘加,到了端侧就是发烫卡顿;ResNet 够快了,也未必塞得进几百 KB 的模型份额。轻量化于是不是"把网络改小"这么粗糙,而是重新设计卷积本身的成本结构。
阅读完本节,你应当能够:
标准卷积每次滑动都在同时做两件事:在空间上找模式(3×3 邻域的加权),在通道上做组合(64 个通道的加权和)。MobileNet 的洞察是这两件事可以拆开做:先用 64 个互相独立的 3×3 核在各自通道内做空间过滤(深度卷积,每通道一个核),再用 1×1 卷积跨通道混合(逐点卷积)。账目立见分晓:
C, k, S = 64, 3, 56 # 通道数、核尺寸、特征图边长 macs_std = S * S * C * C * k * k # 标准卷积 macs_dw = S * S * C * k * k # 深度卷积:每通道独立 macs_pw = S * S * C * C # 逐点卷积:只混通道 print("标准卷积乘加:", f"{macs_std:,}") # 115,605,504 print("可分离乘加:", f"{macs_dw + macs_pw:,}") # 14,651,392 print("省算比:", round(macs_std / (macs_dw + macs_pw), 1)) # 7.9
56×56 的 64 通道特征图上,标准 3×3 要 1.156 亿次乘加,拆开做只要 1,465 万次,比值约 7.9——理论上限约等于核尺寸的平方(九分之一),通道数越大越接近。代价是精度略降,通常在一到两个百分点内;换算成手机上的续航与发热,这笔交易几乎无脑划算。
import torch import torch.nn as nn dw = nn.Conv2d(64, 64, kernel_size=3, padding=1, groups=64, bias=False) # groups=通道数 pw = nn.Conv2d(64, 128, kernel_size=1, bias=False) x = torch.randn(1, 64, 56, 56) print(tuple(pw(dw(x)).shape)) # (1, 128, 56, 56) print("深度卷积参数:", dw.weight.numel()) # 576 = 64 通道 × 3×3 print("逐点卷积参数:", pw.weight.numel()) # 8192 = 64×128
groups 参数就是深度卷积的开关:分组数等于通道数时,每个通道独享一个核。注意参数总量依然小得可怜——两段合计 8,768 个参数,只是标准卷积 36,864 的零头。
深度卷积有个天然副作用:通道之间互不来往,全靠逐点卷积传话,通道间信息交换不够充分。ShuffleNet 把逐点卷积改成更便宜的分组卷积(比如每组只管四分之一的通道),再用"通道洗牌"补课——把各组的通道交错重排,让下一层每组都能看到上一层的全部组。整套组合把分组带来的信息孤岛拆掉,精度几乎不掉。
轻量化还有两个"排量旋钮":宽度乘数把每层通道整体乘个系数(0.75、0.5、0.25,参数按平方缩),分辨率乘数把输入图缩小(算力按平方缩)。MobileNet v2 又补了两手——倒残差结构(先扩宽再压缩,与 ResNet 相反)与线性瓶颈(瓶颈层不加激活防信息损失),精度再抬一截。选型的尺子可以这样用:端侧实时、批量巨大、任务简单(质检、门禁、美颜)——闭眼上深度可分离;云端离线、任务精细(医学影像、小目标密集检测)——别省,标准卷积与 ResNet 级主干仍是对的选择。 精度敏感的任务里,轻量化省下的算力经常不够弥补误判的代价。
问:深度可分离卷积的精度损失,主要丢在哪里?答:丢在空间与通道的联合建模上——标准卷积的 3×3 核同时看"哪个位置、哪些通道一起响应",拆开后两件事各管各的,交互只剩逐点卷积一关;特征越依赖通道间精细联动,损失越明显。问:为什么轻量网络的训练往往更依赖增强与正则?答:容量小、层数薄,抗噪声能力弱,进料干净与否对它的影响被放大——轻模型的调参重心天然在数据侧而非结构侧。
宽度乘数的效果按平方兑现,值得单独记一笔:取 α=0.5,本节那个 64 通道的可分离卷积组变成 32 通道——深度卷积 32×9=288、逐点卷积 32×32=1024,乘加从 1,465 万掉到约 366 万,恰好是原来的四分之一(α²)。分辨率乘数同理:输入边长减半,像素数变四分之一,乘加再砍四倍。两个旋钮叠加可以近似按"预算公式"反推模型规模,这正是端侧团队做排量规划的基本手艺。
groups 等于通道数即深度卷积,逐点卷积就是 1×1,两段参数量分别 576 与 8,192(64 通道例);⚠️ 常见坑:把深度卷积当万能省料器,直接往任意网络里替换 3×3。浅层特征通道少、空间模式复杂,拆开的收益小、损失大——轻量网络的浅层反而常用普通卷积,刀法要分部位。
六份机型档案翻完,工位没变过,变的是省料、加深、提速的手法。第四章转入质检与回炉:这些流水线是怎么被训练到位的。