机器学习周报第四周(7.15-7.21)

摘要

本周学习了 batch,以及当 batch size过大或过小时的对比分析。对Momentum与梯度下降相结合进行优化模型的方法进行分析。在进行梯度下降过程中,学习率是一个重要的参数,学习率的大小决定着模型训练的平滑程度和稳定性。本文介绍了如何自动调整学习率,学习率会随着梯度的改变而改变。从而在各个情况下采用合适的学习率。同时也介绍了Adagard算法和Prop算法,Learning Rate Decay和Warm up是机器学习中的优化技术,这两种方式可以改变学习率中的 η \eta η,将 η \eta η随着时间的改变而改变,从而可以避免 “梯度爆炸” 等现象;同时搜索相关资料学习朴素贝叶斯理论。

Abstract

This week we learned about batch and comparative analysis when batch size is too large or too small. The method of combining Momentum and gradient descent to optimize the model is analyzed. In the process of gradient descent, the learning rate is an important parameter, which determines the smoothness and stability of model training. This article describes how to automatically adjust the learning rate, which will change as the gradient changes. Thus, the appropriate learning rate is adopted in each case. At the same time, Adagard algorithm and Prop algorithm are also introduced. Learning Rate Decay and Warm up are optimization techniques in machine learning. These two methods can change η \eta ηin learning rate and change η \eta ηwith the change of time, so as to avoid “gradient explosion” and other phenomena. At the same time, search relevant materials to learn naive Bayes theory.

1.批次(Batch)和动量(momentum)

1.1 批次(Batch)

实际上在计算梯度的时候,并不是对所有数据的损失Loss计算梯度,而是把所有的数据分成一个一个的批量(batch),每次更新参数时,会用每个Batch的数据计算出Loss值和梯度值,进行更新参数。

遍历所有批量的过程称为一个回合(epoch)。

在把数据分为批量的时候,我们还会进行随机打乱(shuffle)。随机打乱有很多不同的做法,一个常见的做法是在每一个回合开始之前重新划分批量,也就是说,每个回合的批量的数据都不一样。
在这里插入图片描述

批次的大小对Gradient descent的影响?

假设我们现在有20组训练数据。有两种极端的情况:

  1. 下图左图情况,没有使用批次,批次大小为训练数量大小,这种使用全批次(Full Batch)的数据来更新参数的方法即批次梯度下降法(Batch Gradient Descent,BGD)。此时模型必须把 20 笔训练数据都看完,才能够计算损失和梯度,参数才能够更新一次。参数更新频率较低,模型的训练过程更加稳定。

  2. 下图右图情况,Batch Size = 1 时,此时 Batch Size 最小,此时参数更新频率较高,模型的训练过程不稳定,同时在进行梯度估计时,会引入更多的噪声,导致梯度估计的不准确性增加。

在这里插入图片描述

当 Batch Size 比较大时,训练过程所花费的时间不一定比 Batch Size 比较小的时候所花费的时间长。如下图所示,这是一个手写数字辨识案例,在该案例中,Batch Size为1时所花费的时间与 Batch Size为1000时所花费的时间几乎相等。这是利用了GPU并行计算的优势,提高了训练效率。但是GPU并行计算的能力是有一个限度的。
在这里插入图片描述

假设训练数据只有 60000 笔,批量大小设为1,要 60000 个更新(update)才能“跑”完一个回合(epoch);如果批量大小等于 1000,60 个更新(update)才能“跑”完一个回合(epoch),计算梯度的时间差不多。但是60000次update和60次update比起来,时间差距是很大的。

下图中右图为跑完一个完整的回合(epoch)需要花的时间,BatchSize越大,跑完一个回合的时间越少。

因此实际上,在有考虑并行计算的时候,大的批量大小反而是较有效率的,一个回合大的批量花的时间反而是比较少的。

在这里插入图片描述

