【DL-CV】卷积神经网路<前篇—后篇>【DL-CV】批量归一化(BN算法)
数据预处理
在网络训练时,我们通常会对原始数据进行预处理再喂给网络进行训练,而不是直接把原始数据喂给网络。这样能减少训练时问题的发生,提高网络模型的性能。现在我们有原始数据 X,其尺寸是 NxD(N是数据样本数量,D是数据的维度)
均值减法
均值减法(Mean subtraction)是预处理最常用的形式,将数据的每一维特征都减去平均值即可,在numpy的实现是X -= np.mean(X, axis=0)
,它能使数据零中心化。
另外还有一些类似的方法对图像数据预处理来说也很可能用到:
- 直接减去整个数据的均值,
X -= np.mean(X)
,对于图像,可以移除图像的平均亮度值,因为很多情况下我们对图像亮度并不感兴趣,而是关注其内容,所以将图像整体减去像素均值是有意义的 - 减去每个颜色通道上的均值
归一化
归一化(Normalization)也是一种预处理的方法,他将数据的所有维度都归一化,使其数值范围都近似相等。先对数据做零中心化处理,然后每个维度都除以其标准差
x = x - np.mean(x, axis=0)
x = x / np.std(x, axis=0)
除此之外,预处理方法还有PCA和白化,但在图像处理这一块他们用得并不是很多,这里就不讲了,有兴趣自查。在图像识别领域,更常用的是零中心化和归一化,特别是零中心化
零中心化在使用时,先将样本数据分成训练/验证/测试集,从训练集中求得平均值,然后将各个集(训练/验证/测试集)中的数据再减去这个均值。
权重初始化
首先,全零初始化想想都知道肯定是错的。
然后,小随机数初始化如W = 0.01 * np.random.randn(D,H)
是可以的(randn函数是基于零均值和标准差的一个高斯分布),不过不是越小越好,权重初始化的太小的话计算出来的激活值会很小,在反向传播中就会得到很小的梯度,后果你知道的。
但是,还不是最好的,小随机数初始化有一个问题就是随着输入数据量的增长,随机初始神经元输出数据的方差也增大,这样网络一深问题就大了。解决方法是:除以输入数据量的平方根来调整数值范围,使神经元输出的方差归一化为1,也就是W = np.random.randn(in, out) / sqrt(in)
,其中in是输入数据的数量(若W尺寸 DxH ,则in=D,out=H)。这种更厉害的方法叫做 Xavier初始化,他保证了网络中所有神经元起始时有近似同样的输出分布。实践经验证明,这样做可以提高收敛的速度。
《Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification》论文指出,使用relu激活函数的网络,由于一半的激活值变成了0,相当于一半的输入数据量是对方差无贡献的,为保持输入输出的方差维持不变,初始化方法也作了相应改变(根号中的数据量除以二): W = np.random.randn(in, out) / sqrt(in/2)
,这是针对使用relu的初始化方法。
至于偏置值,通常初始化为0
总结
针对图像识别领域,通常来说
- 数据预处理使用零中心化
- 权重初始化使用Xavier;如网络使用relu,使用
W = np.random.randn(in, out) / sqrt(in/2)
- 偏置值初始化为0