我们常说调参,但具体调的是什么,在此做一份总结:
超参数是我们控制我们模型结构、功能、效率等的 调节旋钮,具体有哪些呢:
- 学习率
- epoch 迭代次数
- 隐藏层
- 激活函数
- batch size
- 优化器,如:Adam,SGD……
学习率 大 | 学习率 小 | |
学习速度 | 块 | 慢 |
使用时间点 | 刚开始训练时 | 一定epoch后 |
副作用 | 容易发生损失值爆炸, 结果容易震荡,不容易收敛 | 容易过拟合,收敛速度慢 |
学习率设置原则(在这主要以迁移学习为主):
由于模型已经在原始数据上收敛,所以应该设置较小学习率,在新数据上微调。若非迁移学习则先将学习率设置在0.01~0.001为宜,一定轮数之后再逐渐减缓,接近训练结束学习率的衰减应在100倍以上。
目标函数损失值 曲线(理想状态应该为绿色滑梯式下降曲线):
- 曲线 初始时 上扬 【红线】:
Solution:初始 学习率过大 导致 振荡,应减小学习率,并 从头 开始训练 。 - 曲线 初始时 强势下降 没多久 归于水平 【紫线】:
Solution:后期 学习率过大 导致 无法拟合,应减小学习率,并 重新训练 后几轮 。 - 曲线 全程缓慢 【黄线】:
Solution:初始 学习率过小 导致 收敛慢,应增大学习率,并 从头 开始训练 。
初始化
当用normal初始化cnn的参数时,最后acc只能到70%多,仅仅改成xavier,acc可以到98%。
还有一次给word embedding初始化,最开始使用了TensorFlow中默认的initializer(即glorot_uniform_initializer,也就是大家经常说的无脑使用xavier),训练速度慢不说,结果也不好。改为uniform,训练速度飙升,结果也飙升。
链接:https://www.zhihu.com/question/25097993/answer/127472322
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
一些大的注意事项:
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兜底, 全局信息都有.
- 预处理: -mean/std zero-center就够了, PCA, 白化什么的都用不上. 我个人观点, 反正CNN能学习encoder, PCA用不用其实关系不大, 大不了网络里面自己学习出来一个.
- shuffle, shuffle, shuffle.
- 网络原理的理解最重要, CNN的conv这块, 你得明白sobel算子的边界检测.
- Dropout, Dropout, Dropout(不仅仅可以防止过拟合, 其实这相当于做人力成本最低的Ensemble, 当然, 训练起来会比没有Dropout的要慢一点, 同时网络参数你最好相应加一点, 对, 这会再慢一点).
- CNN更加适合训练回答是否的问题, 如果任务比较复杂, 考虑先用分类任务训练一个模型再finetune.
- 无脑用ReLU(CV领域).
- 无脑用3×3.
- 无脑用xavier.
- LRN一类的, 其实可以不用. 不行可以再拿来试试看.
- filter数量2^n.
- 多尺度的图片输入(或者网络内部利用多尺度下的结果)有很好的提升效果.
- 第一层的filter, 数量不要太少. 否则根本学不出来(底层特征很重要).
- sgd adam 这些选择上, 看你个人选择. 一般对网络不是决定性的. 反正我无脑用sgd + momentum.
- batch normalization我一直没用, 虽然我知道这个很好, 我不用仅仅是因为我懒. 所以要鼓励使用batch normalization.
- 不要完全相信论文里面的东西. 结构什么的觉得可能有效果, 可以拿去试试.
- 你有95%概率不会使用超过40层的模型.
- shortcut的联接是有作用的.
- 暴力调参最可取, 毕竟, 自己的生命最重要. 你调完这个模型说不定过两天这模型就扔掉了.
- 机器, 机器, 机器.
- Google的inception论文, 结构要好好看看.
- 一些传统的方法, 要稍微了解了解. 我自己的程序就用过1×14的手写filter, 写过之后你看看inception里面的1×7, 7×1 就会会心一笑…
- ensemble:
- 将不同的经典网络提取出的特征向量,假设
VGG16
提取出的特征向量维度是[N,c1]
,ResNet50
提取的特征向量维度是[N,c2]
,Xception
提取的特征向量维度是[N, c3]
,那么我们可以使用三个系数a、b、c
将其组合为形状为[N, a*c1+b*c2+c*c3]
,其中a、b、c
三个参数的取值代表我们使用哪个模型的特征多一些,如果是分类回归比赛,我们在后面接特征处理网络就可以了。可以取不同的a、b、c
得到不同的特征,然后对结果做voting
,soft-voting
等多种处理,一般结果不会太差啦。 - 可以使用不同的初始化方式训练出模型,然后做ensemble。
- 可以使用用不同超参数(如学习率,
batch_size
,优化器)训练出不同模型,然后做ensemble。
为什么你的模型效果这么差?
为什么别人的模型都能快速达到较低的错误率,而你的模型错误率却居高不下。
造出这种现象的原因可以分为4大类:
1、模型实现中的bug:比如标签错误的问题。
2、超参数选择不合适:模型对超参数很敏感,学习率太高或太低都不行。
3、数据模型不适配:比如你要训练一个自动驾驶图像识别的模型,用ImageNet数据集来训练就不合适。
4、数据集的构造问题:没有足够数据、分类不均衡、有噪声的标签、训练集合测试集分布不同。
深度学习debug的流程策略
针对上面的问题,小哥总结出调试深度学习模型的第一要义——悲观主义。
既然消除模型中的错误很难,我们不如先从简单模型入手,然后逐渐增加模型的复杂度。
他把这个过程分为5个步骤:
- 从最简单模型入手;
- 成功搭建模型,重现结果;
- 分解偏差各项,逐步拟合数据;
- 用由粗到细随机搜索优化超参数;
- 如果欠拟合,就增大模型;如果过拟合,就添加数据或调整。
从简单模型开始
在这一步之前,假定你已经有了初始的测试集、需要改进的单一指标、基于某种标准的模型目标性能。
首先,选择一个简单的架构。比如,你的输入是图片就选择类似LeNet的架构,输入是语言序列就选择有一个隐藏层的LSTM。
模型推荐的默认设置:
- Adam优化器学习速率3e-4
- 激活函数选用ReLU或tanh
- ReLU初始化推荐使用He normal,tanh初始化推荐使用Glorot normal
为了简化问题,我们从一个只有1万样本的数据集开始训练,数据的特点包括:固定数量的目标、分类、更小的图片尺寸。由此创建一个简单的合成训练集。
开始搭建深度学习模型
在搭建模型之前,有(Implement)5种最常见的bug:
- 错误的张量形状;预处理输入错误;损失函数错误输入;忘记设置正确的训练模型;错误的数据类型。
- 为了防止这些错误发生,给出的建议是:尽可能减少代码的行数,使用现成的组件,然后再构建复杂的数据pipeline。
- 运行模型后,你可能会遇到形状不匹配、数据类型错误、内存不足等等问题。
- 对于第一个问题,可以在调试器中逐步完成模型创建和推理。数据类型错误是由于没有把其他类型数据转化成float32,内存不足是因为张量或者数据集太大。
评估
下面我们开始用错误率评估模型的性能。
测试集错误率 = 错误率下限 + 偏移 + 方差 + 分布偏差 + 验证集过拟合
为了处理训练集和测试集分布的偏差,我们使用两个验证数据集,一个样本来自训练集,一个样本来自测试集。
改进模型和数据
上一步中粗略搭建的模型错误率仍然相当高,我们应该如何改进?
让我们先用以下方法解决欠拟合的问题:
让模型更大(比如加入更多的层,每层中使用更多的单元);减少正规化;错误分析;选择另一种性能更好的模型架构;调节超参数;加入更多特征。
首先,我们给模型加入更多的层,转换到ResNet-101,调节学习率,使训练集错误率降低到0.8%。
在出现过拟合后,我们可以增加训练集的样本量解决这个问题,把图片数量扩大到25万张。
经历过优化参数、权重衰减、数据增强等一系列操作后,我们终于把测试错误率降低到目标值。
接下来我们着手解决训练集和测试集的分布偏差问题。
分析测试验证集错误率,收集或者合成更多训练数据弥补二者的偏差。比如下面的自动驾驶目标识别模型,训练完成后,让它判断图片里有没有人,常常发生错误。
经过分析得出,训练集缺乏夜晚场景、反光等情况。后续将在训练集中加入此类数据纠正偏差。
另一种修正错误率的方法称为领域适配,这是一种使用未标记或有限标记数据进行训练的技术。它能在源分布上进行训练,并将其推广到另一个“目标”。
超参数优化
这是调试的最后一步,我们需要选取那些更敏感的超参数,下图是模型对不同超参数的敏感性:
常用的超参数优
化方法有:手动优化、网格搜索、随机搜索、由粗到细、贝叶斯优化。
你可以手动优化超参数,但是耗时而且需要理解算法的细节。Josh推荐的方法是由粗到细的随机搜索、贝叶斯优化。
由粗到细的随机搜索可以缩小超高性能参数的范围,缺点是由一些手动的操作。贝叶斯优化是优化超参数最有效一种无需手动干涉的方式,具体操作请参考:
今天的文章调参_调参调的是什么参数分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/49461.html