大的批量更新比较稳定,小的批量的梯度的方向是比较有噪声的(noisy)。但实际上有,噪声的的梯度反而可以帮助训练。

下图中横轴是批量大小,纵轴是正确率。
批量大小越大,验证集准确率越差。但这不是过拟合,因为批量大小越大,训练准确率也是越低。因为用的是同一个模型,所以这不是模型偏见的问题。 但大的批量大小往往在训练的时候,结果比较差。这个是优化的问题,大的批量大小优化可能会有问题,小的批量大小优化的结果反而是比较好的。

在这里插入图片描述

为什么 Batch Size 较小时引入更多噪声,但却能使得我们的训练结果更好呢?

假设我们此时选择的是 Full Batch,那我们在更新参数时,则是沿着一个 Loss function来更新,当参数更新到局部最小点或者鞍点时,梯度下降也就随之停止。如果此时我们选择的是 Small Batch,我们在更新参数时,选择第一个 Batch 时,是用 L 1 L^{1} L1这个function来更新,选择第二个 Batch 时,我们是用 L 2 L^{2} L2来更新,如果我们用 L 1 L^{1} L1计算梯度时,更新到梯度为0的点停止了,由于 L 2 L^{2} L2的funciton与 L 1 L^{1} L1不同,因此在 L 1 L^{1} L1 更新至梯度为0的点,此点在 L 2 L^{2} L2不一定梯度为0,因此即便在 L 1 L^{1} L1处无法更新参数了,但是在 L 2 L^{2} L2 处仍然可以更新参数。

在这里插入图片描述

如下图:训练损失上面有多个局部最小值,这些局部最小值的损失都很低,其损失可能都趋近于 0。但是局部最小值有好最小值跟坏最小值之分,如果局部最小值在一个“峡谷”里面,它是坏的最小值;如果局部最小值在一个平原上,它是好的最小值。

如果发生训练时的Loss跟测试时的Loss不一样,虽然只是差一点点。但对在右边在“峡谷”里面的最小值,一差就可以天差地远 。虽然它在训练集上的损失很低,但训练跟测试之间的损失函数不一样,因此测试时,损失函数一变,计算出的损失就变得很大。

大的批量大小会让我们倾向于走到“峡谷”里面,而小的批量大小倾向于让我们走到“盆地”里面。小的批量有很多的损失,其更新方向比较随机,其每次更新的方向都不太一样。即使“峡谷”非常窄,它也可以跳出去,之后如果有一个非常宽的“盆地”,它才会停下来。
在这里插入图片描述

在有并行计算的情况下,小的批量跟大的批量运算的时间并没有太大的差距(除非BatchSize特别大)。
在这里插入图片描述

1.2 Momentum

动量法(momentum method)是另外一个可以对抗鞍点或局部最小值的方法。

假设误差表面就是真正的斜坡,参数是一个球,把球从斜坡上滚下来,如果使用梯度下降,球走到局部最小值或鞍点就停住了。 但是在物理的世界里,一个球如果从高处滚下来,就算滚到鞍点或鞍点,因为惯性的关系它还是会继续往前走。如果球的动量足够大,其甚至翻过小坡继续往前走。 因此在物理的世界里面,一个球从高处滚下来的时候,它并不一定会被鞍点或局部最小值卡住,如果将其应用到梯度下降中,这就是动量。

在这里插入图片描述

引入动量后,每次在移动参数的时候,不是只往梯度的反方向来移动参数,而是根据梯度的反方向加上前一步移动的方向决定移动方向。

图中红色虚线方向是梯度的反方向,蓝色虚线方向是前一次更新的方向,蓝色实线的方向是下一步要移动的方向。把前一步指示的方向跟梯度指示的方向相加就是下一步的移动方向。

