GoogleNet
GoogleNet在2014年中的ImageNet夺冠,将Inception这一结构推向了热潮。从另外一个角度来看,CV魔改网络结构也从中得到启发或者说推动,拓宽了各种魔改的方式。GoogleNet其实只是Inception这一结构大规模集成后得到的模型,Inception的发展却远不至于此。本文会详细介绍这一发展历史,从Inception v1(GooglNet) [1]到BN-Inception [2],Inception v2 [3],Inception v3 [3]直至Inception v4 [4]以及衍生出来的Xception [5].
Inception v1
上图左边是Inception v1,有图是利用1×1降维减小参数量后的Inception网络,即为GoogleNet。在Inception v1网络中,使用了不同卷积核大小的卷积进行处理,直观理解上来看,不同卷积核大小的卷积可以从不同尺寸学习图像特征,从更多方面、角度进行学习。
下图很详细地展示了GoogleNet的网络结构。具体来说,Inception相当于一种特殊的模块结构,而GoogleNet是由多种不同的Inception模块组成的,且每个Inception用1x1的卷积进行降维(具体来说是通过减小通道维度)。
此外,为了解决深层次网络在模型中间出现的梯度消失问题,额外使用了两个辅助损失函数进行训练,如下图中所示。如果上图不够直观,在原论文中也提供了一个清晰完整的模型结构图(比较长):
BN-Inception
顾名思义,这一结构是在Inception结构中引入Batch Normalization (BN)这一操作。Batch Normalization其实思想很简单,就是对每个batch进行归一化操作,具体来说,我们分别计算这一个batch中所有数据的均值和方差:
μ
=
1
N
∑
i
=
1
N
x
i
,
σ
2
=
1
N
∑
i
=
1
N
(
x
i
−
μ
)
2
\mu=\frac{1}{N}\sum_{i=1}^{N}x_i,\sigma^2=\frac{1}{N}\sum_{i=1}^{N}(x_i-\mu)^2
μ=N1i=1∑Nxi,σ2=N1i=1∑N(xi−μ)2
这相当于我们假定所有数据满足同一个正态分布
N
(
μ
,
σ
)
\N(\mu,\sigma)
N(μ,σ),而归一化就是将所有数据变成标准正态分布
N
(
0
,
1
)
\N(0,1)
N(0,1)。公式如下:
x
i
′
′
=
x
i
−
μ
σ
2
+
ϵ
x_i^{''}=\frac{x_i-\mu}{\sqrt{\sigma^2+\epsilon}}
xi′′=σ2+ϵxi−μ
这里
ϵ
\epsilon
ϵ的作用是防止方差变成0或者过小。
Inception v2
在VGG那篇博客中我们提到,将5×5的卷积分成两个3×3的卷积可以极高地提升卷积的计算效率。
上图是原始的Inception结构,我们将其中5×5的卷积换成两个3×3的卷积就变成了下图【figure 5】:
事实上,3×3的卷积可以进一步被分解成1×3的卷积和3×1的卷积的叠加,这样就可以得到如下的结构【figure 6】:
除此之外,3×3的卷积可以进一步被分解成1×3的卷积和3×1的卷积的并列,就得到了如下的结构【figure 7】:
【figure 5-7】的结构图就是Inception v2组成部分的主要结构,具体结构如下图中的表格所示:
Inception v3
Inception v3的卷积结构基本与Inception v2相同,但是在其基础上增加了许多优化点。
1-RMSProp
RMSProp(Root Mean Square Propagation)是一种优化方法,常用于深度学习中的梯度下降优化。它的目的是通过调整每个参数的学习率,来加速优化过程并提高模型训练的稳定性。RMSProp最早由Geoffrey Hinton提出。在传统的梯度下降中,每个参数都有一个固定的学习率,但在RMSProp中,每个参数的学习率是根据历史梯度的平方平均值进行调整的。通过跟踪每个参数的历史梯度平方的移动平均值,RMSProp可以动态调整每个参数的学习率,从而加速训练过程并防止梯度消失或爆炸。
RMSProp的计算过程:
- 首先,定义一个动量因子(通常记为 γ \gamma γ)和一个非常小的数(通常是 ϵ \epsilon ϵ)来防止除零错误。
- 初始化一个累积的平方梯度(记为 s s s),通常设为与参数相同形状的零矩阵。
- 在每一步训练中,计算当前参数的梯度。
- 计算累积平方梯度: s = γ ⋅ s + ( 1 − γ ) ⋅ gradient 2 s = \gamma \cdot s + (1 - \gamma) \cdot \text{gradient}^2 s=γ⋅s+(1−γ)⋅gradient2。
- 使用累积平方梯度调整学习率:学习率与 $ \sqrt{s + \epsilon} $ 反比。
- 根据调整后的学习率来更新参数。
RMSProp的更新公式:
假设当前参数为
θ
\theta
θ,梯度为
g
g
g,学习率为
α
\alpha
α,累积平方梯度为
s
s
s,那么RMSProp的更新公式为:
s
=
γ
⋅
s
+
(
1
−
γ
)
⋅
g
2
s = \gamma \cdot s + (1 - \gamma) \cdot g^2
s=γ⋅s+(1−γ)⋅g2
θ
=
θ
−
α
s
+
ϵ
⋅
g
\theta = \theta - \frac{\alpha}{\sqrt{s + \epsilon}} \cdot g
θ=θ−s+ϵα⋅g
其中:
- γ \gamma γ 是动量因子,通常取值在 0.9 0.9 0.9 左右。
- ϵ \epsilon ϵ 是一个小值,用于防止除零错误,通常为 1 e − 8 1e-8 1e−8。
- α \alpha α 是全局学习率。
通过这种方式,RMSProp可以动态调整学习率以适应不同的参数,这有助于加快收敛速度并提高模型的训练稳定性。
2-Label Smoothing
标签平滑(Label Smoothing)是一种正则化技术,用于改善模型训练过程中的稳定性并减少模型过度自信的问题。它通过在目标标签上引入一些随机噪声来实现。这种方法在目标标签中进行平滑,使得模型在预测时更加谨慎和鲁棒。
-
目标标签的转换:在标准的分类任务中,真实标签通常是一个one-hot编码(例如,三分类问题中,类别2的真实标签为
[0, 0, 1]
)。标签平滑将这个one-hot编码进行平滑处理。对于给定的真实标签y
,我们将目标标签q(k|x) = δk,y
转换为平滑后的分布q'(k|x)
:
q ′ ( k ∣ x ) = ( 1 − ϵ ) ⋅ δ k , y + ϵ ⋅ u ( k ) q'(k|x) = (1 - \epsilon) \cdot δk,y + \epsilon \cdot u(k) q′(k∣x)=(1−ϵ)⋅δk,y+ϵ⋅u(k)
这里, ϵ \epsilon ϵ 是平滑参数(通常是一个小的值,比如0.1),表示将真实标签转变为平滑标签的比例。 u ( k ) u(k) u(k) 是一个固定的分布,比如均匀分布u(k) = 1/K
(这里, K K K 是类别数量)。 -
交叉熵损失:模型训练的目标是最小化交叉熵损失。标准的交叉熵损失计算方式为:
ℓ = − ∑ k = 1 K q ′ ( k ∣ x ) ⋅ log p ( k ∣ x ) , \ell = -\sum_{k=1}^{K} q'(k|x) \cdot \log p(k|x), ℓ=−k=1∑Kq′(k∣x)⋅logp(k∣x),
其中 p ( k ∣ x ) p(k|x) p(k∣x) 是模型对类别k
的预测概率,q'(k|x)
是平滑后的目标标签。 -
损失的分解:交叉熵损失可以分解为两个部分:
-
(
1
−
ϵ
)
⋅
H
(
q
,
p
)
(1 - \epsilon ) \cdot H(q, p)
(1−ϵ)⋅H(q,p):这是标准交叉熵损失,其中
q
是原始的one-hot编码标签。 -
ϵ
⋅
H
(
u
,
p
)
\epsilon \cdot H(u, p)
ϵ⋅H(u,p):这是一个新损失项,衡量预测分布
p
与固定分布u
(通常是均匀分布)之间的差异。
-
(
1
−
ϵ
)
⋅
H
(
q
,
p
)
(1 - \epsilon ) \cdot H(q, p)
(1−ϵ)⋅H(q,p):这是标准交叉熵损失,其中
通过这种方式,标签平滑在原始标签与固定分布之间引入了一种平衡。这一过程有助于模型在训练过程中不对特定类别过于自信,从而提高模型的稳定性和泛化能力。
3-Batch Normalization
在BN-Inception进行过介绍,这里特指的是对辅助分类器也使用BN归一化。
4-分解7×7卷积
将模型一开始使用的7×7卷积分解成一系列3×3卷积。
Inception v4 / Inception-ResNet
与Inception v4同一篇论文提出的是Inception-ResNet v1和Inception-ResNet v2。整体上来看,Inception-ResNet v1和Inception-ResNet v2就是在Inception结构中增加了ResNet结构,此外Inception v4在Inception v3基础上结构更加复杂了一些,并没有太多新增的理论,详细可以查阅论文《Inception-v4, inception-resnet and the impact of residual connections on learning》
Xception
Xception来自论文《Xception: Deep Learning with Depthwise Separable Convolutions》,取义自Extreme Inception,通俗理解起来就是Inception结构中的极端情况,并结合了深度可分离卷积。(深度可分离卷积并不是这篇论文中提出的,而是Xception助推了其应用)下图是Xception的基本结构图【最极致的版本】,每个通道用一个独立的3×3卷积进行处理,并将结果进行拼接,而Xception其它结构则是位于Inception和这个最极致版本的结构之间。这样做的原理是,卷积时将通道和空间卷积分离会更好。Xception的1x1卷积作用于通道,3x3卷积同时作用于通道和空间,没有做到完全分离。所以Xception让3x3卷积只作用于一个通道的特征图,从而实现了完全分离。此举不仅可以提升性能,而且可以降低参数量。
Xception与深度可分离卷积并不是完全一致的(思想一样),其不同之处在于:
- 深度可分离卷积先对通道进行卷积再1x1卷积,而Xception先1x1卷积,再对通道卷积。
- 深度可分离卷积两个卷积间不带激活函数,Xception会经过ReLU。
代码实现
Pytorch中的torchvision库可以直接调用GoogleNet和Inceptionv3:
Weight | Acc@1 | Acc@5 | Params | GFLOPS | Recipe |
---|---|---|---|---|---|
GoogLeNet_Weights.IMAGENET1K_V1 | 69.778 | 89.53 | 6.6M | 1.5 | link |
Inception_V3_Weights.IMAGENET1K_V1 | 77.294 | 93.45 | 27.2M | 5.71 | link |
import torch.nn as nn
import torchvision.models as models
from torchvision.models.googlenet import GoogleNet_Weights
from torchvision.models.inception import Inception_v3_Weights
class GoogleNet(nn.Module):
def __init__(self):
super(GoogleNet, self).__init__()
self.googlenet = models.googlenet(weights=GoogleNet_Weights.IMAGENET1K_V1)
self.dim_feat = 1000
self.googlenet.classifier[2] = nn.Linear(4096, 1000)
def forward(self, x):
output = self.googlenet(x)
return output
class Inceptionv3(nn.Module):
def __init__(self):
super(Inceptionv3, self).__init__()
self.inception = models.inception(weights=Inception_v3_Weights.IMAGENET1K_V1)
self.dim_feat = 1000
self.inception.classifier[2] = nn.Linear(4096, 1000)
def forward(self, x):
output = self.inception(x)
return output
在timm库中有其它Inception模型,可以通过huggingface (Inception v3)找到:
model = timm.create_model('inception_v3', pretrained=True, num_classes=NUM_FINETUNE_CLASSES)
总结
从Inception最初提出到Xception,网络深度和网络宽度都不断增加。深度方面,出现了由多层卷积组成的子模块,多层子模块再构成的主模块,此外还利用残差连接的方式缓解梯度消失,为深层网络的应用提供可能。宽度方面,利用不同卷积核处理原始特征,并将处理后的特征进行拼接,其样式更加丰富。整体来说,虽然从单独一个模块的角度来说利用深度可分离卷积等方法使得训练速度加快,但是由于网络深度加深整体运行速度会变慢。
[1] Szegedy, Christian, et al. “Going deeper with convolutions.” Proceedings of the IEEE conference on computer vision and pattern recognition. 2015.
[2] Ioffe, Sergey, and Christian Szegedy. “Batch normalization: Accelerating deep network training by reducing internal covariate shift.” ICML. 2015.
[3] Szegedy, Christian, et al. “Rethinking the inception architecture for computer vision.” Proceedings of the IEEE conference on computer vision and pattern recognition. 2016.
[4] Szegedy, Christian, et al. “Inception-v4, inception-resnet and the impact of residual connections on learning.” Thirty-First AAAI Conference on Artificial Intelligence. 2017.
[5] Chollet, François. “Xception: Deep learning with depthwise separable convolutions.” Proceedings of the IEEE conference on computer vision and pattern recognition. 2017.
tion: Deep learning with depthwise separable convolutions." Proceedings of the IEEE conference on computer vision and pattern recognition. 2017.