参考cs231n与这位的博文https://www.zhihu.com/people/will-55-30/posts?page=1 非常感谢!
- 对输入数据的预处理
Mean Subtraction
中心化X-=np.mean(X)
中心化的好处:
不中心化的话,决策边界稍微变一下,loss就会有很大的改变;而右边中心化了的话,稍微转一下也没有关系的。
Normalization
将数据的所有维度都归一化,使其数值范围都近似相等
可以先对数据做零中心化然后每个维度都除以其标准差X/=np.std(X,axis=0)
或者对每个维度做归一化使其在[-1,+1]之间
这个预操作只有在确信你不同的输入特征有不同的数值范围或计量单位时才有意义,像图像这种每个元素都在[0,255]之间的就用不着
Batch Normalization
在神经网络中额外加入一层,以使得中间的激活值均值为0方差为1
在forward pass时用mini batch的数据来计算均值与方差,用这个估计值对数据进行归一化。
即在W与激活函数之间加一个BatchNorm层
可以理解为在网络的每一层之前都做预处理
- W的初始化
错误:全零初始化
这样会导致每个神经元都计算出同样的输出,然后就会在反向传播中计算出相同的梯度,从而进行相同的参数更新。
小随机数初始化
W=0.01*np.random.randn(fan_in, fan_out);
但当一个神经网络的层中的权重值很小,那么在反向传播时会计算出非常小的梯度,就会很大程度上减小反响传播中的梯度信号,在深度网络中就会出问题
Xavier initialization(最推荐)
W=np.random.randn(fan_in,fan_out)/np.sqrt(fan_out)
- biases的初始化
通常初始化为0
Babysitting Learning
x轴通常都是表示周期(epochs),一个周期意味着每个样本数据都被观察过一次了。由于使用了mini batch素以epochs与iteration是不一样的
第一个图中而可以看到绿色的那条先所以学得快,但学到一个不太好的位置就停下了。这是因为最优化的“能量”太大,参数在混沌中随机震荡,不能最优化到一个很好的点上。
损失值的震荡程度和批尺寸有关,当批尺寸是1,震荡就会相对很大。而批尺寸是整个数据集时震荡就最小,因为每次梯度更新都是单调的优化损失函数。(除非学习率设置的过高)
最右边那个图,随时间增加训练集上的效果越来越好而验证集上的效果不在上升,这表明模型进入过拟合状态,这个时候就要加入其它的正则化手段。
另一个需要跟踪的是训练集和验证集的准确率
这个图表能够知道模型过拟合的程度
过拟合太严重比如蓝色曲线,那么就要增大正则化强度或收集更多的数据
还有一种不太好的状况就是验证集曲线与训练集曲线如影随形,这说明模型容量还不够大,应该通过增加参数数量让模型容量更大。
还要跟踪权重更新比例,一般应该在1e-3左右,太小说明学习率太小了
还要观察每次的激活数据及梯度分布
比如对于使用tanh的神经元,本应看到激活数据的值在整个[-1,1]上都有分布,如果看到神经元的输出全是0或-1或1的话那就有问题了。
还可以进行第一层可视化
梯度检查
把解析梯度与数值梯度进行比较
一般1e-7比较好,但随着网络深度的加深误差也会累积也不用一直要求1e-7
训练之前的合理性检查
1.寻找特定情况的正确损失值
2.对小数据子集过拟合
超参数搜索
随机搜索更能精确地发现那些比较重要的超参数的好数值。
对于边界上的最优值要小心。如果在一个不好的范围搜索超参数,如果搜索到的值在边界上,那就很有可能错过了其它的好的搜索范围。
从粗到细地分阶段搜索。在实践中,先进行粗略范围搜索,然后根据好的结果出现的地方缩小范围进行搜索。粗略范围的时候搜索一下下就好,小范围的时候多搜索一会儿。
总结来说,训练一个神经网络需要:
利用小批量数据对实现进行梯度检查,注意梯度检查中的各种错误
进行合理性检查,确认初始损失值是合理的,在小数据集上能得到100%的准确率
在训练时,跟踪损失函数值,训练集和验证集准确率,还可以跟踪更新的参数数量相对于总参数的比例,然后如果对于卷积神经网络可以将第一层的权重可视化。
推荐的两个更新方法是SGD+Nestrov动量方法或Adam方法
随着训练进行学习率衰减
使用随机搜索来搜索最优的超参数,分阶段从粗到细来搜索。比较宽的超参数范围训练1-5个周期,窄范围训练很多个周期。
进行模型集成来获得额外的性能提高