具体来说,首先我们需要有一个初始的参数 θ 0 \theta_0 θ0,假设一开始前一步的Movement变化量为0,即 M o v e m e n t Movement Movement m 0 = 0 m^0=0 m0=0,接下来通过初始参数计算出 g 0 g^0 g0,更新Movement参数,即 m 1 = λ m 0 − η g 0 m^1=\lambda m^0-\eta g^0 m1=λm0ηg0,然后更新我们的 θ \theta θ参数, θ 1 = θ 0 + m 1 \theta^1=\theta^0+m^1 θ1=θ0+m1,以此类推,不断反复更新参数。

在这里插入图片描述

m i m^i mi也可以理解为过去所计算所有gradient的总和,其中 η \eta η是学习率, λ \lambda λ是钱一个方向的权重参数,是需要调的。
在这里插入图片描述

如下图,红色表示负梯度方向,蓝色虚线表示前一步的方向,蓝色实线表示真实的移动量。;假设我们在进行梯度下降过程中,当梯度更新至0时,也就是到达局部最小值点时,此时无法继续更新参数,但根据 Last Movement 和 Real Movement,我们仍然可以继续更新参数,并不会卡在 “山谷” 中,甚至如果当梯度从0逐步增大后时,如果在某点的 Last Movement 比所求梯度还要大时,在 Last Movement 助力之下,可以成功的翻越下一个 “小山坡”,从而找到Loss值更低的点,找到更优的参数。

在这里插入图片描述

2.自动调整学习速率(Learning rate)

临界点其实不一定是在训练一个网络的时候会遇到的最大的障碍,下面两个图中,上面的图横坐标代表更新的次数,竖坐标表示损失;一般在训练一个网络的时候,Loss值原来很大,随着参数不断的更新,Loss值会越来越小,最后就卡住了,最终Loss值会逐渐趋于平稳。虽然最后Loss值是趋于平稳,但是gradient的值还会突然上升。

在这里插入图片描述

可能是这种情况,下图是一个error surface,gradient在这个谷底两侧来回震荡,此时Loss值确实不再减少,但是也没有卡到临界点。
在这里插入图片描述

一般的训练方法是很难走到临界点(critical point),此时Loss值已经下降到很低了,但是gradient值还很大。所以我们要动态改变学习率,需要学习率随着梯度变化而变化。

在这里插入图片描述

图中学习率 η = 1 0 − 2 \eta=10^{-2} η=102比较大,参数一直在谷底两侧震荡,梯度值一直很大降不下去,降低学习率为 η = 1 0 − 7 \eta=10^{-7} η=107,参数不在震荡,但是也永远无法到达终点,因为学习率太小了。

我们往常都是采用所有参数都采用同一个学习率,这样显然不可行。如果在某一个方向上,梯度的值很小,非常平坦,我们会希望学习率调大一点;如果在某一个方向上非常陡峭,坡度很大,我们会希望学习率可以设得小一点。
在这里插入图片描述

2.1 Adagrad 算法

在这里插入图片描述

例如:两个参数 θ 1 \theta_1 θ1 θ 2 \theta_2 θ2 θ 1 \theta_1 θ1坡度小, θ 2 \theta_2 θ2坡度达。
因为 θ 1 \theta_1 θ1坡度小,计算出来的梯度小,由上述 σ i t \sigma_i^t σit计算机公式计算出来的 σ \sigma σ都小,故学习率就大。相反,因为 θ 2 \theta_2 θ2坡度大,计算出来的梯度大,由上述 σ i t \sigma_i^t σit计算机公式计算出来的 σ \sigma σ都大,故学习率就小。

因此有了 这一项 σ i t \sigma_i^t σit以后,就可以随着梯度的不同,每一个参数的梯度的不同,来自动调整学习率的大小。
在这里插入图片描述

2.2 RMSProp

同一个参数需要的学习率,也会随着时间而改变,如果考虑横轴方向,绿色箭头处坡度比较陡峭,需要较小的学习率,但是走到红色箭头处,坡度变得平坦了起来,需要较大的学习率。因此同一个参数的同个方向,学习率也是需要动态调整的,于是就有了一个新的方法
在这里插入图片描述

