调参就是trial-and-error. 没有其他捷径可以走. 唯一的区别是有些人盲目的尝试, 有些人思考后再尝试. 快速尝试, 快速纠错这是调参的关键.
这是一个很好的链接, 说明了如何从零开始不断的trial-and-error(其实这里面没遇到什么error):
Using convolutional neural nets to detect facial keypoints tutorial
========================================================
基本原则:
快速试错
一些大的注意事项:
1. 刚开始, 先上小规模数据, 模型往大了放, 只要不爆显存, 能用256个filter你就别用128个. 直接奔着过拟合去. 没错, 就是训练过拟合网络, 连测试集验证集这些都可以不用.
为什么?
+ 你要验证自己的训练脚本的流程对不对. 这一步小数据量, 生成速度快, 但是所有的脚本都是和未来大规模训练一致的(除了少跑点循环)
+ 如果小数据量下, 你这么粗暴的大网络奔着过拟合去都没效果. 那么, 你要开始反思自己了, 模型的输入输出是不是有问题? 要不要检查自己的代码(永远不要怀疑工具库, 除非你动过代码)? 模型解决的问题定义是不是有问题? 你对应用场景的理解是不是有错? 不要怀疑NN的能力, 不要怀疑NN的能力, 不要怀疑NN的能力. 就我们调参狗能遇到的问题, NN没法拟合的, 这概率是有多小?
+ 你可以不这么做, 但是等你数据准备了两天, 结果发现有问题要重新生成的时候, 你这周时间就酱油了.
2. Loss设计要合理.
+ 一般来说分类就是Softmax, 回归就是L2的loss. 但是要注意loss的错误范围(主要是回归), 你预测一个label是10000的值, 模型输出0, 你算算这loss多大, 这还是单变量的情况下. 一般结果都是nan. 所以不仅仅输入要做normalization, 输出也要这么弄.
+ 多任务情况下, 各loss想法限制在一个量级上, 或者最终限制在一个量级上, 初期可以着重一个任务的loss。
3. 观察loss胜于观察准确率
准确率虽然是评测指标, 但是训练过程中还是要注意loss的. 你会发现有些情况下, 准确率是突变的, 原来一直是0, 可能保持上千迭代, 然后突然变1. 要是因为这个你提前中断训练了, 只有老天替你惋惜了. 而loss是不会有这么诡异的情况发生的, 毕竟优化目标是loss.
给NN一点时间, 要根据任务留给NN的学习一定空间. 不能说前面一段时间没起色就不管了. 有些情况下就是前面一段时间看不出起色, 然后开始稳定学习.
4. 确认分类网络学习充分
分类网络就是学习类别之间的界限. 你会发现, 网络就是慢慢的从类别模糊到类别清晰的. 怎么发现? 看Softmax输出的概率的分布. 如果是二分类, 你会发现, 刚开始的网络预测都是在0.5上下, 很模糊. 随着学习过程, 网络预测会慢慢的移动到0,1这种极值附近. 所以, 如果你的网络预测分布靠中间, 再学习学习.
5. Learning Rate设置合理
+ 太大: loss爆炸, 或者nan
+ 太小: 半天loss没反映(但是, LR需要降低的情况也是这样, 这里可视化网络中间结果, 不是weights, 有效果, 俩者可视化结果是不一样的, 太小的话中间结果有点水波纹或者噪点的样子, 因为filter学习太慢的原因, 试过就会知道很明显)
+ 需要进一步降低了: loss在当前LR下一路降了下来, 但是半天不再降了.
+ 如果有个复杂点的任务, 刚开始, 是需要人肉盯着调LR的. 后面熟悉这个任务网络学习的特性后, 可以扔一边跑去了.
+ 如果上面的Loss设计那块你没法合理, 初始情况下容易爆, 先上一个小LR保证不爆, 等loss降下来了, 再慢慢升LR, 之后当然还会慢慢再降LR, 虽然这很蛋疼.
+ LR在可以工作的最大值下往小收一收, 免得ReLU把神经元弄死了. 当然, 我是个心急的人, 总爱设个大点的.
6 对比训练集和验证集的loss
判断过拟合, 训练是否足够, 是否需要early stop的依据, 这都是中规中矩的原则, 不多说了.
7 清楚receptive field的大小
CV的任务, context window是很重要的. 所以你对自己模型的receptive field的大小要心中有数. 这个对效果的影响还是很显著的. 特别是用FCN, 大目标需要很大的receptive field. 不像有fully connection的网络, 好歹有个fc兜底, 全局信息都有.
(人是大目标,关节点是吗???)
简短的注意事项:
因为优化问题到底是什么取决于模型+数据。对于不同的优化问题可能不同的求解器的结果都不一样。adam 的主要作用是自适应梯度值。如果数据集巨大,每个类里都有很大的in-class diversity的话可能会对同一个label 得到较大的loss,这时候adam会有优势。如果模型和数据都不是特别大,SGD+moment会有更好的效果。哈哈,调参没有万金油。
我只对卷积网络有一点点了解,所以接下来谈的都是和卷积网络相关的内容。
调参请在验证集上!调参请在验证集上!调参请在验证集上!(水论文会得高分)
首先我们假设我们手上有一个正确的,没有bug,可以训练的模型,以及预先设立的误差目标。那么分三种情况:
1、模型表现非常好,在训练集和验证集上都满足我们的目标。那不用调了。
2、模型在训练集上的误差很小,且各种(softmax 等等) loss 能减小到一个很小的值(对于我自己而言小于0.01),但是验证集的 loss 相对较大(对我的问题而言,一般会在0.3~0.6)。那就是过拟合了。
3、在训练集和验证集上的loss都比较大,都大于0.3,那可能就是欠拟合了。
——————————————————————————————————————————
模型的训练是在拟合训练集的规律,模型的使用却是将规律作用于测试集。那么我们假设训练集和测试集所包含的规律是大方向相同的,小细节存在差异的。
如果一个模型在训练集上一直一直训练下去,那么它会很好的拟合训练集所有的大方向规律和小细节规律,过拟合就是必然的了。因为训练的目标是将训练集 loss 降到 0。理想的训练过程如图:
我们假设模型在验证集的表现由两部分组成:1、对训练集规律的掌握(主要指标 trainset loss),2、学习结果对训练集的适应程度(主要指标 validation set loss)。如上图所示,调参的本质就是要找到那个best model 平衡点。
——————————————————————————————————————————
出现上述情况该调什么?调试hyperparameters 的先后顺序是什么?
1、优先调 learning rate!优先调 learning rate!优先调 learning rate!
学习速率会很大程度上影响模型的表现。同样的模型采用不同的learning rate 可能会表现迥异。所以凭感觉建好一个模型后如果对表现不满意应该优先调学习速率。我前段时间在知乎上看一个哥们说学习速率可以有解析解,希望他早日成功拯救我脱离调学习速率的苦海。模型具有理论容量和有效容量两种能力指标,理论容量是由卷积核数量,模型深度等决定的。但是有效容量会受学习速率影响。
2、加 Dropout, 加 BN, 加Data augmentation
一般而言,在设计模型之初我们都信奉大力出奇迹。模型尽量深,卷积核尽量多,强行让模型拟合训练集。这时容易遇到的问题就是过拟合。解决过拟合的第一要素是模型的正则化,最有效方法是加大训练数据集。如果有钱任性,那请多标记数据。如果没钱要认命(比如我),那就给训练数据加增强,什么图像裁剪,对称变换,旋转平移,都可以让模型在验证集上的表现更好。此外,增加常用的正则化也可以提升模型的表现。
3、调模型的层数和卷积核数量
走到这一步的时候都是迫不得已了。这两个参数都是对模型理论容量具有巨大影响的参数,一旦调整了之后所有东西都要重新调。增大模型的层数和卷积核的数量都会提升模型的容量。不同的是,增大模型层数(让模型变高)可以让模型获得更好的非线性,模型容量指数增加,缺点是加大层数会让模型更难训练,面临梯度消失的风险,引入死单元。增加卷积核(让模型变胖)可以在不引入训练困难的情况下让模型更好的拟合训练集,也就是降低 training loss,但是会更容易过拟合。
总之,理想情况下表现优越的模型一般长的高高瘦瘦(深,每层卷积核不多),但是为了便于我们训练,有时候不得不让他更矮壮一些。模型的调参除了学习速率和正则化这些比较耗时的工作外,还需要一些灵感,来确定模型的身材。
努力多调吧,你在训练模型的时候它也在训练你。
2.理解NN,可视化之类 - 杨军的回答 - 知乎 https://www.zhihu.com/question/25097993/answer/127374415