侧抑制(lateral inhibition)
局部归一化出现原因:在神经生物学上有一个概念叫做 侧抑制(lateral inhibition),指的是被激活的神经元抑制相邻神经元。归一化的目的是“抑制”,局部响应归一化就是借鉴侧抑制的思想实现局部抑制尤其适用ReL()激活函数的时候这种思想表现很高效。
优势:
- 增加泛化能力,做了平滑处理,识别率提高1%~2%
- LRN模仿生物神经元侧抑制,对局部神经元活动建立竞争机制,使得响应比较大的值相对更大,提高模型泛化能力,Hinton在ImageNet表现分别提高1.4%和1.2%
什么是归一化?
归一化化是归纳统一样本的统计分布性。就是要把你需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。
为什么要归一化,归一化目的是什么?
- 为了后面数据处理的方便,归一化的确可以避免一些不必要的数值问题。
- 为了程序运行时收敛加快。 下面图解。
- 同一量纲。样本数据的评价标准不一样,需要对其量纲化,统一评价标准。这算是应用层面的需求。
- 避免神经元饱和,就是当神经元的激活在接近0或者1时会饱和,在这些区域,梯度几乎为0,这样,在反向传播过程中,局部梯度就会接近0,这会有效地“杀死”梯度。
- 保证输出数据中数值小的不被吞食。
左图:归一化前 右图:归一化后
计算公式
Alex-Net网络结构
a表示第i核在位置(x,y),运用ReLU()非线性神经元输出,n是同一个位置kernel map的数量,N是kernel的总数。
K = 5,n = 5 ,alpha = 1e-4 , beta=0.75
争议:
在2015年 Very Deep Convolutional Networks for Large-Scale Image Recognition.提到LRN基本没什么用。
参考文献:
[LRN]:ImageNet Classification with Deep Convolutional Neural Networks
Very Deep Convolutional Networks for Large-Scale Image Recognition
AlexNet将LeNet的思想发扬光大,把CNN的基本原理应用到了很深很宽的网络中。AlexNet主要使用到的新技术点如下。
- 成功使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过了Sigmoid,成功解决了Sigmoid在网络较深时的梯度弥散问题。虽然ReLU激活函数在很久之前就被提出了,但是直到AlexNet的出现才将其发扬光大。
- 训练时使用Dropout随机忽略一部分神经元,以避免模型过拟合。Dropout虽有单独的论文论述,但是AlexNet将其实用化,通过实践证实了它的效果。在AlexNet中主要是最后几个全连接层使用了Dropout。
- 在CNN中使用重叠的最大池化。此前CNN中普遍使用平均池化,AlexNet全部使用最大池化,避免平均池化的模糊化效果。并且AlexNet中提出让步长比池化核的尺寸小,这样池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。
- 提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
这个公式中的a表示卷积层(包括卷积操作和池化操作)后的输出结果,这个输出结果的结构是一个四维数组[batch,height,width,channel],这里可以简单解释一下,batch就是批次数(每一批为一张图片),height就是图片高度,width就是图片宽度,channel就是通道数可以理解成一批图片中的某一个图片经过卷积操作后输出的神经元个数(或是理解成处理后的图片深度)。ai(x,y)表示在这个输出结构中的一个位置[a,b,c,d],可以理解成在某一张图中的某一个通道下的某个高度和某个宽度位置的点,即第a张图的第d个通道下的高度为b宽度为c的点。论文公式中的N表示通道数(channel)。a,n/2,k,α,β分别表示函数中的input,depth_radius,bias,alpha,beta,其中n/2,k,α,β都是自定义的,特别注意一下∑叠加的方向是沿着通道方向的,即每个点值的平方和是沿着a中的第3维channel方向的,也就是一个点同方向的前面n/2个通道(最小为第0个通道)和后n/2个通道(最大为第d-1个通道)的点的平方和(共n+1个点)。而函数的英文注解中也说明了把input当成是d个3维的矩阵,说白了就是把input的通道数当作3维矩阵的个数,叠加的方向也是在通道方向。
tensorflow下的局部响应归一化函数tf.nn.lrn
官方说明如下:
sqr_sum[a, b, c, d] = sum(input[a, b, c, d - depth_radius : d + depth_radius + 1] ** 2)
output = input / (bias + alpha * sqr_sum) ** beta
In [35]: import tensorflow as tf
In [36]: import numpy as np
In [37]: x = np.array([i for i in range(1,33)]).reshape([2,2,2,4])
In [38]: y = tf.nn.lrn(input=x,depth_radius=2,bias=0,alpha=1,beta=1)
In [39]: with tf.Session() as sess:
...: print(x)
...: print(y.eval())
[[[[ 1 2 3 4]
[ 5 6 7 8]]
[[ 9 10 11 12]
[13 14 15 16]]]
[[[17 18 19 20]
[21 22 23 24]]
[[25 26 27 28]
[29 30 31 32]]]]
[[[[ 0.07142857 0.06666667 0.10000001 0.13793103]
[ 0.04545454 0.03448276 0.04022989 0.05369128]]
[[ 0.02980132 0.02242153 0.02466368 0.03287672]
[ 0.0220339 0.01654846 0.0177305 0.02363368]]]
[[[ 0.0174538 0.01310044 0.01382824 0.01843318]
[ 0.01444292 0.01083744 0.01133005 0.01510384]]
[[ 0.01231527 0.00923952 0.00959488 0.01279123]
[ 0.01073279 0.00805153 0.00831991 0.01109185]]]]