RMSprop 第一步跟 Adagrad 的方法是相同的,即
θ i 0 = ( g i 0 ) 2 = ∣ g i 0 ∣ \theta_i^0=\sqrt{(g_i^0)^2}=|g_i^0| θi0=(gi0)2 =gi0
在这里插入图片描述
其中 0 < α < 1,其是一个可以调整的超参数。
Adagrad算法中,每一个梯度都有同等的重要性,但在 RMSprop 里面,可以自己调整现在的这个梯度的重要性。如果 α 很小趋近于 0,代表 g i t g_i^t git 相较于之前算出来的梯度而言,比较重要,如果 α 设很大趋近于 1,代表 g i t g_i^t git 比较不重要,之前算出来的梯度比较重要。

球就从 A 走到 B,AB 段的路很平坦,g 很小,更新参数的时候,我们会走比较大的步伐。走到BC 段后梯度变大了,AdaGrad 反应比较慢,而 RMSprop 会把 α 设小一点,让新的、刚看到的梯度的影响比较大,很快地让 θ i t \theta_i^t θit的值变大,很快地让步伐变小,RMSprop 可以很快地“踩刹车”。如果走到 CD 段,CD 段是平坦的地方,可以调整 α,让其比较看重最近算出来的梯度,梯度一变小, θ i t \theta_i^t θit的值就变小了,走的步伐就变大了。

在这里插入图片描述

2.3 Adam

最常用的优化的策略或者优化器(optimizer)是Adam(Adaptive moment estimation)Adam 可以看作 RMSprop 加上动量,其使用动量作为参数更新方向,并且能够自适应调整学习率。PyTorch 里面已经写好了 Adam 优化器,这个优化器里面有一些超参数需要人为决定,但是往往用 PyTorch 预设的参数就足够好了。

2.4 学习率调度

我们加入自动调整学习率之后,一开始优化的时候很顺利,在左转的时候,有Adagard以后,也可以继续顺利走下去,走到非常接近终点的位置。走到 BC 段时,因为横轴方向的梯度很小,所以学习率会自动变大,步伐就可以变大,从而不断前进。

但是有一个新的问题:图中红圈的地方,快走到终点的时候突然“爆炸”了。 σ i t \sigma_i^t σit是把过去所有的梯度拿来作平均。在 AB段梯度很大,但在 BC 段,纵轴的方向梯度很小,因此纵轴方向累积了很小的 σ i t \sigma_i^t σit,累计到一定程度后,步伐就变很大,但有办法修正回来。因为步伐很大,其会走到梯度比较大的地方。走到梯度比较大的地方后 σ i t \sigma_i^t σit会慢慢变大,更新的步伐大小会慢慢变小,从而回到原来的路线
在这里插入图片描述

学习率调度方法一:学习率衰减(learning rate decay)

在这里插入图片描述

学习率调度方法一:预热(Warm up)
在这里插入图片描述
使用 Warm up 的目的是在训练初期防止模型陷入局部最优解,并帮助模型跳出局部最优点,更好地探索训练空间。通过逐渐增加学习率,模型可以在初始阶段进行更大的权重更新,然后在后期以较小的步伐进行微调。

在这里插入图片描述

其中 m i t m_i^t mit是动量,把过去所有算出梯度的方向做一个加权总和当作更新的方向。接下来的步伐大小为 m i t σ i t \frac{m_i^t}{\sigma_i^t} σitmit,最后通过 η t \eta^t ηt最后通过

在这里插入图片描述

3.朴素贝叶斯理论

朴素贝叶斯(Naive Bayes)是一种简单经典的分类算法

3.1 贝叶斯定理

先验概率:即基于统计的概率,是基于以往历史经验和分析得到的结果,不需要依赖当前发生的条件。

