GoogLeNet网络详解
论文地址:1409.4842.pdf (arxiv.org)
亮点:
-
引入Inception结构(融合不同多尺度的特征信息)
-
使用1*1卷积进行降维处理
-
添加两个辅助分类器帮助训练
-
丢弃全连接层,使用平均池化层
Inception结构:
还有一个优势就是: 利用稀疏矩阵分解成密集矩阵计算的原理来加快收敛速度
code:
class BasicConv2d(nn.Module):
def __init__(self, in_channels, out_channels, **kwargs):
super(BasicConv2d, self).__init__()
self.conv = nn.Conv2d(in_channels, out_channels, **kwargs)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
x = self.conv(x)
x = self.relu(x)
return x
class Inception(nn.Module):
def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj):
super(Inception, self).__init__()
self.branch1 = BasicConv2d(in_channels, ch1x1, kernel_size=1)
self.branch2 = nn.Sequential(
BasicConv2d(in_channels, ch3x3red, kernel_size=1),
BasicConv2d(ch3x3red, ch3x3, kernel_size=3, padding=1) # 保证输出大小等于输入大小
)
self.branch3 = nn.Sequential(
BasicConv2d(in_channels, ch5x5red, kernel_size=1),
# 在官方的实现中,其实是3x3的kernel并不是5x5,这里我也懒得改了,具体可以参考下面的issue
# Please see https://github.com/pytorch/vision/issues/906 for details.
BasicConv2d(ch5x5red, ch5x5, kernel_size=5, padding=2) # 保证输出大小等于输入大小
)
self.branch4 = nn.Sequential(
nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
BasicConv2d(in_channels, pool_proj, kernel_size=1)
)
def forward(self, x):
branch1 = self.branch1(x)
branch2 = self.branch2(x)
branch3 = self.branch3(x)
branch4 = self.branch4(x)
outputs = [branch1, branch2, branch3, branch4]
return torch.cat(outputs, 1)
MobileNetV1 V2 V3网络详解
V1中提出DWConv
D
k
∗
D
k
∗
M
∗
D
F
∗
D
F
+
M
∗
N
∗
D
F
∗
D
F
D_{k} *D_{k} * M * D_{F} * D_{F} + M * N * D_{F} * D_{F}
Dk∗Dk∗M∗DF∗DF+M∗N∗DF∗DF
D k ∗ D k ∗ M ∗ N ∗ D F ∗ D F D_{k} * D_{k} * M * N * D_{F} * D_{F} Dk∗Dk∗M∗N∗DF∗DF
V2中提出Inverted Residuals(倒残差结构)
实验发现在MobileNetv1中,深度卷积核的参数较多为0,也就是其卷积核没有发挥提取特征作用。那么作者先通过1*1卷积将维度上升,再使用深度卷积,深度卷积的输入输出通道数更高,就能够提取更多的信息。
v3亮点:
更新Block(加入SE, 使用ReLU6激活函数), NAS搜索
ShuffleNetV1网络详解
论文地址:arxiv.org/pdf/1707.01083.pdf
ShuffleNet的核心设计理念是对不同的channels进行shuffle来解决group convolution带来的弊端。Group convolution是将输入层的不同特征图进行分组,然后采用不同的卷积核再对各个组进行卷积,这样会降低卷积的计算量。GConv虽然能减少参数量与计算量,但GConv不同组之间之间没有信息交流, 引入channnle shuffle
实际上比如ResNeXt模型中1x1卷积基本上占据了93.4%的乘加运算,那么不如也对1x1卷积采用channel sparse connection,那样计算量就可以降下来了
计算量对比:
ShuffleNetV2网络详解
论文地址:arxiv.org/pdf/1807.11164.pdf
四条设计高效网络的准则:
G1 同等通道大小最小化内存访问量
G2 过量使用组卷积会增加MAC
G3 网络碎片化会降低并行度
G4 不能忽略元素级操作
在ShuffleNetv1的模块中,大量使用了1x1组卷积,这违背了G2原则,另外v1采用了类似ResNet中的瓶颈层(bottleneck layer),输入和输出通道数不同,这违背了G1原则。同时使用过多的组,也违背了G3原则。短路连接中存在大量的元素级Add运算,这违背了G4原则。
def channel_shuffle(x: Tensor, groups: int) -> Tensor:
batch_size, num_channels, height, width = x.size()
channels_per_group = num_channels // groups
# reshape
# [batch_size, num_channels, height, width] -> [batch_size, groups, channels_per_group, height, width]
x = x.view(batch_size, groups, channels_per_group, height, width)
x = torch.transpose(x, 1, 2).contiguous() # 通过转置操作实现 shuffle
# flatten
x = x.view(batch_size, -1, height, width)
return x
EfficientNet网络详解
论文地址:https://arxiv.org/abs/1905.11946
作者希望找到一个可以同时兼顾速度与精度的模型放缩方法,为此,作者重新审视了前人提出的模型放缩的几个维度:网络深度、网络宽度、图像分辨率,作者认为这三个维度之间是互相影响的并探索出了三者之间最好的组合,在此基础上提出了最新的网络 EfficientNet
EfficientNet中使用了MBConv单元
EfficientNetV2网络详解
论文地址:https://arxiv.org/abs/2104.00298
V1中存在的问题是:
(1) 训练图像的尺寸很大,训练速度非常慢
(2) 浅层使用DWConv速度会很慢
(3)同等放大每个stage是次优的。
V2中关注模型的训练速度
虽然Depthwise convolutions
结构相比普通卷积拥有更少的参数以及更小的FLOPs,但通常无法充分利用现有的一些加速器(虽然理论上计算量很小,但实际使用起来并没有想象中那么快) 可以在浅层网络中MBConv替换为Fused-MBConv,但不是全部替换。
这篇文章做出的三个贡献:
引入新的网络(EfficientNetV2),该网络在训练速度以及参数数量上都优于先前的一些网络。
提出了改进的渐进学习方法,该方法会根据训练图像的尺寸动态调节正则方法(例如dropout、data augmentation和mixup)。通过实验展示了该方法不仅能够提升训练速度,同时还能提升准确率。
通过实验与先前的一些网络相比,训练速度提升11倍,参数数量减少为1/6.8
Progressive Learning渐进学习策略
在前面提到的搜索空间中采样并训练模型,训练过程中尝试使用不同的图像尺寸以及不同强度的数据增强data augmentations
。当训练的图片尺寸较小时,使用较弱的数据增强augmentation
能够达到更好的结果;当训练的图像尺寸较大时,使用更强的数据增强能够达到更好的接