来源:https://www.worthpen.top/blog?id=656617456aa58e39d9301927
训练时的问题
出现nan
-
检查模型的构建,确保没有出现除0的情况;
-
检查输入数据,确保没有出现nan或者inf;
-
检查学习率,确保学习率不过大;
-
检查模型参数,确保模型参数初始化合理;
-
检查损失函数,确保损失函数没有出现除0的情况;
-
检查优化器,确保优化器的参数设置合理;
-
检查batch size,确保batch size不过大;
-
检查数据增强,确保数据增强没有出现除0的情况;
-
检查模型的梯度,确保梯度没有出现除0的情况;
-
检查模型的参数,确保模型参数没有出现nan或者inf;
训练流程
小规模训练
如果上手一个模型, 就用全部数据来进行训练, 那么就会消耗大量的时间来调整一些不需要训练全部数据就可以得到的超参或debug. 因此, 需要分阶段来进行训练.
阶段一: debug, 数据集长度设置为多个batch就可以, 主要跑一遍程序保证可以运行和没有明显的错误运算. 对于多层架构的网络,可以在一开始选用较少层的网络,如对于ResNet采用ResNet50而不是ResNet152.
阶段二: 使用更多的数据(可能几千个数据), 验证模型过拟合特性, 保证模型可以拟合数据和确定学习率等超参数.
阶段三: 使用可以反应数据分布的数据的量级(可能与阶段二的数据量相似或稍微大几倍), 去训练数据, 在这过程中尽量决定超参数. 当数据量不是特别大时, 直接步骤四.
阶段四: 完全训练, 这时同样可以对超参数进行修改, 但是尽量在阶段三完成超参数的修改. 对于多层架构的网络,这阶段开始使用较多层的网络进行训练。
数据集的分割
为了提高泛化性,即对未知数据的识别能力,需要使用训练数据外的数据进行测试. 一般主要分为训练集, 验证集, 测试集.
定义
训练集(Training Dataset)主要在训练阶段使用。当我们的模型训练好之后,我们并不知道他的表现如何。
这个时候就可以使用验证集(Validation Dataset)来看看模型在新数据(验证集和测试集是不同的数据)上的表现如何。同时通过调整超参数,让模型处于最好的状态。验证集不像训练集和测试集,它是非必需的。如果不需要调整超参数,就可以不使用验证集,直接用测试集来评估效果。
通过测试集(Test Dataset)来做最终的评估。因为测试集是从未见过的数据,因此可能最公正的表示模型的性能。
数据划分的方法并没有明确的规定,不过可以参考3个原则:
● 对于小规模样本集(几万量级),常用的分配比例是 60% 训练集、20% 验证集、20% 测试集。
● 对于大规模样本集(百万级以上),只要验证集和测试集的数量足够即可,例如有 100w 条数据,那么留 1w 验证集,1w 测试集即可。1000w 的数据,同样留 1w 验证集和 1w 测试集。
● 超参数越少,或者超参数很容易调整,那么可以减少验证集的比例,更多的分配给训练集。
此外,还有一种划分数据集的方法为K折交叉验证法,用于降低由于数据划分引起的验证结果的方差, 更真实的体现模型的性能。
为什么训练集的数据量最大?
训练或者选取超参数的过程实际上是通过使用特定参数拟合当前数据集来拟合超越当前数据集的未知模型的过程, 应该用适当的参数量拟合适当复杂度的模型(少量参数难以拟合复杂模型, 大量参数会过拟合复杂模型), 训练过程中的参数量相较于超参数的参数量大, 可以拟合更复杂的模型, 因此, 训练集的数据量最大.
是否需要将测试集纳入k折交叉验证中?
不将测试集纳入K折交叉验证中, 必然会带来随机性的误差. 就像学习-测验-高考一样, 总会有人发挥好. 为了简化流程, 可以定义验证集后为测试集.
是否可以使用多个小数据集选择多个参数?
使用新数据去判断网络的泛化性, 本质是使用新的数据去训练网络, 只不过该训练挑选的不是权重, 而是网络模型, 也可以认为是超参数.
训练神经网络的目的是使参数以适当的程度去拟合数据集, 同时又可以保证其在隐模型(未知模型)上的精度.
假设当前网络已经较好的拟合了旧数据, 如果再在旧数据的基础上进行选择, 那么就会导致更进一步的拟合旧数据. 每有一个新参数, 则采用一个新的数据集来进行选取, 则可以保证比较好的受隐模型的引导, 保证一定的泛化性. 但是, 假设当前并没有拟合当前旧数据, 盲目的使用新数据集来进行选取, 则会导致欠拟合, 不能对数据集进行较好的拟合.
综合来看, 并不能确定多少个参数对应多少的数据量, 这中间存在一个未知的平衡. 因此, 在训练过程中, 当前只分为决定权重的训练集, 决定超参数的验证集和决定网络模型的测试集.
重载训练和载入之前的权重重新训练的区别
重载训练会使用之前的学习率和一些其他与epoch有关的量, 而仅载入权重则无该效果.
但是仍建议尽量不要使用重载训练. pl(其实基本都是如此)中的重载训练不会保存随机数信息, 这会导致重载训练时, 取样序列和初始训练时的顺序一样, 无法进行有效shuffle. 通过我对机器学习框架的修改, 实现了重载训练具有不同的取样序列, 并且该序列在给定随机种子的情况下不变.
但是, 此时的训练结果仍与原作者的训练结果不同. 在训练过程中随机种子随着epoch数变化, 这些改变的随机种子影响着随机梯度下降等方面, 导致了出现差异. 该差异在自身训练的情况下是可以接受的, 在使用其他作者给出的参数下训练是不能得到和原作者相同的结果的.
超参的设置
超参数优化的先后取决于超参数的相互依赖关系。有时,某些超参数可能对其他超参数的影响更大,就需要先进行优化调整。例如:当一个网络由于层数或者结构导致在盆地数量和大小方面更平滑时,总是采用该平滑的网络好,不论此时的batch size是多少。因此,网络影响更大,应当先调整网络结构。
超参数有:batch size、epoch、优化器及其学习率。
batch size
当处理器不饱和时,batch size越大,训练速度越快。因此,针对gpu的并行训练, 为了提高训练速度,可以尽量高batch size。上限是对于gpu利用率100既可.
但是,大的batch size会导致在一个epoch内,迭代次数减小。而loss是batch内的均值,其虽然会有误差,但是基本不会随着batch size改变而改变。因此大batch size会导致迭代次数减小,探索范围变小。进而影响模型的性能。
当使用二阶梯度下降算法时,因为二阶梯度下降需要计算准确的二阶导数,因此需要大batch size。
听说batch size设置为2的幂次可以具有更好的性能,如2、4、8、16、32.
综上,当使用adam时,由于无法调整学习率以适配batch size。因此,只能延长epoch以保证性能。batch size应当尽量大,保证GPU利用率100即可。
小batch size的噪声问题
batch size较小时, 梯度具有不确定性, 具有较大噪声。有研究人员指出,该噪声是网络最后停在平滑点的关键。然而,也有研究人员指出,网络最后的性能更依赖于探索范围,而不是噪声。见文章[train longer,generalize better]。
优化器
一类优化器是自适应优化器,如Adam,Adagrad,RMSprop等。自适应优化器可以快速收敛,但是可能陷入局部极小,导致泛化性能不强。另一类是SGD+momentum,可以实现找到泛化能力更好的权重,但可能需要更长的收敛时间。
可以在训练的前期使用自适应优化器,在后期使用SGD+momentum。
优化器的学习率
虽然现在通常使用adam优化器,但是该优化器效果的好坏仍与初始学习率相关,可以通过小数据集测试拟合能力的方式确定学习率。
学习率与网络的关系
学习率会因为网络变化而改变
学习率、数据量和batch size的关系
根据论文[Don’t Decay the Learning Rate, Increase the Batch Size],SGD的随机波动满足
g
=
l
r
∗
(
N
/
B
−
1
)
g=lr*(N/B−1)
g=lr∗(N/B−1)
其中,N为数据量,B为batch size。因此,为了保证随机波动性大致不变,当数据量变大时,学习率应该减小;当batch size变大时,学习率应该同步变大。
多任务学习的学习率
对于多任务学习,首先单任务确定各自学习率,再确定其比例和总学习率
动态学习率
变化的学习率也可以提高准确度。可以采用余弦退火和热重启的动态学习率;也可以在损失停止改善后,降低学习率,类似于早停法。
epoch的设置(最优模型的选取)
训练集的损失是永远向下的(排除跳出驻点的情况). 损失和准确率是负相关的, 但是可能出现损失降低, 准确率不变的情况.
过拟合的现象为训练集损失降低,而验证集的损失(因为准确率的变化慢于损失,因此后续准确率也会降低)变大, 验证集和训练集的损失和准确率变化图如图所示. 由图可知, 损失的最低点不一定准确率最高, 准确率在损失到达一定程度后, 可能上升也可能平缓.
最优模型的选取方案一:
为了保证准确率, 需要选择验证集的准确率最大的模型为最优, 否则模型将会过拟合,导致为了更好的训练集acc而学习一些不具有代表性的特征。
当然, 该图仅是在不考虑正则等防止过拟合的方法, 现在有许多防止过拟合的方法. 这些方法可能使得再多的训练也不会使得验证集出现准确率下降的情况. 但是, 即使不考虑过拟合的因素, 在max epoch内选择最优的模型也是较好的方案.
最优模型的选取方案二:
根据方案一中提到的不考虑过拟合的因素, 就有了train longer的训练方法, 即选择最后训练最后得到的模型. 训练的越久越好.
注意: 还需要对这两种进行测试. Stochastic Training is Not Necessary for Generalization中的train longer既每个epoch都保存, 又保存了last model. 因此, 需要对两种方案进行测试.
图中,AB点之间,验证准确度可能上升或者平缓,C点开始出现过拟合
早停法
早停法有三类标准. 首先定义泛化损失为当前的泛化误差相比于最低的泛化误差的差值. 第一类早停标准是泛化损失到达一定阈值; 第二类是当训练loss降低的很慢时泛化损失到达一定的阈值(这里使用了通俗语言来描述, 详细方法可以在网络上搜索); 第三类是当泛化损失在N个周期内持续增长.
早停法的作用是为了对抗过拟合, 当前已经有了很多对抗过拟合的方法, 如正则化, dropout等. 因此, 不需要担心过拟合, 大多数情况下不会出现过拟合. 因此, 可以尽量多的训练epoch, 然后挑选这期间最好的结果.
权重初始化
当权重值(值指的是绝对值)过小,输入值每经过网络层,方差(同样也是值)都会减少,每一层的加权和很小。当权重的值过大,输入值经过每一层后方差会迅速上升,每层的输出值将会很大,此时每层的梯度将会较大. 为了防止方差剧烈变化导致的震荡, 需要对初始化的值进行计算.
需要根据使用的激活函数,采用不同的初始化方式,如rule激活函数使用kaiming分布,tanh激活函数使用xavier分布. 此外, 初始化权重的分布要与输入同分布类型, 如都为高斯分布或均匀分布. 输入的均值需要为0、
令初始化权重的特征值为1的作用
一般而言, 初始化网络追求的是一个神经元输入与输出的方差相同, 以保证参数空间不会具有较大的距离差, 以保证梯度大小稳定, 这是一个针对参数空间的, 也就是针对最后计算的误差的距离所形成的梯度过大或过小. 从另一个方面看, 这里出现梯度过大或过小的原因是因为w是一个随机数, 而这个随机数的范围大导致了输出范围大, 这与w的固定值大无关. 初始化方法稳定了输出误差的大小, 而不是使反向传播过程中不会具有较大的放缩.
对于RNN, 由于多次乘W, 所以W矩阵的特征值很重要, 保证特征值为1, 则可保证梯度不会爆炸和消失. 这与w的固定值比较大小有关, 如固定值大, 反向传播时引起了梯度越来越大.
可以设计一种算法, 实现对W矩阵的随机选取, 并限定W矩阵的范围和特征值, 这样就可以实现同时满足输出范围和反向传播的梯度的问题. 但是, 由于这仅是一个初始值, 一旦训练过一次梯度下降, 则W矩阵的特征值不再满足特征值为1. 因此, 该算法可能不会带来性能上的提升,但会有训练稳定性.
初始化不能全部相同
当全部神经元的初始化参数相同时,同层神经元的误差图的对称的。并且,此时得到的同层权重的导数是相同的,就会造成,梯度下降的方向只会沿着对称轴的方向,这就是神经网络的对称性。因此,需要避免权重参数处于这一状态,目前有两种方案。一种是当计算出梯度时,人为的增加一个随机数,但是这会导致梯度计算不准确。虽然随机梯度下降法也引入了随机的梯度,但是随机梯度下降中的随机梯度是根据一个样本计算出的,其是有迹可循的。而完全的随机数可能会导致梯度计算出现较大的误差。另一种方案是随机初始化,这个方案既避免了梯度下降受困于对称轴,又避免了错误的梯度计算,还保证了寻找的最低点的范围比较大,是当前大多数采用的方案。
DataLoader的num_works参数
根据CPU核心数和内存大小, 尽量越大越好.
tricks
trick指的是可用于多个网络模型的一种操作, 可以提升模型的性能, 也可以不添加trick. transformer作为一种模型, 而不是一个trick.
输入数据的标准化
为了满足初始化权重算法的要求, 需要输入参数的均值为0.
归一化
归一化可以改变数据的分布,通过改变数据分布,当数据不同维度的分布不同时,容易出现更具影响力的维度,而实际上该维度不该具有如此的影响力这个影响力仅仅是因为其输入的数值过大而引起的,这降低了收敛速度;归一化还使数据在激活函数中落入有梯度的区间,防止了梯度消失,这同样增加了收敛速度。
神经网络本质就是学习特定分布下的曲线,如果分布一直改变,会导致收敛速度很慢。因此,需要对每一层的输入进行归一化,实现神经网络每层输入的稳定。
批归一化
(1) 批归一化的最后一步,缩放和平移使为了让网络自己学习得到归一化后的均值和方差,因为强制性的将所有均值及方差置为0有时候不能使其落入有梯度的区间。
(2) 批归一化在测试过程时使用全部训练集的均值和方差。因此,需要在每个batch的训练过程中保存该batch的均值的方差,最后求和。
层归一化
层归一化只能使数据在激活函数中落入有梯度的区间,防止了梯度消失,不能实现对不同维度的特征分配不同的分布。
通道和空间注意力机制
https://blog.csdn.net/u011984148/article/details/109475440
数据清洗
当标签有错误时, 可以先训练一个结果, 再对数据集进行测试, 如果结果出错, 则数据有可能为错误标签. 该方法已经提出并应用.
硬标签和软标签
one-hot就是硬标签, 转为one-hot前的概率分布就是软标签
标签平滑
标签平滑就是将硬标签转化为软标签, 实际上是引入了噪声, 对训练参数进行正则化以提高泛化性. 方法如下.
其中, K为类别, ε为一个较小的超参数.
知识蒸馏
知识蒸馏通过以下几点提高了性能:
(1) 通过对硬标签的学习, 获得了软标签的知识, 相当于扩充了数据集. 例如, 一开始在的硬标签让模型学习到了为车的概率是0.9, 为猫的概率是0.1(可能由于车灯像猫的眼睛), 之后通过这一软标签进行蒸馏, 相当于扩充了猫的数据集, 可以某种程度上学习到猫和车灯类似的知识, 仅通过硬标签进行再多次的训练, 也无法得到该知识, 反而容易过拟合, 不认为车灯像猫, 实际上车灯确实像猫.
模型集成
使用不同随机种子的学习网络F1,…F10, 这些网络具有非常相似的测试性能。只需对这些独立训练的网络的输出进行无加权的平均,就可以在许多深度学习应用中获得测试时性能的巨大提升。
模型集成提升性能的原因可能是: 网络的学习具有随机性, 这与随机种子有关, 不同的随机种子可能会以不同的顺序学习特征, 当已经学到了一部分特征a, 但仍有一部分特征b没有学到. 这时, 特征a已经足以判断数据集中的大部分数据, 这就会导致这些数据不再提供梯度, 无法进一步学习, 这就导致了特征b在该随机种子下不会被学习. 通过使用不同的随机种子, 学习了不同的特征信息, 再通过集成, 将这些特征进行融合, 就提高了模型的性能.
warm-up
warm-up不一定能提升性能, 使用需要具有不使用warm-up的对比试验, 保证warm-up可以提升性能.
多尺度训练
多尺度训练是一种有效的训练方法,通过输入不同尺度的图像数据集,因为神经网络卷积池化的特殊性,这样可以让神经网络充分地学习不同分辨率下图像的特征,可以提高机器学习的性能。也可以用来处理过拟合效应,在图像数据集不是特别充足的情况下,可以先训练小尺寸图像,然后增大尺寸并再次训练相同模型。
需要注意的是:多尺度训练并不是适合所有的深度学习应用,多尺度训练可以算是特殊的数据增强方法,在图像大小这一块做了调整。如果有可能最好利用可视化代码将多尺度后的图像近距离观察一下,「看看多尺度会对图像的整体信息有没有影响」,如果对图像信息有影响的话,这样直接训练的话会误导算法导致得不到应有的结果。
限制权重最大值
与L2正则类似,属于正则化技术
标签权重
对于高度不平衡的数据,是应用类别加权,如过采样或欠采样技术重新采样训练集。
先最大池化再ReLU
先最大池化再ReLU和先ReLU再最大池化结果完全一样。前者降低运算量。
改变输入动态范围,归一化前使用
以合理地保留动态范围的方式对输入数据进行缩放。这个步骤和归一化有关,但是应该在归一化操作之前进行。例如,在真实世界中范围为 [0, 140000000] 的数据 x 通常可以用「tanh(x)」或「tanh(x/C)」来进行操作,其中 C 是某个常数,它可以对曲线进行拉伸,从而在 tanh 函数的动态倾斜(斜率较大)部分对更大输入范围内的数据进行拟合。尤其是在输入数据在函数的一端或者两端都不受限的时候,神经网络将在数据处于 (0,1) 时学习效果更好。
竞赛技巧
trick可以应用于生产环境,可以真实的提升网络性能,而竞赛技巧只是针对测试集研究的技巧,而不能提升在生产环境中预测真实分布的能力。
挑选出和测试集输入分布构成的loss相同的验证集
https://blog.csdn.net/xixiaoyaoww/article/details/109234145