后验概率:则是从条件概率而来,由因推果,是基于当下发生了事件之后计算的概率,依赖于当前发生的条件。

在这里插入图片描述

在这里插入图片描述

3.2 朴素贝叶斯

假设每个特征之间没有联系,给定训练数据集,其中每个样本x都包括n维特征,即 x = ( x 1 , x 2 , x 3 , . . . . . , x n ) x=(x_1,x_2,x_3,.....,x_n) x=(x1,x2,x3,.....,xn),类标记集合含有k种类别,即 y = y 1 , y 2 , . . . . , y n y={y_1,y_2,....,y_n} y=y1,y2,....,yn;

对于给定的新样本x,判断其属于那个类别,根据贝叶斯定理得,x属于类别 y k y_k yk的概率为:
P ( y k ∣ x ) = P ( y k ) P ( x ∣ y k ) P ( x ) = P ( y k ) P ( x ∣ y k ) ∑ i = 0 n P ( y i ) P ( x ∣ y i ) P(y_k|x)=\frac{P(y_k)P(x|y_k)}{P(x)}=\frac{P(y_k)P(x|y_k)}{\sum_{i=0}^{n} P(y_i)P(x|y_i)} P(ykx)=P(x)P(yk)P(xyk)=i=0nP(yi)P(xyi)P(yk)P(xyk)

朴素贝叶斯算法对条件概率分布作出了独立性的假设,通俗地讲就是说假设各个维度的特征 x 1 , x 2 , . . . . . . . . x n x_1,x_2,........x_n x1,x2,........xn互相独立,在这个假设的前提上,条件概率可以转化为: P ( x ∣ y k ) = P ( x 1 , x 2 , . . . . , x n ∣ y k ) = ∏ i = 1 n P ( x i ∣ y k ) P(x|y_k)=P(x_1,x_2,....,x_n|y_k)=\prod_{i=1}^nP(x_i|y_k) P(xyk)=P(x1,x2,....,xnyk)=i=1nP(xiyk)

代入上面贝叶斯公式中,得到:

P ( y k ∣ x ) = P ( y k ) ∏ i = 1 n P ( x i ∣ y k ) P ( x ) P(y_k|x)=\frac{P(y_k)\prod_{i=1}^nP(x_i|y_k)}{P(x)} P(ykx)=P(x)P(yk)i=1nP(xiyk)
= P ( y k ) ∏ i = 1 n P ( x i ∣ y k ) ∑ k = 0 n P ( y k ) ∏ i = 1 n P ( x i ∣ y k ) =\frac{P(y_k)\prod_{i=1}^nP(x_i|y_k)}{\sum_{k=0}^{n} P(y_k)\prod_{i=1}^nP(x_i|y_k)} =k=0nP(yk)i=1nP(xiyk)P(yk)i=1nP(xiyk)

例:

症状 职业 疾病
打喷嚏 护士 感冒
打喷嚏 农夫 过敏
头痛 建筑工人 脑震荡
头痛 建筑工人 感冒
打喷嚏 教师 感冒
头痛 教师 脑震荡

现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?即 P ( 感冒 ∣ 打喷嚏 × 建筑工人 ) P(感冒|打喷嚏×建筑工人) P(感冒打喷嚏×建筑工人)

由朴素贝叶斯得
P ( 感冒 ∣ 打喷嚏 × 建筑工个人 ) P(感冒|打喷嚏×建筑工个人) P(感冒打喷嚏×建筑工个人)
= P ( 打喷嚏 × 建筑工人 ∣ 感冒 ) P ( 感冒 ) P ( 打喷嚏 × 建筑工人 ) =\frac{P(打喷嚏×建筑工人|感冒)P(感冒)}{P(打喷嚏×建筑工人)} =P(打喷嚏×建筑工人)P(打喷嚏×建筑工人感冒)P(感冒)

