@TOP神经网络训练步骤
总结源于:troubleshooting deep neural networks
1. 确定一个简单的模型
选择一个简单的架构、使用Adam且无正则化、归一化输入、用来解决简单的问题(原问题数据集的子集)
2. 实现算法
v1版中,写尽量少行数的代码,不要超过200行;尽量调用api,而非自己写函数实现;先用于解决一个小的数据集上的问题
2.1 让模型跑起来
注意数据的shape、维数(特别是有的某一维是1)、精度(存储和使用的格式很可能不一样)、范围,可通过可视化每一步操作来解决;减少占用内存的操作.
numpy默认是float64,而一般DL使用float32;图像默认是uint8,需要转为float32.
自己导入数据时,尤其要注意这点!
注意:Batch size是否太大;FCN是否太大;是否往内存导入了过多数据,可考虑将数据按顺序输入内存;为数据集分配的缓冲区是否过大;同个session中是否创建了多个模型,这可能会导致内存泄漏;重复创建一个操作;GPU是否正在跑其他程序.
是否忘记初始化变量;忘记在batch norm中关掉bias;获得的参数无效/空
2.2 对单个batch拟合
error上升:loss function或者gradient的符号反了;学习率过高;softmax在错误的维度上求和;
error爆炸式上涨:数值错误(检查exp、log、除法操作的输出结果);学习率过高;
error震荡:数据或label被污染了(未归一化、不正确的打乱顺序);学习率过高;
error陷入高原:学习率过低;梯度没有很好的在整个模型中传递(梯度消失);正则化过重了;loss function输入了不正确的数据;数据或label被污染了
2.3与一个已知结果作对比
将官方模型在与我相似的dataset上进行评估:一行一行地检查,以确定我能够得到相同的输出;确保我的模型能够达到预期目标;
将官方模型在benchmark上评估(e.g. MNIST):一行一行地检查,以确保我能得到相同的输出;
与非官方的模型进行对比:同上,只是confidence相对较低;
与不提供源码的论文结果对比:确保我的模型能达到预期目标;
与我的模型在benchmark上的结果对比:确保我的模型在简单设置后效果好;
与相似的模型在相似的数据集上的结果对比:明白大致能够获得怎样的性能;
3. 模型评估
画出:Human level performance、Train error、Val error、Test error四根曲线;
Test error = Val error + Val set overfitting
Val error = Train error + Variance(overfitting)
Train error = Human level performance + Avoidable bias(underfitting)
然后根据过拟合和欠拟合的程度,进行调整模型
当train set 和 test set的分布不同时:使用两个val set,一个从train set采样,一个从test set采样
4. 改进模型
处理欠拟合(按顺序):把模型变大(加layer、每层的units增多)、减少正则化、分析Error来源;选择另一个模型架构(选更state-of-the-art的);调节超参数(e.g. 学习率);增加features
处理过拟合(按顺序):增加更多数据(如果可以的话);增加正则化(batch norm;layer norm);数据增广;增加正则化程度(Dropout、L2、weight decay);分析Error来源;选择另一个模型架构(更state-of-the-art的);调节超参数;(Early stopping;移除一些features;减小模型size;最后这三种不推荐)
处理train set和test set的分布不同(按顺序):分析test error和val error(e.g. 很难看见行人;反光、夜景),并收集更多数据;分析test error和val error,并合成更多数据;使用domain自适应技术(当target domain的数据有限时:finetune一个预训练好的模型、把这些数据加入train set;当target domain有大量的无标签数据时:Correlation Alignment、Domain confusion、CycleGAN)
重新平衡数据集(如果有用的话):(此时val的效果远好于test的效果,通常此时val set的数据很少,或需要调节的超参数很多时使用)需要收集更多的val data。
5. 调节超参数
NN:ResNet这种架构?多少层?权重如何初始化?Kernel size?等
优化器:Adam这种方法?Batch size?Learning rate?beta1?beta2?epsilon?等
正则化:。。。等
模型对参数的敏感程度:
高度敏感:学习率、损失函数、网络的大小
中度敏感:初始化的权重、模型深度、每一层的size、正则化的权重
低敏感:优化方式、优化参数、Batch Size、非线性性
超参数调节方法:
法1:人工调节:优点:对有经验的人来说计算少;缺点:需要对算法很了解、会猜测参数、比较耗时
法2:Grid Search:优点:简单、能得到好的结果;缺点:非常耗时、需要一定先验知识;
法3:随机搜索
法4:由粗糙到细致的搜索:优点:计算量小,实际中最常用;缺点:需要人工进行;
法5:贝叶斯参数优化:基于先验知识去估计一些点,建立每组超参数对应的性能与概率的模型(即基于已经测试过的点拟合性能与超参数的曲线,越靠近已经测试过的点,曲线的可信度越高;每次训练时,使用曲线上最能提升性能的那一组超参数,并用训练结果来更新曲线和可信度模型)。优点:很有效率,可以不用人来控制;缺点:不易进行曲线的拟合;难以程序化,且没有现成的工具
效果不好的原因:
实现起来有bug
超参数没选好
模型和数据的匹配程度
数据集没处理好(没有足够多的数据、类别不平衡、噪声数据、训练集和测试集不同分布)
一些建议:
使用Adam optimizer(在TensorFlow中,如果要保存或者载入权重,记得在AdamOptimizer后使用Saver)
使用ReLU
不要在output层后加了激活函数(一定确保关闭了output layer的激活函数)
每一层都加上bias(有BN层的除外)
使用variance-scaled初始化(在TensorFlow中为:tf.contrib.layers.variance_scaling_initializer())
白化(归一化)输入数据
卷积层有64个或128个filters,一般来说已经足够了
池化具有变化不变性(池化操作让网络学得更佳整体的idea,使得CNN对平移、旋转、尺度缩放更加鲁棒)