目录
一、Inception名称的由来
二、Inception结构
三、Inception v2
四、Inception v3
1、深度网络的通用设计原则
2.卷积分解(Factorizing Convolutions)
3.对称卷积分解
3.非对称卷积分解
五、Inception v4
一、Inception名称的由来
Inception网络名字来源于《盗梦空间》。inception网络代替人工确定卷积 层中的过滤器类型,解决了计算量爆炸的问题,让网络变得更深。
基于对AlexNet 的卷积过程的研究,大家逐渐强化了一个信念-----更深的 网络带来更高的准确率,所以最简单,安全,有效地提高准备率的办法就是增加网络 的深度.这也正是Inception名称所隐含的"We need to go deeper"的含义.
增加网络的深度(往往同时增加每层神经元数量) 容易导致以下几个方面的 问题.
(1) 导致神经网络参数的数量过多,网络不容易训练,容易出现过拟合,需要更 多的训练数据. 然而训练数据并不容易获得,尤其是需要人工标记样本数据时就更 难了.所以如何在增加网络规模的同时尽可能地减少参数的数量是首先要考虑的 问题.
(2 )增大了网络的规模(更深,更宽) , 需要消耗大量的计算资源,需要"有 效"和"充分"地使用计算资源.以两个卷积堆叠为例,随着卷积层的过滤器线性增 加,所需要的计算资源与过滤器个数的平方成正比.如果所增加的计算资源没有 被"有效"地使用,如所有的权重于0(但不等于0),那么这些计算量不会带来准确率 的提高,
(3)当网络的深度达到一定程度之后,浅层神经网络容易出现梯度弥散的问题, 这是因为,误差反向传播的时候,随着深度的增加梯度会迅速变小,从而导致权重参 数变化缓慢,模型无法收敛.
Inception 的网络架构正是沿着如何解决以上几个问题的方向,有针对性地设 计网络架构的.
二、Inception结构
Inception就是将多个卷积或池化操作放在一起组装成一个网络模块,设计 神经网络时,以模块为单位去组装整个网络结构。Inception结构设计了一个稀 疏网络结构,但是能够产生稠密的数据,既能增加神经网络表现,又能保证计 算资源的使用效率。
假设input feature map的size为28 × 28 × 256 ,output feature map的 size为28 × 28 × 480 则native Inception Module的计算量有854M。计算过程 如下
从上图可以看出,计算量主要来自高维卷积核的卷积操作,因而在每一个 卷积前先使用1 × 1卷积核将输入图片的feature map维度先降低,进行信息压 缩,在使用3x3卷积核进行特征提取运算,相同情况下,Inception v1的计算量 仅为358M。
Inception v1结构总共有4个分支,输入的feature map并行的通过这四个 分支得到四个输出,然后在在将这四个输出在深度维度(channel维度)进行拼 接(concate)得到我们的最终输出(注意,为了让四个分支的输出能够在深度方 向进行拼接,必须保证四个分支输出的特征矩阵高度和宽度都相同),因此 inception结构的参数为:
branch1:Conv1×1 , stride=1
branch2:Conv3×3, stride=1, padding=1
branch3:Conv5×5, stride=1, padding=2
branch4:MaxPool3×3, stride=1, padding=1
一个完整的Inception模块如图所示。
通过将这些模块组合起来就得到了完整的inception网络,由于它是由 google的研究员提出的,所以也叫做goolenet,是为了向lenet致敬。
inception网络:
Inception网络就是将多个Inception模块连接成一个网络。
网络的最后几层通常为全连接层,最后接一个softmax层。可以看到网络中 的隐藏层有很多分支。这些分支使得隐藏层也可以单独进行预测,降低了过拟 合的风险。
代码实现:
#需求:inception,cifar10 确定框架 conv,maxpool flatten ,dense
dropout ,预处理,bn,激活平均池化,全局平均池化
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, MaxPool2D,
Flatten, Dense, Dropout, BatchNormalization, Activation,
AveragePooling2D, GlobalAveragePooling2D
from tensorflow.keras import Model
(x_train,y_train),
(x_test,y_test)=tf.keras.datasets.cifar10.load_data()
x_train=x_train.reshape([-1,32,32,3])/255
x_test=x_test.reshape([-1,32,32,3])/255
class ConvBNRelu(Model):
def __init__(self, ch, kernelsz=3, strides=1,
padding='same'):
super(ConvBNRelu, self).__init__()
self.model = tf.keras.models.Sequential([
Conv2D(ch, kernelsz, strides=strides,
padding=padding),
BatchNormalization(),
Activation('relu')
])
def call(self, x):
x = self.model(x, training=False) # 在training=False时,
BN通过整个训练集计算均值、方差去做批归一化,training=True时,通过当前
batch的均值、方差去做批归一化。推理时 training=False效果好
return x
class InceptionBlk(Model):
def __init__(self, ch, strides=1):
super(InceptionBlk, self).__init__()
self.ch = ch
self.strides = strides
self.c1 = ConvBNRelu(ch, kernelsz=1, strides=strides)
self.c2_1 = ConvBNRelu(ch, kernelsz=1,
strides=strides)
self.c2_2 = ConvBNRelu(ch, kernelsz=3, strides=1)
self.c3_1 = ConvBNRelu(ch, kernelsz=1,
strides=strides)
self.c3_2 = ConvBNRelu(ch, kernelsz=5, strides=1)
self.p4_1 = MaxPool2D(3, strides=1, padding='same')
self.c4_2 = ConvBNRelu(ch, kernelsz=1,
strides=strides)
def call(self, x):
x1 = self.c1(x)
x2_1 = self.c2_1(x)
x2_2 = self.c2_2(x2_1)
x3_1 = self.c3_1(x)
x3_2 = self.c3_2(x3_1)
x4_1 = self.p4_1(x)
x4_2 = self.c4_2(x4_1)
# concat along axis=channel
x = tf.concat([x1, x2_2, x3_2, x4_2], axis=3)
return x
class Inception10(Model):
def __init__(self, num_blocks, num_classes, init_ch=16,
**kwargs):
super(Inception10, self).__init__(**kwargs)
self.in_channels = init_ch
self.out_channels = init_ch
self.num_blocks = num_blocks
self.init_ch = init_ch4. Inception v2
即在v1的基础上于卷积层与激活函数之间插入BN层:Conv-BN-ReLU,并
将v1结构中的5 × 5 卷积核替换为2个3 × 3 卷积核。第二篇论文里,作者给出了
inception v2中卷积分解的详细说明。
self.c1 = ConvBNRelu(init_ch)
self.blocks = tf.keras.models.Sequential()
for block_id in range(num_blocks):
for layer_id in range(2):
if layer_id == 0:
block = InceptionBlk(self.out_channels,
strides=2)
else:
block = InceptionBlk(self.out_channels,
strides=1)
self.blocks.add(block)
# enlarger out_channels per block
self.out_channels *= 2
self.p1 = GlobalAveragePooling2D()
self.f1 = Dense(num_classes, activation='softmax')
def call(self, x):
x = self.c1(x)
x = self.blocks(x)
x = self.p1(x)
y = self.f1(x)
return y
model = Inception10(num_blocks=2, num_classes=10)
#模型编译
model.compile(loss=tf.keras.losses.SparseCategoricalCrossentr
opy(),
optimizer=tf.keras.optimizers.Adam(lr=0.001),
metrics=['accuracy'])
#one-hot编码
history=model.fit(x_train,y_train,batch_size=64,epochs=1,vali
dation_split=0.3)
score = model.evaluate(x_test, y_test)
print('loss', score[0])
print('accuracy', score[1])
三、Inception v2
即在v1的基础上于卷积层与激活函数之间插入BN层:Conv-BN-ReLU,并 将v1结构中的5 × 5 卷积核替换为2个3 × 3 卷积核。第二篇论文里,作者给出了 inception v2中卷积分解的详细说明。
Batch Normalization
小卷积核替代大卷积核
在VGGNet中就提出了通过堆叠两层3 × 3 的卷积核可以替代一层5 × 5 的卷 积核,堆叠三层 3 × 3的卷积核替代一层 7 × 7 的卷积核(参考:VGGNet网络 详解与模型搭建)。这样的连接方式在保持感受野范围的同时又减少了参数 量,并且可以避免表达瓶颈,加深非线性表达能力。基于此,作者通过将 inception v1结构中的5 × 5 卷积核替换为2个3 × 3 卷积核。如下左图为v1结 构,右图为v2结构。
四、Inception v3
1、深度网络的通用设计原则
(1) 避免表达瓶颈,特别是在网络靠前的地方。 信息流前向传播过程中显 然不能经过高度压缩的层,即表达瓶颈。从input到 output,feature map的宽和高基本都会逐渐变小,但是不能一下子就变得很小。比如你 上来就来个kernel = 7, stride = 5 ,这样显然不合适。另外输出的维度 channel,一般来说会逐渐增多(每层的num_output),否则网络会很难 训练。(特征维度并不代表信息的多少,只是作为一种估计的手段)。
(2) 高维特征更易处理。 高维特征更易区分,会加快训练。
(3)可以在低维嵌入上进行空间汇聚而无需担心丢失很多信息。 比如在进 行3x3卷积之前,可以对输入先进行降维而不会产生严重的后果。假设 信息可以被简单压缩,那么训练就会加快。
(4)平衡网络的宽度与深度
2.卷积分解(Factorizing Convolutions)
将一个大卷积核的操作分解成若干个小卷积核的操作称为卷积分 解,并探讨了2种不同的卷积分解方法,即对称卷积分解和不对称卷积 空间分解。
3.对称卷积分解
即使用小卷积核串联来替代大卷积核,这在inception v2中已经提到过。同时作 者还提出,通过大量实验表明这种替代方案并不会造成表达能力的下降。通过 堆叠两层3 × 3 3\times33×3的卷积核可以替代一层5 × 5 的卷积核,堆叠三层 3 × 3 的卷积核替代一层 7 × 7 的卷积核,可以看出,大卷积核完全可以由一系列 的3 × 3 卷积核来替代,那能不能再分解得更小一点呢?GoogLeNet团队考虑了 非对称卷积分解。
3.非对称卷积分解
任意n × n 的卷积都可以通过1 × n 卷积后接n × 1卷积来替代,如下图(右)所 示。
在网络的前期使用这种分解效果并不好,还有在中度大小的feature map 上使用效果才会更好
降低特征图大小
一般情况下,如果想让特征图的通道数,可以有如下两种方式:
先池化再作Inception卷积,或者先作Inception卷积再作池化。但是方法一 (左图)先作pooling(池化)会导致特征表示遇到瓶颈(特征缺失),方法二 (右图)是正常的缩小,但计算量很大。为了同时保持特征表示且降低计算 量,将网络结构改为下图,使用两个并行化的模块来降低计算量(卷积、池化 并行执行,再进行合并),即用卷积得到一半的特征图,池化得到一半的特征 图,再进行拼接。
五、Inception v4
2016年ResNet网络的提出解决了随着神经网络的加深,参数越来越多,模 型越来越难以训练,训练时间大大增加,容易出现梯度消散问题。为了融合这 一重要成果,Inception v4研究了Inception模块与残差连接(Residual Connection)的结合来改进V3结构。
如图,将残差模块的卷积结构替换为Inception结构,即得到Inception Residual结构。除了上述右图中的结构外,作者通过20个类似的模块进行组 合,最后形成了InceptionV4的网络结构,构建了Inception-ResNet模型.
总结回顾
Inception v1主要采用了多尺度卷积核、1x1卷积操作。
Inception v2在v1的基础上增加了BN层,使用2个3 × 3小卷积核堆叠替换5 ×
5大卷积核;
inception v3进行了卷积分解(将7 × 7 分解成两个一维的卷积1 × 7 和1 ×
7 ,3 × 3 也是一样1 × 3 和3 × 1 和特征图降维。
inception v4在v3的基础上融合了Residual模块。