深度学习之MobileNet

MobileNet 是一种专为移动和嵌入式设备设计的轻量级卷积神经网络架构,其核心优势在于通过创新的结构设计大幅减少参数量和计算量,同时保持较好的模型性能。接下来我们来探讨一下它的原理和优势。

一、MobileNet的核心原理

1. 深度可分离卷积 (Depthwise Separable Convolution)
  • 传统卷积:同时处理空间(宽高)和通道维度,计算量为:
    H × W × C_in × C_out × K × K
    其中 K 为卷积核大小。

  • 深度可分离卷积:分解为两步:

    • 深度卷积 (Depthwise Conv):每个输入通道单独卷积,不跨通道计算。
      计算量:H × W × C_in × K × K
    • 逐点卷积 (Pointwise Conv):1×1卷积融合通道信息。
      计算量:H × W × C_in × C_out
  • 计算量对比
    对于输入特征图尺寸为 H×W×C_in,输出通道 C_out,卷积核 K×K

标准卷积FLOPs = H × W × C_in × C_out × K × K × 2(乘加各算1次操作,所以×2)。

深度可分离卷积计算量分解:分为深度卷积 + 逐点卷积两部分:

(1) 深度卷积(Depthwise Conv)
深度卷积FLOPs = H × W × C_in × K × K × 2 (每个输入通道独立计算)
(2) 逐点卷积(Pointwise Conv)
逐点卷积FLOPs = H × W × C_in × C_out × 1 × 1 × 2 (1×1卷积混合通道)
总计算量:
总FLOPs = H×W×2 × (C_in×K² + C_in×C_out)
  传统卷积计算量是深度可分离卷积的 `1/C_out + 1/K²` 倍(例如当 `C_out=256`、`K=3` 时,计算量减少约8-9倍)。

C_out=256K=3 时:

1/C_out = 1/256 ≈ 0.0039
1/K² = 1/9 ≈ 0.1111
比例 = 1 / (0.0039 + 0.1111) ≈ 8.7

即标准卷积计算量是深度可分离卷积的约8.7倍。这个数量是很客观的,因此,MobileNet 是一种专为移动和嵌入式设备设计的轻量级卷积神经网络架构。
对于MobileNet 可以这样去理解:想象你要处理一堆彩色积木(图像数据),传统方法需要同时考虑:

  1. 积木的颜色(通道维度)
  2. 积木的摆放位置(宽高维度)
    MobileNet说:“太麻烦了!我们分开处理吧!”

传统卷积

  • 操作:一次性检查所有颜色的积木+位置
  • 计算量公式:
    图片高度 × 图片宽度 × 输入通道 × 输出通道 × 卷积核大小 × 卷积核大小
    MobileNet的聪明办法
    第一步:深度卷积(只看位置)
  • 操作:把不同颜色的积木分开,单独检查每种颜色的摆放位置
  • 计算量:
    高度 × 宽度 × 输入通道 × 卷积核大小 × 卷积核大小

第二步:逐点卷积(只看颜色)

  • 操作:用1×1的小漏斗混合颜色
  • 计算量:
    高度 × 宽度 × 输入通道 × 输出通道
    按照这样算下来,就可以节省了87%的计算量!
2. 宽度乘子 (Width Multiplier)
  • 通过系数 α(默认0.25-1)等比例减少所有层的通道数,参数量近似减少 α² 倍。
3. 分辨率乘子 (Resolution Multiplier)
  • 通过系数 ρ 降低输入分辨率,计算量减少 ρ² 倍。

二、MobileNet的结构设计

1. 基础结构单元
# MobileNetV1 基础块
class DepthwiseSeparableConv(nn.Module):
    def __init__(self, in_ch, out_ch, stride):
        super().__init__()
        self.depthwise = nn.Conv2d(in_ch, in_ch, 3, stride, 1, groups=in_ch, bias=False)
        self.bn1 = nn.BatchNorm2d(in_ch)
        self.pointwise = nn.Conv2d(in_ch, out_ch, 1, 1, 0, bias=False) 
        self.bn2 = nn.BatchNorm2d(out_ch)
        self.relu = nn.ReLU(inplace=True)
        
    def forward(self, x):
        x = self.relu(self.bn1(self.depthwise(x)))
        x = self.relu(self.bn2(self.pointwise(x)))
        return x
2. 整体架构
  • MobileNetV1:由1个标准卷积 + 13个深度可分离卷积块堆叠而成。
import torch
import torch.nn as nn

class DepthwiseSeparableConv(nn.Module):
    def __init__(self, in_channels, out_channels, stride):
        super().__init__()
        self.depthwise = nn.Conv2d(
            in_channels, in_channels, kernel_size=3,
            stride=stride, padding=1, groups=in_channels, bias=False
        )
        self.pointwise = nn.Conv2d(
            in_channels, out_channels, 
            kernel_size=1, stride=1, bias=False
        )
        self.bn1 = nn.BatchNorm2d(in_channels)
        self.bn2 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.depthwise(x)
        x = self.bn1(x)
        x = self.relu(x)
        
        x = self.pointwise(x)
        x = self.bn2(x)
        x = self.relu(x)
        return x

class MobileNetV1(nn.Module):
    def __init__(self, num_classes=1000):
        super().__init__()
        
        # 标准卷积层 (第一层)
        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True)
        )
        
        # 深度可分离卷积层
        self.ds_conv = nn.Sequential(
            DepthwiseSeparableConv(32, 64, stride=1),
            DepthwiseSeparableConv(64, 128, stride=2),
            DepthwiseSeparableConv(128, 128, stride=1),
            DepthwiseSeparableConv(128, 256, stride=2),
            DepthwiseSeparableConv(256, 256, stride=1),
            DepthwiseSeparableConv(256, 512, stride=2),
            *[DepthwiseSeparableConv(512, 512, stride=1) for _ in range(5)],
            DepthwiseSeparableConv(512, 1024, stride=2),
            DepthwiseSeparableConv(1024, 1024, stride=1)
        )
        
        # 分类层
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(1024, num_classes)

    def forward(self, x):
        x = self.conv1(x)
        x = self.ds_conv(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.fc(x)
        return x

关键结构说明:

  1. 标准卷积层 (仅第一层):

    • 3x3卷积,步长2,输出通道32
    • 后接BN和ReLU
  2. 深度可分离卷积堆叠 :

    • 共13个深度可分离卷积层
    • 特征图尺寸逐步下降(224→112→56→28→14→7)
    • 通道数逐步增加(32→64→128→256→512→1024)
  3. 分类头 :

    • 全局平均池化
    • 全连接层输出分类结果
  4. 参数特点 :

    • 总参数量约4.2M
    • 计算量约569M FLOPs (输入224x224)
    • 相比标准卷积网络(VGG16)计算量减少约8-9倍

这个实现严格遵循了原论文《MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications》的网络结构设计。当然,现在的MobileNets也已经发展了多个版本出来,但是怎么变化,深度可分离卷积还是这里面的核心。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值