深度学习入门(四):与学习相关的技巧
选择与目标职位相关的讲座深度学习 #生活常识# #职场技巧# #职业发展讲座#
与学习相关的技巧
本章介绍的方法,可以高效地进行神经网络(深度学习)的学习,提高识别精度
参数的更新
神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题,解决这个问题的过程称为最优化。
在前几章中。为了找到最优参数,我们将参数的梯度作为线索,使用参数的梯度,沿梯度方向更新参数,并重复这个步骤若干次,从而靠近最优参数。这个过程称为SGD 随机梯度下降法。
代码
class SGD:def __init__(self, lr = 0.01):self.lr = lrdef update(self, params, grads):for key in params.keys():params[key] -= self.lr * grads[key] 1234567'
变量名optimizer表示“进行最优化的人”的意思。
SGD的缺点 如果函数的形状非均向,比如呈延伸状,搜索的路径就会非常低效。SGD低效的根本原因是,梯度的方向并没有指向最小值的方向。
MomentumMomentum是“动量”的意思。
v ← α v − η ∂ L ∂ W v \leftarrow \alpha v - \eta \frac{\partial L}{\partial W} v←αv−η∂W∂L
W ← W + v W \leftarrow W + v W←W+v
W表示要更新的权重参数, ∂ L ∂ W \frac{\partial L}{\partial W} ∂W∂L表示损失函数关于W的梯度, η \eta η表示学习率。这里新出现了一个变量v,对应物理上的速度。表示了物体在梯度方向上受力,在这个力的作用下,物体的速度增加这一物理法则。
class Momentum: def __init__(self, lr=0.01, momentum=0.9): self.lr = lr self.momentum = momentum self.v = None def update(self, params, grads): if self.v is None: self.v = {} for key, val in params.items(): self.v[key] = np.zeros_like(val) for key in params.key(): self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] params[key] += self.v[key] 123456789101112131415'
实例变量v会保存物体的速度。初始化时,v中什么都不保存,但当第一次调用update时,v会以字典型变量的形式保存与参数结构相同的数据。
AdaGrad在神经网络的学习中,学习率(数学中记为 η \eta η)的值很重要。学习率过小,会导致学习花费过多的时间;反过来,学习率过大,则会导致学习发散而不能正确进行。
在学习率的有效技巧中,有一种被称为学习率衰减的方法,即随着学习的进行,使学习率逐渐减少。
AdaGrad进一步发展了这个想法,针对“一个一个”的参数,赋予其“定制”的值。
AdaGrad会为参数的每个元素适当的调整学习率。
h ← h + ∂ L ∂ W ⨀ ∂ L ∂ W h \leftarrow h + \frac{\partial{L}}{\partial{W}}\bigodot \frac{\partial{L}}{\partial{W}} h←h+∂W∂L⨀∂W∂L
W ← W − η 1 h ∂ L ∂ W W \leftarrow W - \eta\frac{1}{\sqrt{h}}\frac{\partial{L}}{\partial{W}} W←W−ηh
1∂W∂L
和SGD一样,W表示要更新的权重参数, ∂ L ∂ W \frac{\partial{L}}{\partial{W}} ∂W∂L表示损失函数关于W的梯度, η \eta η表示学习率。h保存了以前的所有梯度值得平方和。然后再更新参数时,通过乘以 1 h \frac{1}{\sqrt{h}} h
1,就可以调整学习的尺度。也就是说,可以按照参数的元素进行学习率的衰减,使变动大的参数进行学习率衰减,使变动大的参数的学习率逐渐减少。
缺点:
AdaGrad会记录过去所有梯度的平方和。因此,学习越深入,更新的幅度就越小。实际上,如果永无止境地学习,更新量就会变为0,完全不更新。
代码实现
class AdaGrad: def __init__(self, lr=0.01): self.lr = lr self.h = None def update(self, params, grads): if self.h is None: self.h = {} for key, val in params.items(): self.h[key] = np.zeros_like(val) for key in params.keys(): self.h[key] += grads[key] * grads[key] params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key] + 1e-7)) 123456789101112131415'
注意:最后一行加上了微小值1e-7。这是为了防止当self.h[key]中有0时,将0用作除数的情况。
Adam如果将AdamGrad和momentum融合在一起会怎么样?这就是Adam方法的基本思路。
Adam会设置3个超参数。一个是学习率,另外两个一个是momentum系数 β 1 \beta_1 β1和momentum系数 β 2 \beta_2 β2。这两个值分别设定为0.9和0.999。这里并没有详细介绍,如果有机会会补充。
权重的初始值
可以将权重初始值设为0吗为什么不能将权重初始值设为0?严格地说,为什么不能将权重初始值设成一样的值呢?这是因为在误差反向传播中,所有的权重值都会进行相同的更新。因此,权重被更新为相同的值,并拥有了对称的值(重复的值)。这使得神经网络拥有许多不同的权重的意义丧失了。为了防止“权重均一化”,必须随机生成初始值。
注意
各层的激活值的分布都要求有适当的广度。为什么呢?因为通过在各层间传递多样性的数据,神经网络可以进行高效的学习。反过来,如果传递的有所偏向的数据,就会出现梯度消失或者“表现力受限”的问题,导致学习可能无法顺利进行。
接着,我们尝试使用Xavier初始值,为了使各层的激活值呈现出具有相同广度的分布,结论是,如果前一层的节点数为n,则初始值使用标准差为 1 n \frac{1}{\sqrt{n}} n
1的分布。
tanh函数和sigmoid函数同是S型曲线函数,但tanh函数是关于原点(0,0)对称的S型曲线,而sigmoid函数是关于(x, y) = (0, 0.5)对称的S型曲线。众所周知,用作激活函数的函数最好具有关于原点对称的性质。
Xavier初始值是以激活函数是线性函数为前提而推导出来的。因为sigmoid函数和tanh函数左右对称,且中央附近可以视作线性函数,所以适合使用Xavier初始值。但不适合ReLU。一般推荐使用ReLU专用的初始值,“He初始值”.当前一层的节点数为n时,He初始值使用标准差为 2 n \sqrt{\frac{2}{n}} n2
的高斯分布。当Xavier初始值是 1 n \sqrt{\frac{1}{n}} n1
可以解释为:因为ReLU的负值区域的值为0,为了使它更具有广度,所以需要2倍的系数。
总结当激活函数使用ReLU时,权重初始值使用He初始值,当激活函数为sigmoid或tanh等S型曲线函数时,初始值使用Xavier初始值。
Batch Normalization
Batch Normalization 的算法优点:
可以使学习快速进行(可以增大学习率)不那么依赖初始值(对于初始值不用那么神经质)抑制过拟合(降低Dropout等的必要性)Batch Norm的思路是调整各层的激活值分布使其拥有适当的广度。
Batch Norm,顾名思义,以进行学习时的mini-batch为单位,按mini-batch进行正规化。具体而言,就是进行使数据分布的均值为0,方差为1的正规化。
I n e w = I − I m e a n s t d ( I ) I_{new} = \frac{I - I_{mean}}{std(I)} Inew=std(I)I−Imean
将这个处理插入到激活函数的前面(或者后面),可以减少数据分布的偏向。
接着,Batch Norm层会对正规化后的数据进行缩放和平移的变换, y i ← γ x i ^ + β y_i \leftarrow\gamma\hat{x_{i}} + \beta yi←γxi^+β
这里, γ 和 β \gamma和\beta γ和β是参数一开始 γ = 1 β = 0 \gamma=1\beta = 0 γ=1β=0,然后通过学习调整到合适的值。
正则化
过拟合指的是只能拟合训练数据,但不能很好地拟合不包括在训练数据中的其他数据的状态。
权值衰减权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。
L2范数是指向量各元素的平方和然后求平方根。
对于所有权重,权值衰减方法都会为损失函数加上 1 2 λ ω 2 \frac{1}{2}\lambda\omega^2 21λω2。因此,在求权重梯度的计算中,要为之前的误差反向传播法的结果加上正则化的导数 λ ω \lambda\omega λω。
Droput是一种在学习的过程中随机删除神经元的方法。在训练时,随机选出隐藏层的神经元,然后将其删除。
import numpy as np class Dropout: def __init__(self, dropout_ratio=0.5): self.dropout_ratio = dropout_ratio self.mask = None def forward(self, x, train_flg=True): if train_flg: self.mask = np.random.rand(*x.shape) > self.dropout_ratio return x * self.mask else: return x * (1.0 - self.dropout_ratio) def backward(self, dout): return dout * self.mask
1234567891011121314151617'每次正向传播时,self.mask中都会以False的形式保存要删除的神经元。self.mask会随机生成和x形状相同的数组,并将值比dropout_ratio大的元素设为True.反向传播时按原样传递信号;正向传播时没有传递信号的神经元,反向传播会停在那里。
机器学习中经常使用集成学习。就是让多个模型单独进行学习,推理时再取多个模型的输出的平均值。这个集成学习与Dropout有密切的关系。可以理解为通过再学习过程中随机删除神经元,从而每一次都让不同的模型进行学习。
超参数的验证
验证数据训练数据用于参数(权重和偏置)的学习,验证数据用于超参数的性能评估。
超参数的最优化进行超参数的最优化时,逐渐减少超参数的“好值”的存在范围非常重要。
超参数的范围只要“大致地指定”就可以了。所谓“大致地确定”,是指像0.001到1000这样,以“10的阶乘”的尺度指定范围。
超参数的最优化的内容:
在缩小到一定程度时,从该范围中选出有个超参数的值,这就是进行超参数的最优化的一种方法。
如果需要更精炼的方法,可以使用贝叶斯定理为中心的数学理论,能够更加严密、高效地进行最优化。 超参数最优化的实现
weight_decay = 10** np.random.uniform(-8,-4) lr = 10 ** np.random.uniform(-6,-2) 12
像这样进行随机采样后,再使用那些值进行学习。之后,多次使用各种超参数的值重复进行学习,观察合乎逻辑的超参数在哪里。
说明
此为本人学习《深度学习入门》的学习笔记,详情请阅读原书.
网址:深度学习入门(四):与学习相关的技巧 https://www.yuejiaxmz.com/news/view/374229
相关内容
在线学习的学习技巧与学习方法.pptx学习方法与技巧
【深度学习】深度学习语音识别算法的详细解析
关于高效学习的方法与技巧
学习技巧,高效学习的技巧有哪些
初学者怎样学习化妆化妆入门小技巧
纯新手入门机器/深度学习自学指南(附一个月速成方案)
怎样学好烹调技术?新手学习烹饪的入门方法技巧
学生学习方法与技巧.doc
学生学习方法与技巧范文(17篇)