一、通俗易懂介绍
Efficient-v1
Efficient-v2
1.1 核心思想:复合缩放(Compound Scaling)
EfficientNet由Google在2019年提出,通过协同缩放网络的深度(层数)、宽度(通道数)、分辨率(输入尺寸),实现“更低计算成本,更高准确率”。
- 传统做法:单独增加深度、宽度或分辨率,但收益递减。
- EfficientNet的智慧:找到三者的最优组合,类似调整水管的粗细(宽度)、长度(深度)、水压(分辨率),让流量(性能)最大化。
1.2 举个栗子 🌰
假设要设计一个图像分类模型:
- ResNet:可能堆叠更多层(仅增加深度)。
- EfficientNet:同时增加层数(深度)、每层的通道数(宽度),并放大输入图像尺寸(分辨率),按比例缩放,实现更高准确率且计算量更少。
二、应用场景与优缺点
2.1 应用场景
领域 | 任务 | 推荐模型变体 |
---|---|---|
移动端部署 | 手机APP图像分类 | EfficientNet-B0/B1 |
服务器推理 | 高精度医学影像分析 | EfficientNet-B4/B5 |
实时检测 | 视频流中的物体识别 | EfficientNetV2-S/M |
迁移学习 | 小样本分类(冻结主干网络) | 所有版本(适合特征提取) |
2.2 优缺点对比
优点 | 缺点 |
---|---|
✅ 计算量减少80%的情况下,性能优于ResNet | ❌ 需要较多显存训练大尺寸模型(如B7) |
✅ 复合缩放策略公开可复现 | ❌ 极小的变体(如B0)在复杂任务上可能欠拟合 |
✅ EfficientNetV2显著加快训练速度 | ❌ 自定义修改缩放系数需要调参经验 |
三、模型结构详解
3.1 EfficientNet-V1 核心模块:MBConv
MBConv(Mobile Inverted Bottleneck Block)结构:
输入 → 1x1升维 → Depthwise 3x3卷积 → SE注意力 → 1x1降维 → DropPath → 输出
- 步骤分解:
- 扩展层:1x1卷积将输入通道扩展(通常4倍)。
- 深度可分离卷积:3x3逐通道卷积提取空间特征。
- SE模块:全连接层学习通道权重,增强重要特征。
- 压缩层:1x1卷积减少通道数,匹配残差连接维度。
- DropPath:随机跳过当前块,防止过拟合。
关键配置参数(以B0为例):
- 初始输入分辨率:224x224
- 总层数:237层(包含重复模块)
- 宽度系数:ϕ=1.0
- 深度系数:d=1.0
- 分辨率系数:r=1.0
3.2 EfficientNet-V2 改进
- 模块混合:结合MBConv和Fused-MBConv(替换部分MBConv的深度可分离卷积为标准3x3卷积)。
- 渐进式训练:逐步增大输入分辨率(从128到380),避免直接大分辨率训练的不稳定。
- 简化缩放规则:V2的复合系数更偏向增加宽度而非深度。
四、数学原理
4.1 复合缩放公式
定义网络总计算量为:
在固定资源约束下(如2倍计算量),优化目标是最大化模型准确率,缩放系数满足:
其中:
五、代表性变体及改进
5.1 EfficientNet-V1系列(B0-B7)
模型 | 分辨率 | Top-1 Acc | 参数量 | FLOPs |
---|---|---|---|---|
B0 | 224x224 | 77.3% | 5.3M | 0.39B |
B4 | 380x380 | 82.9% | 19M | 4.2B |
B7 | 600x600 | 84.3% | 66M | 37B |
5.2 EfficientNet-V2系列
模型 | 分辨率 | Top-1 Acc | 训练速度vsV1 |
---|---|---|---|
V2-S | 384x384 | 83.9% | 3.1x更快 |
V2-M | 480x480 | 85.2% | 2.5x更快 |
V2-L | 480x480 | 85.7% | 2.0x更快 |
改进点:
- NAS(神经架构搜索)优化:搜索更适合GPU/TPU的模块组合。
- 自适应正则化:根据输入分辨率动态调整Dropout率。
六、PyTorch代码示例
6.1 使用HuggingFace预训练模型
from transformers import EfficientNetImageProcessor, EfficientNetForImageClassification
from PIL import Image
import requests
# 加载预训练模型(EfficientNet-B0)
processor = EfficientNetImageProcessor.from_pretrained("google/efficientnet-b0")
model = EfficientNetForImageClassification.from_pretrained("google/efficientnet-b0")
# 预处理输入
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)
inputs = processor(image, return_tensors="pt")
# 推理
outputs = model(**inputs)
logits = outputs.logits
predicted_class_idx = logits.argmax(-1).item()
print("预测类别:", model.config.id2label[predicted_class_idx])
6.2 自定义MBConv模块
import torch
from torch import nn
class MBConv(nn.Module):
def __init__(self, in_channels, out_channels, expansion_ratio=4, stride=1):
super().__init__()
hidden_dim = int(in_channels * expansion_ratio)
self.use_residual = (in_channels == out_channels) and (stride == 1)
# MBConv块
self.layers = nn.Sequential(
nn.Conv2d(in_channels, hidden_dim, 1, bias=False) if expansion_ratio !=1 else nn.Identity(),
nn.BatchNorm2d(hidden_dim),
nn.SiLU(inplace=True),
nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False), # Depthwise卷积
nn.BatchNorm2d(hidden_dim),
nn.SiLU(inplace=True),
SqueezeExcite(hidden_dim), # SE模块
nn.Conv2d(hidden_dim, out_channels, 1, bias=False),
nn.BatchNorm2d(out_channels)
)
def forward(self, x):
if self.use_residual:
return x + self.layers(x) # 残差连接
else:
return self.layers(x)
class SqueezeExcite(nn.Module):
def __init__(self, channels, se_ratio=0.25):
super().__init__()
reduced_channels = max(1, int(channels * se_ratio))
self.se = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Conv2d(channels, reduced_channels, 1),
nn.SiLU(),
nn.Conv2d(reduced_channels, channels, 1),
nn.Sigmoid()
)
def forward(self, x):
return x * self.se(x) # 通道注意力加权
# 测试MBConv
x = torch.randn(1, 32, 224, 224)
mbconv = MBConv(32, 64, stride=2)
print(mbconv(x).shape) # 输出:torch.Size([1, 64, 112, 112])
七、EfficientNet V1与V2的核心区别
1. 模型架构优化
模块类型 | EfficientNet V1 | EfficientNet V2 |
---|---|---|
基础模块 | 全量使用MBConv(含SE模块的深度可分离卷积) | 混合模块:浅层用Fused-MBConv(标准3x3卷积),深层用改进MBConv |
激活函数 | Swish(即SiLU) | 沿用Swish,但对部分层简化计算(如移除冗余激活) |
最大层数 | B7达813层(重复堆叠MBConv) | 减少重复块,V2-L仅约550层,降低内存消耗 |
Fused-MBConv结构:
- 前N层:用标准3x3卷积替代深度可分离卷积,加速GPU计算。
- 后M层:保留深度可分离卷积 + SE模块,维持轻量化。
# Fused-MBConv示例(V2的浅层结构)
Fused-MBConv = nn.Sequential(
nn.Conv2d(in_ch, expanded_ch, kernel_size=3, stride=2, padding=1), # 标准卷积
nn.BatchNorm2d(expanded_ch),
nn.SiLU(),
SqueezeExcite(expanded_ch), # 可选
nn.Conv2d(expanded_ch, out_ch, kernel_size=1), # 1x1降维
)
2. 训练策略升级
策略 | V1 | V2 |
---|---|---|
输入分辨率 | 固定分辨率(如B0用224x224) | 渐进式训练:从小分辨率(128x128)开始,逐步增大至目标尺寸(如380x380) |
正则化 | 固定Dropout率 | 自适应正则化:根据输入分辨率动态调整Dropout和权重衰减强度 |
数据增强 | 基础增强(随机裁剪、翻转) | 引入更强的增强(如RandAugment、Mixup) |
数学表达:
- 渐进式分辨率:设总训练步数为T,第t步的分辨率r(t)按线性增长:
- 自适应Dropout:分辨率r越大,Dropout率p(r)越高:
3. 缩放策略调整
V1与V2缩放对比:
- V1目标:最大化精度,允许深度、宽度、分辨率自由增长。
- V2目标:平衡训练速度与精度,优先增加宽度,限制深度和分辨率。
4. 硬件效率优化
优化方向 | V1 | V2 |
---|---|---|
GPU/TPU适配 | 未针对硬件优化,深度可分离卷积在GPU上低效 | 通过NAS搜索更适合GPU的模块组合(如Fused-MBConv) |
训练速度 | B0训练耗时≈100 epoch | V2-S训练速度快3倍(相同硬件下) |
显存占用 | B7需32GB+显存 | V2-L仅需16GB显存(相同分辨率) |
5. 性能对比(ImageNet Top-1)
模型 | 参数量 | 分辨率 | 精度 | 训练速度(GPU小时) |
---|---|---|---|---|
EfficientNet-B7 | 66M | 600x600 | 84.3% | 1500 |
EfficientNetV2-L | 120M | 480x480 | 85.7% | 800 |
关键结论:
- V2在更少计算量下达到更高精度(V2-L比B7精度+1.4%,训练时间减半)。
- V2更适合实际部署:显存占用低,训练/推理速度更快。
八、总结
EfficientNet系列通过复合缩放统一深度、宽度与分辨率,平衡模型性能与效率,成为CV领域的标杆架构。2021年的V2版本进一步优化训练速度和硬件适配性,使其在工业界的落地应用更为广泛。未来可能的演进方向包括:
- 动态缩放策略:根据输入内容自适应调整网络结构。
- 跨模态扩展:适用于视频、3D点云等多模态数据。
- 二值化/量化压缩:结合模型压缩技术部署到边缘设备。