前言
一、学习和泛化
二、技巧1:随机梯度下降与批量学习
三、技巧2:打乱样本顺序
四、技巧3:标准化输入
五、技巧4:激活函数
六、技巧5:选择目标值
七、技巧6:初始化权重
八、技巧7:选择学习率
九、其他
总结
神经网络模型使用随机梯度下降进行训练,模型权重使用反向传播算法进行更新。通过训练神经网络模型解决的优化问题非常具有挑战性,尽管这些算法在实践中表现出色,但不能保证它们会及时收敛到一个良好的模型。
在本文中,您将了解在训练神经网络模型时如何充分利用反向传播算法的技巧和诀窍。
使用反向传播设计和训练网络需要做出许多看似任意的选择,例如节点的数量和类型、层的数量、学习率、训练和测试集等。这些选择可能至关重要,但却没有百分百可靠的决策法则,因为它们在很大程度上取决于问题和数据。训练神经网络模型的目标最具挑战性,因为它要解决两个难题:
在这些问题之间存在权衡,因为学的太好的模型泛化能力可能较差,而泛化良好的模型可能欠拟合。训练神经网络的目标是在这两方面找到一个良好的平衡。
在拟合神经网络模型时,这些术语可以定义为:
这种表述将模型的容量定义为偏差的选择,控制可以学习的函数范围。它将方差视为训练过程的函数,并在过拟合训练数据集和泛化误差之间取得平衡。
随机梯度下降,也称为在线梯度下降,是指从训练数据集中随机选择一个示例,估算误差梯度,然后更新模型参数(权重)的算法版本。它的效果是快速训练模型,尽管可能会导致模型权重的大幅、嘈杂的更新。
通常情况下,基本反向传播首选随机学习,原因有三:
批量梯度下降涉及使用训练数据集中所有示例的平均值来估算误差梯度。它执行更快,从理论上更容易理解,但导致学习速度较慢。
尽管随机学习具有诸多优势,仍有理由考虑使用批量学习:
尽管批量更新具有优势,但在处理非常大的数据集时,随机学习仍然通常是首选方法,因为它更简单更快。
神经网络从最意外的样本中学得最快。因此,建议在每次迭代中选择对系统最不熟悉的样本。实现这个技巧的一个简单方法是确保用于更新模型参数的连续示例来自不同的类别。
这个技巧也可以通过向模型展示并重新展示它在进行预测时犯的最多错误或产生最多错误的示例来实现。这种方法可能是有效的,但如果在训练期间过度表示的示例是离群值,它也可能导致灾难。
选择信息内容最大的示例:
当训练数据集中的示例总和为零时,神经网络通常学得更快。这可以通过从每个输入变量中减去平均值(称为居中)来实现。通常,如果训练集上每个输入变量的平均值接近零,收敛速度会更快。
此外,将输入居中也很提高模型对来自先前层的输入到隐藏层的收敛性。这是令人着迷的,因为它为后来近15年发展并广泛流行的批量归一化技术奠定了基础。
因此,最好将输入移动,以使训练集的平均值接近零。这个启发式方法应该应用于所有层,这意味着我们希望节点的输出的平均值接近零,因为这些输出是下一层的输入。
转换输入:
非线性激活函数赋予神经网络非线性能力。其中一种最常见的激活函数形式是Sigmoid。
在隐藏层使用Logistic和Tanh激活函数不再是一个合理的默认选择,因为使用ReLU的性能使得模型收敛速度更快。
最后一层的激活函数:
限制输出范围的话,一般不用任何激活。需要考虑输入的是什么,标准化之后的输出的取值范围,如果输出有正有负,用ReLU和Sigmoid是明显不行的;多分类任务一般使用Softmax(相当于对输出归一化为概率分布)。
最后一层一般用Tanh激活函数,产生一个问题就是梯度在-1或1附近非常小,神经元饱和学习很慢,容易产生梯度消息,模型产生更多接近-1或1的值。
在二分类问题的情况下,目标变量可能是logistic激活函数(通常指的是Sigmoid函数)的渐进值集合{0,1},或者Tanh函数的渐进值集合{-1,1},分别对应使用交叉熵或铰链损失(Hinge Loss)函数(因为交叉熵直接针对概率分布,而sigmoid函数的输出可以被解释为概率;铰链损失函数铰链损失通常与支持向量机(SVM)相关联,但它也可以用于神经网络,它适用于"最大间隔"分类。),即使是在现代神经网络中也是如此。
在激活函数的饱和点(边缘)取得值可能需要更大的权重,这可能使模型变得不稳定。
权重的初始值对训练过程有很大的影响。权重应该随机选择,但以Sigmoid函数的线性区域为主要激活区域。这个建议也适用于ReLU的权重激活,其中函数的线性部分是正的。
初始权重对模型学习有重要影响,其中大权重使激活函数饱和,导致不稳定的学习,而小权重导致梯度非常小,进而学习缓慢。理想情况下,我们寻求模型权重位于激活函数的线性(非曲线)部分之上。
学习率是模型权重在算法的每次迭代中更新的量。较小的学习率可能导致收敛较慢,但可能得到更好的结果,而较大的学习率可能导致更快的收敛,但可能得到不太理想的结果。
建议当权重值开始来回变化,例如振荡时,减小学习率。
1、单批次过拟合
主要是用来测试我们网络的性能。首先,输入单个数据批次,并且保证这个batch数据对应的标签是正确的(如果需要标签的话)。然后,重复在这个batch数据上进行训练,直到损失函数数值达到稳定。如果你的网络不能到达一个完美的准确率(利用不同指标),那么首先检查一下数据,在我们提出的这个方法,就是在确保数据没有问题的情况下,检测我们模型的性能。这样,就避免了我们使用过于庞大或复杂的模型来解决简单的问题,毕竟找到最合适的方法才是最有效的(杀鸡用不着牛刀)。
2、运行大数值epochs
很多情况下,我们通过大量epochs训练模型之后,可以获得一个很好的结果。如果,我们可以承受长时间的模型训练,那么我们可以采用一种策略来选择epochs数值(例如:从100逐渐增长到500)。这样,当我们有过大量训练模型的经验之后,大家就可以总结出自己的一组数据(称为epoch factors),使用这些参数,我们训练新的模型时,可以快速设置初始训练epochs,并且按照一定的比例来增加epochs。
3、设置种子参数
为了保证模型的可重现性(reproducibility),我们可以采用一种方法,就是设置任何随机数生成操作的种子。例如,如果我们使用TensorFlow框架,我们可以采用下面的代码片段:
import os, random
import numpy as np
import tensorflow as tf
def set_seeds(seed: int):
os.environ['PYTHONHASHSEED'] = str(seed)
random.seed(seed)
tf.random.set_seed(seed)
np.random.seed(seed)
使用操作种子的原因是,计算机并不能真实输出随机数,也就是计算机输出的是伪随机数,它是按照一定的规则来输出随机数。这样的话,我们可以采用一系列规则来模拟随机数的生成,也就是我们采用set_seed这个函数来模拟随机数生成,
4、使用数据增强
数据增强可以让我们训练一个更加鲁棒的网络模型,通过增加数据集的数量,或者通过上采样小类别数据,但是这些数据增强,带来的消耗就是训练次数的增加。
神经网络训练是一个非常复杂的过程,在这过程中,许多变量之间相互影响,因此在这过程中,很难搞清楚这些变量是如何影响神经网络的。而本文给出的众多tips就是让大家,在神经网络训练过程中,更加简单方便的加速训练网络。