关于训练神经网路的诸多技巧Tricks(彻底总结版)

欢迎访问Oldpan博客,分享人工智能有趣消息,持续酝酿深度学习质量文。

前言

不少人都说训练神经网络和炼金术师炼药的过程相像,难以破解其中的黑盒子。其实否则,在训练的时候咱们依然能够经过大量的技巧去最大化咱们的训练效果,从而帮助咱们的任务取得不错的精度,这些技巧是训练神经网络不可缺乏的一环。html

本文尽量说明训练过程当中所须要的各类小技巧,会有不完善的地方,限于篇幅每一个点不会说很细,可是这些观念是咱们都须要掌握的,牢记这几点,在训练神经网络的过程当中就能够驾轻就熟,让炼丹再也不没有头绪~git

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

避免overfitting

overfitting即过拟合,典型的表现为训练集损失远远小于验证集损失。而欠拟合则表现为训练集损失大于验
证集损失。github

咱们要清楚远远大于的概念,若是训练集损失只比验证集损失多一点点的话,同等数量级(例如0.8与0.9)这种状况下并非过拟合的表现。咱们通常遇到的过拟合应该是0.8(训练集损失)与2.0(验证集损失)这种不在一个量级的损失比。算法

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

dropout与overfitting的关系

Dropout相似于bagging ensemble减小variance。也就是投经过投票来减小可变性。一般咱们在全链接层部分使用dropout,在卷积层则不使用。但要声明,dropout并不适合全部的状况,请你们不要无脑上Dropoutbash

Dropout通常适合于全链接层部分,而卷积层因为其参数并非不少,因此不须要dropout,加上的话对模型的泛化能力并无太大的影响。以下图:网络

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

咱们通常在网络的最开始和结束的时候使用全链接层,而hidden layers则是网络中的卷积层。因此通常状况,在全链接层部分,采用较大几率的dropout而在卷积层采用低几率或者不采用dropout。app

进一步请看相关讨论机器学习

数据集是否损坏?

数据集的好坏是算法泛化好坏的一个很是重要的前提条件,咱们一般在构建深度学习的任务中,所获得的数据集通常不会是很是完美的(不管是本身搭建仍是利用他人的数据,在数据集量过大的时候,数据集中不免会有图像损坏或者错误的个例)。分布式