= P ( 打喷嚏 ∣ 感冒 ) P ( 建筑工人 ∣ 感冒 ) P ( 感冒 ) P ( 打喷嚏 ) P ( 建筑工人 ) =\frac{P(打喷嚏|感冒)P(建筑工人|感冒)P(感冒)}{P(打喷嚏)P(建筑工人 )} =P(打喷嚏)P(建筑工人)P(打喷嚏感冒)P(建筑工人感冒)P(感冒)
= 0.66 × 0.33 × 0.5 0.5 × 0.33 = 0.66 =\frac{0.66×0.33×0.5}{0.5×0.33}=0.66 =0.5×0.330.66×0.33×0.5=0.66

3.3 朴素贝叶斯优缺点

  • 优点:
  1. 朴素贝叶斯模型有稳定的分类效率。
  2. 对小规模的数据表现很好,能处理多分类任务,适合增量式训练,尤其是数据量超出内存时,可以一批批的去增量训练。
  3. 对缺失数据不太敏感,算法也比较简单,常用于文本分类。
  • 缺点:
  1. 需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳
  2. 对输入数据的表达形式很敏感(离散、连续,值极大极小之类的)

总结

我们将所有数据分成若干个 batch,然后对每个 batch 求微分,求损失(Loss)值,根据每个batch的顺序,依次梯度下降优化参数。这样大大加快了梯度下降的计算效率。但是也需要合理选择batch的大小,如果过大,模型参数更新至局部最小点或鞍点处就无法更新。如果过小,模型参数仍可以继续更新,这通过batch间接的解决了局部最小点和鞍点的问题。最后我也了解了动量(momentum),Momentum算法在计算每个梯度的时候会考虑这个梯度在先前更新中的权重,将当前梯度与先前权重的指数加权和相加,然后再通过这个更新结果来更新权重值。这样即便梯度为0时,也可以继续优化参数,跨越局部最小点、鞍点。

同时我知道了如何自动调整学习率,也理解了Adagrad算法的优缺点,Adagrad算法的主要思想是根据每个参数的梯度历史信息来自适应地调整学习率。但是 Adagrad 算法只是针对不同参数而动态改变学习率,为此我们引入了改进后的RMSProp算法,此算法引入了一个衰减系数 α \alpha α用来控制梯度平方累加项的贡献程度,可以根据梯度的值来合理的增大和减少学习率,从而避免出现学习率过大,导致梯度来回震荡。避免学习率过小,梯度下降过程十分缓慢。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 07:32:01       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 07:32:01       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 07:32:01       45 阅读
  4. Python语言-面向对象

    2024-07-22 07:32:01       55 阅读

热门阅读

  1. 2742. 给墙壁刷油漆

    2024-07-22 07:32:01       14 阅读
  2. longjmp和多线程:读写线程实例

    2024-07-22 07:32:01       17 阅读
  3. 【CF】1216F-WiFi 题解

    2024-07-22 07:32:01       17 阅读
  4. 牛客周赛 Round 52VP(附D的详细证明)

    2024-07-22 07:32:01       16 阅读
  5. Android13 应用代码中修改热点默认密码

    2024-07-22 07:32:01       14 阅读
  6. 【React】事件绑定、React组件、useState、基础样式

    2024-07-22 07:32:01       16 阅读
  7. postman接口测试工具详解

    2024-07-22 07:32:01       16 阅读
  8. Symfony数据库抽象层:深入理解其工作原理

    2024-07-22 07:32:01       15 阅读
  9. 设计模式--职责链模式

    2024-07-22 07:32:01       17 阅读
  10. PXIe-6592

    PXIe-6592

    2024-07-22 07:32:01      13 阅读
  11. FPGA 中的 IOE与IO BANK

    2024-07-22 07:32:01       17 阅读
  12. 前端部署后提示用户刷新页面

    2024-07-22 07:32:01       16 阅读
  13. 编写测试用例:策略、技巧与最佳实践

    2024-07-22 07:32:01       17 阅读