4 months ago

一、背景介绍

GoogleNet和VGG是2014年ImageNet竞赛的双雄,这两类模型结构有一个共同特点是go deeper,即网络层级加深
vgg继承了LeNet以及AlexNet的一些框架
GoogleNet做了更大胆的网络上的尝试,该模型虽然有22层,但大小却比alexnet和vgg都小很多(参数量仅为AlexNet的1/12),性能优越

通常,获得高质量模型最保险的做法就是增加模型的深度(层数)或者是其宽度(每一层卷积核核或者神经元数)
但是这里一般设计思路的情况下会出现三种缺陷:
1.参数太多,若训练数据集有限,容易过拟合,;
2.网络越大计算复杂度越大,难以应用;
3.网络越深,梯度越往后穿越容易消失,难以优化模型

googlenet的主要思想就是围绕着提高模型质量的两个方向同时又规避三种风险的思路去做的:
1.深度:层数更深,采用了22层
为了避免上述提到的梯度消失问题,googlenet巧妙的在不同深度处增加了两个loss来保证梯度回传消失的现象。

2.宽度:增加了多种核1x1,3x3,5x5,还有直接max pooling的
但是如果简单的将这些应用到feature map上的话,concat起来的feature map厚度将会很大
所以在googlenet中为了避免这一现象提出的Inception Module:在3x3前,5x5前,max pooling后分别加上了1x1的卷积核起到了降低feature map厚度的作用。

二、GoogleNet网络结构

下面采用层层推进的方式介绍GoogleNet网络结构

1.Inception Module:网中网结构

GoogleNet最令人称道的就是它的Inception Module(网中网NIN network in network)结构
整个网络由9个这样的Inception Module构成
下面一张简单的图介绍NIN结构


卷积层采用不同尺寸规格的卷积核,增加特征提取的多样性,然后把不同的卷积结果进行深度上的“连接”
举个例子理解起来更直观

# -*- coding: utf-8 -*-
import tensorflow as tf
#"1个高3宽3深度2(3x3x2)的输入张量"
inputTensor=tf.constant(
        [
        [
        [[2,5],[3,3],[8,2]],
        [[6,1],[1,2],[5,4]],
        [[7,9],[2,-3],[-1,3]]
        ]
        ],tf.float32
        )
#
session=tf.Session()
#"3个高1宽1深度2(1x1x2)的卷积核"
filter112_3=tf.constant(
        [
        [[[1,2,-1],[-1,-2,2]]]
        ],tf.float32
        )
result1=tf.nn.conv2d(inputTensor,filter112_3,[1,1,1,1],'SAME')
print(session.run(result1))
#"2个高2宽2深度2(2x2x2)的卷积核"
filter222_2=tf.constant(
        [
        [[[3,-1],[1,2]],[[-2,1],[2,3]]],
        [[[-1,1],[-3,7]],[[4,2],[5,4]]]
        ],tf.float32)
result2=tf.nn.conv2d(inputTensor,filter222_2,[1,1,1,1],'SAME')
print(session.run(result2))
#"最大池化"
maxPool_33=tf.nn.max_pool(inputTensor,[1,3,3,1],[1,1,1,1],'SAME')
print(session.run(maxPool_33))
#"深度方向上拼接"
result=tf.concat([result1,result2,maxPool_33],3)
print(session.run(result))

2.在卷积层添加并行pooling用于提高效率

3.采用1x1的卷积核减少计算成本

直接导致GoogleNet该模型虽然有22层,但大小却比alexnet和vgg都小很多(参数量仅为AlexNet的1/12,当然也有很大一部分原因是去掉了全连接层),性能优越

4.Batch Normalization(批量归一化BN)

对输入数据做了归一化处理,就是将每个特征在所有样本上的值转归一化成均值0方差1。
这样我们保证训练数据里数值都同样量级上,从而使得训练的时候数值更加稳定。

对于浅层模型来说,通常数据归一化预处理足够有效。输出数值在只经过几个神经层后通常不会出现剧烈变化。
但对于深层神经网络来说,情况一般比较复杂。因为每一层里都对输入乘以权重后得到输出。
当很多层这样的相乘累计在一起时,一个输出数据较大的改变都可以导致输出产生巨大变化,从而带来不稳定性。

批量归一化层的提出是针对这个情况。它将一个批量里的输入数据进行归一化然后输出。
如果我们将批量归一化层放置在网络的各个层之间,那么就可以不断的对中间输出进行调整,从而保证整个网络的中间输出的数值稳定性。

Batch Normalization批量归一化(简称BN)是由著名的GoogleNet首次提出
它有效地解决了在网络层数很深地情况下,收敛速度很慢地问题
使用BN操作可以加大网络梯度下降的学习率,加速网络收敛
在实际应用中,批量归一化的收敛非常快,并且具有很强的泛化能力,某种情况下完全可以替代正则化和弃权。

BN的地位:与激活函数层、卷积层、全连接层、池化层一样

BN的本质原理:在网络的每一层输入的时候(通常在激活函数前),也就是先做一个归一化处理(归一化至:均值0、方差为1)

GoogleNet的完整结构如下


参考资料:
GoogLeNet学习心得

← 【深度学习】Batch Normalization批量归一化 【深度学习】深度学习资料 →