摘要
大名鼎鼎的的Inception系列网络,是由Google Inc在2018年9月发布的“Going deeper with convolutions”,中文意思为更深的卷积。由此也可见一斑,该文章在深度神经网络的结构大做文章。
- 提出了一种代号为Inception的深度卷积神经网络结构,并在分类和检测上取得了新的最好结果。
- inception体系结构的主要特点是提高了网络内计算资源的利用率。这是通过精心设计实现的,该设计允许在保持计算预算不变的同时增加网络的深度和宽度。
- 改善深层神经网络性能最直接的方法是增加它们的大小。这包括增加网络的深度(层数)及其宽度:每层的单元数。这是一种简单而安全的方法来训练高质量的模型,特别是考虑到大量的标记训练数据的可用性。
- 然而,这个简单的解决方案有两个主要缺点:
- 1) 更大的规模通常意味着更多的参数,这使得扩大后的网络更容易过度拟合,特别是在训练集中标记示例的数量有限的情况下;
- 2)网络大小均匀增加的另一个缺点是计算资源的使用急剧增加。例如,在深度视觉网络中,如果将两个卷积层链接起来,它们的滤波器数目的任何均匀增加都会导致计算的二次增长。如果增加的容量没有得到有效的使用(例如,如果大多数权重最终接近于零),那么大量的计算就会被浪费掉。由于计算预算在实践中总是有限的,因此更倾向于有效分配计算资源,而不是任意增加规模,即使主要目标是提高结果的质量。
到这里作者提出了两个问题,但是根据写文章套路!这必定已经有人解决了,但是在这基础上又有新的问题引出。
果不其然,这篇文章也是这样子的套路。
- 解决这两个问题的一个基本的方式就是将全连接层替换为稀疏的全连接层,甚至在卷积层内部。除了模仿生物系统之外,由于Arora等人的开创性工作,这也将具有更坚实的理论基础的优势。
好,接下来又提出了缺点:
- 缺点是,今天的计算架构对于非均匀稀疏数据结构的数值计算效率很低。即使算术运算的数量减少了100倍,查找和缓存丢失的开销仍然占主导地位,因此切换到稀疏矩阵是不会有好处的。
解决这些问题的方法当然就是在增加网络深度和宽度的同时减少参数,为了减少参数,自然就想到将全连接变成稀疏连接。但是在实现上,全连接变成稀疏连接后实际计算量并不会有质的提升,因为大部分硬件是针对密集矩阵计算优化的,稀疏矩阵虽然数据量少,但是计算所消耗的时间却很难减少。
那么,有没有一种方法既能保持网络结构的稀疏性,又能利用密集矩阵的高计算性能。大量的文献表明可以将稀疏矩阵聚类为较为密集的子矩阵来提高计算性能,就如人类的大脑是可以看做是神经元的重复堆积,因此,GoogLeNet团队提出了Inception网络结构,就是构造一种“基础神经元”结构,来搭建一个稀疏性、高计算性能的网络结构。
Inception网络
GoogLeNet 由 9 组 inception 模块线性堆叠组成。深 22 层(如算上池化层共 27 层)。
以下为整个网络的参数值:
Inception naive结构如下:
下图看的更加直观点:
还有这种类型的Inception 模块:
Inception 模块的作用:
- Inception 模块会并行计算同一输入映射上的多个不同变换,并将它们的结果都连接到单一一个输出。换句话说,对于每一个层,Inception 都会执行 5×5 卷积变换、3×3 卷积变换和最大池化。然后该模型的下一层会决定是否以及怎样使用各个信息。
- Inception可以看做是在水平方向上加深了网络
使用1*1卷积的作用:
- 降维( dimension reductionality )。比如,一张500 * 500 depth为100的图片在20个filter上做11的卷积,那么结果的大500500*20。
- 加入非线性。卷积层之后经过激励层,1*1的卷积在前一层的学习表示上添加了非线性激励( non-linear activation),提升网络的表达能力;
辅助loss函数:
为防止网络中间部分不会「梯度消失」,作者引入了 2 个辅助分类器,它们本质上对 2 个 inception 模块的输出执行 softmax,并计算对同一个标签的 1 个辅助损失值。
辅助损失值纯粹是为训练构建,分类推断时将被忽略。辅助分类器促进了更稳定的学习和更好的收敛。辅助分类器往往在接近训练结束时,辅助分支网络开始超越没有任何分支的网络的准确性,达到了更高的稳定水平。
GoogleInceptionNet创新之处:
- 去除了最后的全连接层,用全局平均池化层(即将图片尺寸变为1x1)来取代他.
- 根据Hebbian原理,多次使用1x1卷积核(即将相关性很高、在同一个空间位置但是不同通道的特征连接起来).
- 使用了Inception Module提高了参数利用效率.
- 提出了著名的Batch Normalization(BN)方法,该方法可以让大型卷积网络的训练速度加快很多倍,同时收敛后的分类内部准确率也可以得到大幅提高.
- 引入Factorization into small convolutions的思想,将一个较大的2维卷积拆成两个较小的一维卷积,如把3x3卷积拆成1x3和3x1两个小卷积,不仅可以加速运算还可以减轻过拟合.
tensorflow代码(Inception v3)
from datetime import datetime
import math
import time
import tensorflow as tf
slim = tf.contrib.slim
trunc_normal = lambda stddev: tf.truncated_normal_initializer(0.0, stddev)
# 生成网络中经常用的函数的默认参数
def inception_v3_arg_scope(weight_decay = 4e-5,
stddev = 0.1,
batch_norm_var_collection = 'moving_vars'):
'''
weight_decay: L2正则weight_decay
stddev: 标准差
batch_norm_var_collection: 默认设置为moving_vars
'''
# 定义batch normalization的参数字典
batch_norm_params = {
'decay': 0.9997,
'epsilon': 0.001,
'updates_collections': tf.GraphKeys.UPDATE_OPS,
'variables_collections': {
'beta': None,
'gamma': None,
'moving_mean': [batch_norm_var_collection],
'moving_variance': [batch_norm_var_collection],
}
}
# 使用slim.arg_scope对参数进行自动复赋值
with slim.arg_scope([slim.conv2d, slim.fully_connected],
weights_regularizer=slim.l2_regularizer(weight_decay)):
with slim.arg_scope(
[slim.conv2d],
weights_initializer=trunc_normal(stddev),
activation_fn=tf.nn.relu,
normalizer_fn=slim.batch_norm,
normalizer_params=batch_norm_params) as sc:
return sc
# 定义Inception