未阅读:
https://www.zhihu.com/question/29641737
A Good Start:
- 将各个参数的设置部分集中在一起。如果参数的设置分布在代码的各个地方,那么修改的过程想必会非常痛苦。
- 可以输出模型的损失函数值以及训练集和验证集上的准确率。
- 可以考虑设计一个子程序,可以根据给定的参数,启动训练并监控和周期性保存评估结果。再由一个主程序,分配参数以及并行启动一系列子程序。
- 画图:一般是训练数据遍历一轮以后,就输出一下训练集和验证集准确率。这样训练一段时间以后,如果模型一直没有收敛,那么就可以停止训练,尝试其他参数了,以节省时间。
如果训练到最后,训练集,测试集准确率都很低,那么说明模型有可能欠拟合。那么后续调节参数方向,就是增强模型的拟合能力。例如增加网络层数,增加节点数,减少dropout值,减少L2正则值等等。
如果训练集准确率较高,测试集准确率比较低,那么模型有可能过拟合,这个时候就需要向提高模型泛化能力的方向,调节参数。 - 分阶段调参:实践中,一般先进行初步范围搜索,然后根据好结果出现的地方,再缩小范围进行更精细的搜索。
建议先参考相关论文,以论文中给出的参数作为初始参数。至少论文中的参数,是个不差的结果。
如果找不到参考,那么只能自己尝试了。可以先从比较重要,对实验结果影响比较大的参数开始,同时固定其他参数,得到一个差不多的结果以后,在这个结果的基础上,再调其他参数。例如学习率一般就比正则值,dropout值重要的话,学习率设置的不合适,不仅结果可能变差,模型甚至会无法收敛。
如果实在找不到一组参数,可以让模型收敛。那么就需要检查,是不是其他地方出了问题,例如模型实现,数据等等。可以参考我写的深度学习网络调试技巧
样本数据:
1、样本要足够随机,防止大数据淹没小数据
2、样本要做归一化
3、正负样本比例: 这个是非常忽视,但是在很多分类问题上,又非常重要的参数。很多人往往习惯使用训练数据中默认的正负类别比例,当训练数据非常不平衡的时候,模型很有可能会偏向数目较大的类别,从而影响最终训练结果。除了尝试训练数据默认的正负类别比例之外,建议对数目较小的样本做过采样,例如进行复制。提高他们的比例,看看效果如何,这个对多分类问题同样适用。
在使用mini-batch方法进行训练的时候,尽量让一个batch内,各类别的比例平衡,这个在图像识别等多分类任务上非常重要。
4、数据增加(Data augmentation):使用算法来增加训练实例数量是个有创意的做法。如果是图像,那么应该转换和旋转它们;
eg:
zero-center ,这个挺常用的.
X -= np.mean(X, axis = 0) # zero-center
X /= np.std(X, axis = 0) # normalize
PCA whitening,这个用的比较少.
初始化:
1、初始化参数尽量小一些,这样 softmax 的回归输出更加接近均匀分布,使得刚开始网络并不确信数据属于哪一类
;另一方面从数值优化上看我们希望我们的参数具有一致的方差(一致的数量级),这样我们的梯度下降法下降也
会更快。同时为了使每一层的激励值保持一定的方差,我们在初始化参数(不包括偏置项)的方差可以与输入神经
元的平方根成反比
2、权值初始化(Weight Initialization):
可用高斯分布乘上一个很小的数。如果想偷懒,不妨试试0.02*randn(num_params)。这个范围的值在许多不同的问题
上工作得很好。当然,更小(或更大)的值也值得一试。如果它工作得不好,那么使用
init_scale/sqrt(layer_width)*randn来初始化每个权值矩阵。这种情况下,init_scale应该设置为0.1或者1,或者类似的值
eg:
uniform
W = np.random.uniform(low=-scale, high=scale, size=shape)
glorot_uniform
scale = np.sqrt(6. / (shape[0] + shape[1]))
np.random.uniform(low=-scale, high=scale, size=shape)
高斯初始化:
w = np.random.randn(n) / sqrt(n),n为参数数目
激活函数为relu的话,推荐
w = np.random.randn(n) * sqrt(2.0/n)
svd ,对RNN效果比较好,可以有效提高收敛速度.
自动调参
自动调参当前也有不少研究。下面介绍几种比较实用的办法:
- Gird Search. 这个是最常见的。具体说,就是每种参数确定好几个要尝试的值,然后像一个网格一样,把所有参数值的组合遍历一下。优点是实现简单暴力,如果能全部遍历的话,结果比较可靠。缺点是太费时间了,特别像神经网络,一般尝试不了太多的参数组合。
- Random Search。Bengio在Random Search for Hyper-Parameter Optimization中指出,Random Search比Gird Search更有效。实际操作的时候,一般也是先用Gird Search的方法,得到所有候选参数,然后每次从中随机选择进行训练。
- Bayesian Optimization. 贝叶斯优化,考虑到了不同参数对应的实验结果值,因此更节省时间。具体原理可以参考这个论文: Practical Bayesian Optimization of Machine Learning Algorithms ,这里同时推荐两个实现了贝叶斯调参的Python库,可以上手即用:
- jaberg/hyperopt, 比较简单。
- fmfn/BayesianOptimization, 比较复杂,支持并行调参。
batchsize:
batch几百到几千是比较合适的(很大数据量的情况下),无论是cnn还是rnn,batch normalization都有用。batch size: 128上下开始。batch size值增加,的确能提高训练速 度。但是有可能收敛结果变差。如果显存大小允许,可以考虑从一个比较大的值开始尝试。因为batch size太大,一般不会对结果有太大的影响,而batch size太小的话,结果 有可能很差。
目的:在内存效率和内存容量之间寻找最佳平衡
1、决定一次训练的样本数目。
2、影响到模型的优化程度和速度。
batch = n
如果数据集比较小我们就采用全数据集。全数据集确定的方向能够更好地代表样本总体,从而更准确地朝向极值所在
的方向。
注:对于大的数据集我们不能使用全批次,因为会得到更差的结果。
batch=k(1<k<n)
选择一个适中的 Batch_Size 值,将会以batch的大小将数据输入深度学习的网络中,然后计算这个batch的所有样本的平均
损失,即代价函数是所有样
本的平均。
batch=1
每次修正方向以各自样本的梯度方向修正,横冲直撞各自为政,难以达到收敛。
适当的增加Batchsize的优点:
1.通过并行化提高内存利用率。
2.单次epoch的迭代次数减少,提高运行速度。(单次epoch=(全部训练样本/batchsize)/ iteration =1)
3.适当的增加Batch_Size,梯度下降方向准确度增加,训练震动的幅度减小。
经验总结:
相对于正常数据集,如果Batch_Size过小,训练数据就会非常难收敛,从而导致underfitting。
增大Batch_Size,相对处理速度加快。
增大Batch_Size,所需内存容量增加(epoch的次数需要增加以达到最好结果)。
这里我们发现上面两个矛盾的问题,因为当epoch增加以后同样也会导致耗时增加从而速度下降。因此我们需要寻找最好的batch_size。
clip c(梯度裁剪):
限制最大梯度,其实是value = sqrt(w1^2+w2^2….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15
Iterator
1、神经网络中我们希望通过迭代进行多次的训练以到达所需的目标或结果。每一次迭代得到的结果都会被作为下一次迭代的初始值。
2、一个迭代 = 一个正向通过+一个反向通过
epoch
一个时期 = 所有训练样本的一个正向传递和一个反向传递。一般设置几次到几百次。
激活函数:
1、激活函数要视样本输入选择
2、激活函数我们现在基本上都是采用Relu,我们在初始化偏置项时,为了避免过多的死亡节点(激活值为0)一般可以初始化为一个较
小的正值。
3、隐藏层的激活函数,tanh往往比sigmoid表现更好
学习率(Leraning Rate)
1、学习率
2、学习率一般要随着训练进行衰减。衰减系数一般是0.5。 衰减时机,可以是验证集准确率不再上升时,或固定训练多少个周期以后。
3、不过更建议使用自适应梯度的办法,例如adam,adadelta,rmsprop等,这些一般使用相关论文提供的默认值即可,可以避免再费劲调节学习率。对RNN来说,有个经验,如果RNN要处理的序列比较长,或者RNN层数比较多,那么learning rate一般小一些比较好,否则有可能出现结果不收敛,甚至Nan等问题。
loss不降了lr就除10
momentum
1、滑动平均模型,在训练的过程中不断的对参数求滑动平均这样能够更有效的保持稳定性,使其对当前参数更新不敏
感。例如加动量项的随机梯度下降法就是在学习率上应用滑动平均模型。
2、一般我们会选择0.9-0.95之间
weight decay
我们一般会选择0.005,
filter
个数为奇数
dropout
1、现在也是标配的存在,在测试时不要忘记关闭dropout,然后对权值求乘积(也就是1-dropout率)。当然,要确保将
网络训练得更久一点。不同于普通训练,在进入深入训练之后,验证错误通常会有所增加。dropout网络会随着时间推
移而工作得越来越好,所以耐心是关键。
2、dropout: 0.5
改进优化算法:
基于随机梯度下降的改进优化算法有很多种,在不熟悉调参的情况,建议使用Adam方法
训练过程:
0、训练过程不仅要观察训练集和测试集的loss是否下降、正确率是否提高,对于参数以及激活值的分布情况也要及时观察,要有一定的波动。
- 要做梯度归一化,即算出来的梯度除以minibatch size
- clip c(梯度裁剪): 限制最大梯度,其实是value = sqrt(w1^2+w2^2….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15
- dropout对小数据防止过拟合有很好的效果,值一般设为0.5,小数据上dropout+sgd效果更好. dropout的位置比较有讲究, 对于RNN,建议放到输入->RNN与RNN->输出的位置.关于RNN如何用dropout,可以参考这篇论文:arxiv.org/abs/1409.2329
- adam,adadelta等,在小数据上,我这里实验的效果不如sgd,如果使用sgd的话,可以选择从1.0或者0.1的学习率开始,隔一段时间,在验证集上检查一下,如果cost没有下降,就对学习率减半. 我看过很多论文都这么搞,我自己实验的结果也很好. 当然,也可以先用ada系列先跑,最后快收敛的时候,更换成sgd继续训练.同样也会有提升.
- 除了gate之类的地方,需要把输出限制成0-1之外,尽量不要用sigmoid,可以用tanh或者relu之类的激活函数.
- rnn的dim和embdding size,一般从128上下开始调整. batch size,一般从128左右开始调整.batch size合适最重要,并不是越大越好.
- word2vec初始化,在小数据上,不仅可以有效提高收敛速度,也可以可以提高结果.
- 尽量对数据做shuffle
- LSTM 的forget gate的bias,用1.0或者更大的值做初始化,可以取得更好的结果。
微调fintuning:
fine-tuning的时候,可以把新加层的学习率调高,重用层的学习率可以设置的相对较低
*--------------------------------------------------------------------------------------------------------------------------------------
Q1、检测自己的数据是否存在可以学习的信息
Q2、数据集中的数值是否泛化(防止过大或过小的数值破坏学习)。
如果是错误的数据则你需要去再次获得正确的数据,如果是数据的数值异常我们可以使用zscore函数来解决这个问题,如果是网络的错误,则希望调
整网络,包括:网络深度,非线性程度,分类器的种类等等。
underfitting:
增加网络的复杂度(深度),
降低learning rate,
优化数据集,
增加网络的非线性度(ReLu),
采用batch normalization,
overfitting:
丰富数据,
增加网络的稀疏度,
降低网络的复杂度(深度),
L1 regularization,
L2 regulariztion,:1.0,超过10的很少见
添加Dropout,
Early stopping--看到我们在验证集的上的正确率开始下降就停止训练
适当降低Learning rate,
适当减少epoch的次数,
调整方法就是保持其他参数不变,只调整一个参数。
learning rate,
minibatch size,
epoch,
filter size,
number of filter
4、其他
梯度检验:当我们的算法在训练出现问题而进行debug时,可以考虑使用近似的数值梯度和计算的梯度作比较检验梯度是否计算正确。
*------------------------------------------------------------------------------------------------------------------------------------
1. 完全不收敛:
2. 部分收敛:
3. 全部收敛:
CNN中的独有技巧:
- CNN中将一个大尺寸的卷积核可以分解为多层的小尺寸卷积核或者分成多层的一维卷积。这样能够减少参数增加非线性
- CNN中的网络设计应该是逐渐减小图像尺寸,同时增加通道数,让空间信息转化为高阶抽象的特征信息。
- CNN中可以利用Inception方法来提取不同抽象程度的高阶特征,用ResNet的思想来加深网络的层数。
- CNN处理图像时,常常会对原图进行旋转、裁剪、亮度、色度、饱和度等变化以增大数据集增加鲁棒性。
Ensemble:深度学习中一般有以下几种方式
- 同样的参数,不同的初始化方式
- 不同的参数,通过cross-validation,选取最好的几组
- 同样的参数,模型训练的不同阶段
- 不同的模型,进行线性融合. 例如RNN和传统模型
我的一个cfg文件:
batch=64 每batch个样本更新一次参数。
subdivisions=8 如果内存不够大,将batch分割为subdivisions个子batch,每个子batch的大小
momentum=0.9 动量
decay=0.0005 权重衰减正则项,防止过拟合
angle=0 通过旋转角度来生成更多训练样本
saturation = 1.5 通过调整饱和度来生成更多训练样本
exposure = 1.5 通过调整曝光量来生成更多训练样本
hue=.1 通过调整色调来生成更多训练样本
learning_rate=0.0001 初始学习率
max_batches = 45000 训练达到max_batches后停止学习
policy=steps 调整学习率的policy,有如下policy:CONSTANT, STEP, EXP, POLY, STEPS,
SIG, RANDOM
steps=100,25000,35000 根据batch_num调整学习率
scales=10,.1,.1 学习率变化的比例,累计相乘
batch_normalize=1 是否做BN
filters=32 输出多少个特征图
size=3 卷积核的尺寸
stride=1 做卷积运算的步长
pad=1 如果pad为0,padding由 padding参数指定。如果pad为1,padding大小为size/2
activation=leaky 激活函数:logistic,loggy,relu,elu,relie,plse,hardtan,lhtan,linear,ramp,leaky,tanh,stair
[maxpool]
size=2 池化层尺寸
stride=2 池化步进
......
#######
[route] 从网络的前几层获取细粒度特征
layers=-9
[reorg] passthrougth layer: 使得这些特征和后面特征图的大小匹配r
stride=2
[route]
layers=-1,-3 route层起连接作用,reorg层来match特征图尺寸。
...
[convolutional]
size=1
stride=1
pad=1
filters=125 region前最后一个卷积层的filters数是特定的,计算公式为filter=num*(classes+5)
5的意义是5个坐标,论文中的tx,ty,tw,th,to
activation=linear
[region]
anchors = 1.08,1.19, 3.42,4.41, 6.63,11.38, 9.42,5.11, 16.62,10.52 预选框,可以手工挑选,也可以通过k means 从训练样本中学出
bias_match=1
classes=20 网络需要识别的物体种类数
coords=4 每个box的4个坐标tx,ty,tw,th
num=5 每个grid cell预测几个box,和anchors的数量一致。当想要使用更多anchors时需要调大num,且如果调大num后训练时Obj趋近0的话可以尝试调大object_scale
softmax=1 使用softmax做激活函数
jitter=.2 通过抖动增加噪声来抑制过拟合
rescore=1 暂理解为一个开关,非0时通过重打分来调整l.delta(预测值与真实值的差)
object_scale=5 栅格中有物体时,bbox的confidence loss对总loss计算贡献的权重
noobject_scale=1 栅格中没有物体时,bbox的confidence loss对总loss计算贡献的权重
class_scale=1 类别loss对总loss计算贡献的权重
coord_scale=1 bbox坐标预测loss对总loss计算贡献的权重
absolute=1
thresh = .6
random=0 random为1时会启用Multi-Scale Training,随机使用不同尺寸的图片进行训练。
牛人总结综合:
1:准备数据:务必保证有大量、高质量并且带有干净标签的数据,没有如此的数据,学习是不可能的
2:预处理:这个不多说,就是0均值和1方差化
3:minibatch:建议值128,1最好,但是效率不高,但是千万不要用过大的数值,否则很容易过拟合
4:梯度归一化:其实就是计算出来梯度之后,要除以minibatch的数量。这个不多解释
5:下面主要集中说下学习率
5.1:总的来说是用一个一般的学习率开始,然后逐渐的减小它
5.2:一个建议值是0.1,适用于很多NN的问题,一般倾向于小一点。
5.3:一个对于调度学习率的建议:如果在验证集上性能不再增加就让学习率除以2或者5,然后继续,学习率会一直变得很小,到最后就可以停止训练了。
5.4:很多人用的一个设计学习率的原则就是监测一个比率(每次更新梯度的norm除以当前weight的norm),如果这个比率在10-3附近,如果小于这个值,学习会很慢,如果大于这个值,那么学习很不稳定,由此会带来失败。
6:使用验证集,可以知道什么时候开始降低学习率,和什么时候停止训练。
7:关于对weight初始化的选择的一些建议:
7.1:如果你很懒,直接用0.02*randn(num_params)来初始化,当然别的值你也可以去尝试
7.2:如果上面那个不太好使,那么久依次初始化每一个weight矩阵用init_scale / sqrt(layer_width) * randn,init_scale可以被设置为0.1或者1
7.3:初始化参数对结果的影响至关重要,要引起重视。
7.4:在深度网络中,随机初始化权重,使用SGD的话一般处理的都不好,这是因为初始化的权重太小了。这种情况下对于浅层网络有效,但是当足够深的时候就不行了,因为weight更新的时候,是靠很多weight相乘的,越乘越小,有点类似梯度消失的意思(这句话是我加的)
8:如果训练RNN或者LSTM,务必保证gradient的norm被约束在15或者5(前提还是要先归一化gradient),这一点在RNN和LSTM中很重要。
9:检查下梯度,如果是你自己计算的梯度。
10:如果使用LSTM来解决长时依赖的问题,记得初始化bias的时候要大一点
12:尽可能想办法多的扩增训练数据,如果使用的是图像数据,不妨对图像做一点扭转啊之类的,来扩充数据训练集合。
13:使用dropout
14:评价最终结果的时候,多做几次,然后平均一下他们的结果。
参考:
https://zhuanlan.zhihu.com/p/24720954#!
http://chenrudan.github.io/blog/2015/08/04/dl5tricks.html
深度学习大牛 Bengio 的paper:《Dropout: A Simple Way to Prevent Neural Networks from Overfitting》
Yoshua Bengio 《Practical Recommendations for Gradient-Based Training of Deep Architectures》总结了很多tricks.
Efficient BackProp, by Yann LeCun, Léon Bottou, Genevieve Orr and Klaus-Robert Müller
Neural Networks: Tricks of the Trade, edited by Grégoire Montavon, Geneviève Orr, and Klaus-Robert Müller.