深度学习之视觉特征提取器——GoogleNet/Inception

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=1Nxi,σ2=N1i=1N(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 1e8
  • α \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(kx)=(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=1Kq(kx)logp(kx),
    其中 p ( k ∣ x ) p(k|x) p(kx) 是模型对类别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(通常是均匀分布)之间的差异。

通过这种方式,标签平滑在原始标签与固定分布之间引入了一种平衡。这一过程有助于模型在训练过程中不对特定类别过于自信,从而提高模型的稳定性和泛化能力。

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与深度可分离卷积并不是完全一致的(思想一样),其不同之处在于:

  1. 深度可分离卷积先对通道进行卷积再1x1卷积,而Xception先1x1卷积,再对通道卷积。
  2. 深度可分离卷积两个卷积间不带激活函数,Xception会经过ReLU。

代码实现

Pytorch中的torchvision库可以直接调用GoogleNet和Inceptionv3:

WeightAcc@1Acc@5ParamsGFLOPSRecipe
GoogLeNet_Weights.IMAGENET1K_V169.77889.536.6M1.5link
Inception_V3_Weights.IMAGENET1K_V177.29493.4527.2M5.71link
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.

  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深度学习在纹理特征提取方面取得了很大的进展。下面是一种常用的深度学习方法,用于纹理特征提取: 卷积神经网络(Convolutional Neural Network,CNN)是一种广泛用于图像处理任务的深度学习模型。CNN通过多层卷积和池化操作来提取图像的特征。在纹理特征提取中,可以使用预训练的CNN模型,如VGG、ResNet或Inception等,作为特征提取。 以下是使用预训练的VGG模型进行纹理特征提取的示例代码: ```python import tensorflow as tf from tensorflow.keras.applications.vgg16 import VGG16 from tensorflow.keras.preprocessing import image from tensorflow.keras.applications.vgg16 import preprocess_input import numpy as np # 加载预训练的VGG模型 model = VGG16(weights='imagenet', include_top=False) # 加载图像 img_path = 'texture_image.jpg' img = image.load_img(img_path, target_size=(224, 224)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) # 提取特征 features = model.predict(x) # 打印特征向量 print(features) ``` 在上述代码中,我们首先加载了预训练的VGG模型,并指定了要提取特征的图像路径。然后,我们将图像预处理为模型所需的输入格式,并使用模型对图像进行特征提取。最后,我们打印出提取到的特征向量。 需要注意的是,上述代码中的图像路径需要替换为实际的纹理图像路径,并且可能需要根据具体的任务进行适当的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值