若是有损坏的图像,若是咱们不知情,通常来讲,在咱们使用代码读取的时候就会报错,举个例子:
raise IOError("image file is truncated) "ide

在Kaggle的一个比赛中就存在这样的状况,训练的数据中有10w+的图像数据,可是存在10余张的图像内容缺失(图像大小明显小于其余正常图像)或者直接被损坏没法读取。这个时候就须要咱们本身去手动编写代码将那些错误且没法参与训练的图像挑选出来。

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

那么若是正确过滤这些图像呢?

  • 找到损坏图像的特色,例如没法读取,编写程序去除没法读取的图像
  • 找到内容缺失的图像,这样的图像大小每每比普通图像小一些,经过过滤文件大小小于某一阈值去除

固然,数据集损坏的形式还有不少,须要咱们本身去发掘。在一开始获得数据集的时候最好不要直接开始训练,应该去仔细检查本身的数据集是否有问题,这样能够避免不少以后训练时须要的处理的麻烦。

难例挖掘 hard-negative-mining

在任何一个深度学习任务中,咱们都会遇到一些比较“棘手”的数据,这些数据相比较于其余的普通数据更难识别,这种特比容易识别错误的例子就称为hard-negative

举个栗子。

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

好比Kaggle比赛中的一个识别遥感图像中船只的任务,使用的图像集是从一张大的遥感图中裁剪出来的,每张图的大小为768*768,在简单地对图像进行分类时(仅仅分类图像中有无船只),在validation中发现最容易识别出错的图以下:

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

在观察到这些最难办的图像的特征后,咱们能够针对这些难办的图像采起一些方法来解决这些问题。咱们先用初始的正负样本(通常是正样本+与正样本同规模的负样本的一个子集)训练分类器, 而后再用训练出的分类器对样本进行分类, 把其中负样本中错误分类的那些样本(hard negative)放入负样本集合, 再继续训练分类器, 如此反复, 直到达到中止条件(好比分类器性能再也不提高)。也就是不停滴将困难样本拿去训练,让分类器更好地学习到难以学习的特征,简单来讲就是熟能生巧嘛。

而在fast-rcnn中,这个方法也被使用了:

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

在 Fast-RCNN 中将与 groud-truth 的 IoU 在 [0.1, 0.5) 之间的图像标记为负例,[0, 0.1)的example 用于hard negative mining.在训练时通常输入为N=2张图片, 选择128个RoI,即每张图片64个RoI。对于每张图片, 按照1:3的比例来抽取RoI, 抽取正负样本的比例为1:3,要在负例中抽取48个。

相关的两篇文章能够看一下

[17] P. Felzenszwalb, R. Girshick, D. McAllester, and D. Ramanan. Object detection with discriminatively trained part based models. TPAMI, 2010.
[37] K. Sung and T. Poggio. Example-based learning for viewbased human face detection. Technical Report A.I. Memo No. 1521, Massachussets Institute of Technology, 1994.
复制代码

关于学习率

寻找合适的学习率(learning rate)

学习率是一个很是很是重要的超参数,这个参数呢,面对不一样规模、不一样batch-size、不一样优化方式、不一样数据集,其最合适的值都是不肯定的,咱们没法光凭经验来准确地肯定lr的值,咱们惟一能够作的,就是在训练中不断寻找最合适当前状态的学习率。

好比下图利用fastai中的lr_find()函数寻找合适的学习率,根据下方的学习率-损失曲线获得此时合适的学习率为1e-2

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

若是想要了解更多,这里推荐一篇fastai首席设计师Sylvain Gugger的一篇博客:How Do You Find A Good Learning Rate
以及相关的论文Cyclical Learning Rates for Training Neural Networks

learning-rate与batch-size的关系

通常来讲,越大的batch-size使用越大的学习率。

原理很简单,越大的batch-size意味着咱们学习的时候,收敛方向的confidence越大,咱们前进的方向更加坚决,而小的batch-size则显得比较杂乱,毫无规律性,由于相比批次大的时候,批次小的状况下没法照顾到更多的状况,因此须要小的学习率来保证不至于出错。

能够看下图损失Loss学习率Lr的关系:

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》
《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

上图来源于这篇文章:Visualizing Learning rate vs Batch size

固然咱们也能够从上图中看出,当batchsize变大后,获得好的测试结果所能容许的lr范围在变小,也就是说,当batchsize很小时,比较容易找打一个合适的lr达到不错的结果,当batchsize变大后,可能须要精细地找一个合适的lr才能达到较好的结果,这也给实际的large batch分布式训练带来了困难。

因此说,在显存足够的条件下,最好采用较大的batch-size进行训练,找到合适的学习率后,能够加快收敛速度。另外,较大的batch-size能够避免batch normalization出现的一些小问题:github.com/pytorch/pyt…

更多相似的问题能够在知乎找到相关答案:www.zhihu.com/question/64…

差分学习率与迁移学习

首先说下迁移学习,迁移学习是一种很常见的深度学习技巧,咱们利用不少预训练的经典模型直接去训练咱们本身的任务。虽说领域不一样,可是在学习权重的广度方面,两个任务之间仍是有联系的。

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

由上图,咱们拿来model A训练好的模型权重去训练咱们本身的模型权重(Model B),其中,modelA多是ImageNet的预训练权重,而ModelB则是咱们本身想要用来识别猫和狗的预训练权重。

那么差分学习率和迁移学习有什么关系呢?咱们直接拿来其余任务的训练权重,在进行optimize的时候,如何选择适当的学习率是一个很重要的问题。

通常地,咱们设计的神经网络(以下图)通常分为三个部分,输入层,隐含层和输出层,随着层数的增长,神经网络学习到的特征越抽象。所以,下图中的卷积层和全链接层的学习率也应该设置的不同,通常来讲,卷积层设置的学习率应该更低一些,而全链接层的学习率能够适当提升。

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

这就是差分学习率的意思,在不一样的层设置不一样的学习率,能够提升神经网络的训练效果,具体的介绍能够查看下方的链接。

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

上面的示例图来自:towardsdatascience.com/transfer-le…

余弦退火(cosine annealing)和热重启的随机梯度降低

余弦就是相似于余弦函数的曲线,退火就是降低,余弦退火就是学习率相似余弦函数慢慢降低。

热重启就是在学习的过程当中,学习率慢慢降低而后忽然再回弹(重启)而后继续慢慢降低。

两个结合起来就是下方的学习率变化图:

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

更多详细的介绍能够查看知乎机器学习算法如何调参?这里有一份神经网络学习速率设置指南
以及相关论文SGDR: Stochastic Gradient Descent with Warm Restarts

权重初始化

权重初始化相比于其余的trick来讲在日常使用并非很频繁。

为何呢?

缘由很简单,由于大部分人使用的模型都是预训练模型,使用的权重都是在大型数据集上训练好的模型,固然不须要本身去初始化权重了。只有没有预训练模型的领域会本身初始化权重,或者在模型中去初始化神经网络最后那几个全链接层的权重。

那么你们喜欢用什么初始化权重算法?

固然是kaiming_normal或者xavier_normal

相关论文:
Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification
Understanding the difficulty of training deep feedforward neural networks

多尺度训练

多尺度训练是一种直接有效的方法,经过输入不一样尺度的图像数据集,由于神经网络卷积池化的特殊性,这样可让神经网络充分地学习不一样分辨率下图像的特征,能够提升机器学习的性能。

也能够用来处理过拟合效应,在图像数据集不是特别充足的状况下,能够先训练小尺寸图像,而后增大尺寸并再次训练相同模型,这样的思想在Yolo-v2的论文中也提到过:

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

须要注意的是:多尺度训练并非适合全部的深度学习应用,多尺度训练能够算是特殊的数据加强方法,在图像大小这一块作了调整。若是有可能最好利用可视化代码将多尺度后的图像近距离观察一下,看看多尺度会对图像的总体信息有没有影响,若是对图像信息有影响的话,这样直接训练的话会误导算法致使得不到应有的结果。

关于优化算法

按理说不一样的优化算法适合于不一样的任务,不过咱们大多数采用的优化算法仍是是adamSGD+monmentum

这两个为何好用?

经验呗~

尝试过拟合一个小数据集。

这是一个经典的小trick了,可是不少人并不这样作,能够尝试一下。

关闭正则化/随机失活/数据扩充,使用训练集的一小部分,让神经网络训练几个周期。确保能够实现零损失,若是没有,那么极可能什么地方出错了。

Cross Validation 交叉验证

在李航的统计学方法中说到,交叉验证每每是对实际应用中数据不充足而采用的,基本目的就是重复使用数据。在日常中咱们将全部的数据分为训练集和验证集就已是简单的交叉验证了,能够称为1折交叉验证。注意,交叉验证和测试集不要紧,测试集是用来衡量咱们的算法标准的,不参与到交叉验证中来。

交叉验证只针对训练集和验证集。

交叉验证是Kaggle比赛中特别推崇的一种技巧,咱们常用的是5-折(5-fold)交叉验证,将训练集分红5份,随机挑一份作验证集其他为训练集,循环5次,这种比较常见计算量也不是很大。还有一种叫作leave-one-out cross validation留一交叉验证,这种交叉验证就是n-折交叉,n表示数据集的容量,这种方法只适合数据量比较小的状况,计算量很是大的状况不多用到这种方法。

吴恩达有一节课The nuts and bolts of building applications using deep learning中也提到了。

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

关于数据集

若是数据集极其不平衡,假如咱们有个检测船只的任务,在100000图中只有30000张图中含有船只,其他图像都是不含船只的图像,这时候若是对此直接进行训练效果应该会不好。为此,首先能够挑选出只有船只的图像集合进行初步训练。其次,使用训练好的模型去检测没有训练的部分(不含船只),挑选出检测失败的false positive(也就是在没有船的图像集中检测出船只了)加入以前的训练集再次进行训练。

数据加强

数据集加强是一个老生常谈的话题了,咱们为何须要那么多数据?为何须要数据加强技术?
能够看这篇文章来了解一下:深度学习为何须要那么多的数据?

这里只简单说下咱们经常使用的数据加强的Transform
大部分咱们使用的图像加强技术通常是随机旋转,水平翻转,高斯模糊和尺度变化还有什么拉伸等blabla的操做。这些图像变化对大部分的任务是比较适合的,但针对特定的任务,存在某一簇特殊的图像加强技术能够达到比普通图像加强技术更好的效果。

例如夜视图或者光照:

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

但也须要提个醒,并非全部的图像加强均可以提高模型的泛化能力

并且有些图像加强技术会对原始图像形成损失从而致使神经网络学习到错误的信息,这点是咱们比较容易忽视的问题,一样重要,相关内容能够查看fastai中的图像加强技术为何相对比较好

TTA(Test Time Augmentation)

最初这个概念是在fastai课程中看到的,这个过程在训练阶段不会参与,是经过在验证和测试阶段进行的。具体过程是,对所要处理的图像进行几种随机的图像加强变化,而后对每种图像加强后的图像进行预测,对预测结果取平均值。

原理相似于模型平均,牺牲推断速度来实现推断精度的提高。

《关于训练神经网路的诸多技巧Tricks(彻底总结版)》

固然,这个技术也有好有坏,在我本身跑的卫星图数据集中采用TTA的精确度比不采用低了0.03个百分点。

结语

大概先说这么多,训练神经网络真的很像炼丹,而咱们全部使用的技巧tricks,也只是增长一些炼丹的成功率,而究竟炼丹能不能成功,最终仍是要取决于咱们设计的算法合不合理。

参考文章:

www.cnblogs.com/nowgood/p/H…
towardsdatascience.com/kaggle-plan…

文章来源于OLDPAN博客,欢迎来访:Oldpan博客

欢迎关注Oldpan博客公众号,持续酝酿深度学习质量文:

相关文章
相关标签/搜索