DataWhale AI夏令营-《李宏毅深度学习教程》笔记
- 第三章 深度学习基础
- 补充一些基础
- 临界点及其种类
- 逃离临界点方法
- 批量
- 动量
- 自适应学习率
- 学习率调度
- 分类
- 分类损失
- 批量归一化
之前一直接触的LLM大模型做一些应用,或者传统的自然语言处理,都是直接拿别人的模型用,要不就是在网上找些源码自己改,还有一些视觉识别任务,大多都是应用层面的知识,刚好DataWhale有这次机会可以补充一下深度学习的基础知识。
书籍地址:https://github.com/datawhalechina/leedl-tutorial
也非常建议大家购买纸质版书籍,必看pdf方便多了
第三章 深度学习基础
要想更好地优化神经网络,首先,要理解为什么优化会失败,收敛在局部极限值与鞍点会导致优化失败。
补充一些基础
在本章中会经常提到一些概念,对于一些新手或者数学不是很好的人(example me)来说可能理解起来没那么容易,所以插一节补点基础知识,后续我也会把想到的一些知识都补充在这个部分。
训练网络的过程:为了让更清楚地理解下面所讲述内容的适用范围,这里我给出大家训练网络的过程。
- 首先,数据进入模型之后经过前向传播预测结果 。
- 预测到的结果与标签输入到损失函数中计算损失 。
- 计算到的损失进行反向传播计算梯度(torch提供)。
- 使用优化器利用计算到的梯度来更新网络参数。
循环这个过程就是训练一个深度学习网络所需的大致流程。
梯度:说到梯度,简单点就是导数,其实梯度和导数主要的不同就是,通常我们的数学思维停留在一维空间,在一维空间中函数 f(x)是指f(x)函数在某一点的变化率或斜率。而梯度就是在一个多维空间f(x,y)需要考虑更多的变化,梯度告诉了你函数在每个方向上的变化率(偏导数)。
泰勒级数近似:假设你有一个函数,想知道它在某个点附近的值。直接计算可能很复杂,所以我们用一个“近似”的方法来替代。泰勒级数就是一个这样的近似工具。泰勒级数就是通过加上一阶、二阶、三阶……这样一层一层的近似,把一个复杂的函数变得更容易处理。
softmax:先把所有的 y 取一个指数(负数取指数后也会变成正的),再对其做归一化(除掉所有y的指数值的和)得到y′,主要的目的其实是增大一些值之间的差距,但是现在softmax也被广泛地应用在一些注意力机制里面,来对特征进行加权处理。
sigmiod:将特征映射到(0,1)之间,常常被作为激活函数使用
临界点及其种类
一般深度学习任务中,当梯度为零(梯度不在下降,模型收敛在了临界点)的时候大多数考虑的都是局部最小值点。但除了局部最小值点之外还有一个梯度为零的点就是鞍点。
如果损失收敛在局部极小值,我们所在的位置已经是损失最低的点了,往四周走损失都会比较高,就没有路可以走了。但鞍点没有这个问题,旁边还是有路可以让损失更低的。只要逃离鞍点,就有可能让损失更低。
(本文属于读书笔记图片均来自《李宏毅深度学习教程》)
判断一个临界点到底是局部极小值还是鞍点需要知道损失函数的形状。可是如何直到损失函数的形状呢,而且随着网络的变化损失函数可能各不相同,虽然想知道损失函数的形状几乎不可能,但是可以近似,通过泰勒级数近似我们可以大致估算出损失函数的形状。
到这数学不好的可能有些蒙了其实没什么难的,这个公式就是之前知识补充中提到的三项泰勒级数近似,这里的第二项因为含有g(梯度)我们在考虑的时候可以把他去除,因为我们考了就是梯度为零的情况,这样式子就已经简化了很多了,接下来其实我们就可以根据第三项来推断临界点附近的形状了。
如果第三项>0,就意味着**L(θ)>L(θ′)**也就是在只要 θ 在 θ′ 附近,L(θ) 都大于 L(θ′). 这代表 L(θ′) 是附近的一个最低点,所以它是局部极小值。
如果第三项<0,这意味着对任意θ,L(θ)<L(θ′),θ′ 是附近最高的一个点,L(θ′) 是局部极大值。
如果对于第三项有时候大于零,有时候小于零。这意味着在 θ′ 附近,有时候L(θ) > L(θ′),有时候 L(θ) < L(θ′). 因此在 θ′ 附近,L(θ′) 既不是局部极大值,也不是局部极小值,而是鞍点。
其实说到这即使你不懂也没关系,因为公示的第三项涉及到了二次微分计算,对矩阵运算的话计算量很大,所以这不是一个常用的方法去逃离局部最小值点或者鞍点。
逃离临界点方法
李老师在这里补充了一个点,我觉得还是很有必要的,就是维度,因为深度学习之所以被称为黑盒子很大原因是因为他大多数计算都是高位空间的数据计算,而这个人脑很难理解。这里老师举了一个具体的例子。比如在一维空间中某个点可能是我们无法处理的局部最小值点,然如果我们给他加了一个参数,把他加到二维空间他很和可能会变成一个可以逃离的鞍点,那么在加一个参数到三维空间会不会这个点就是一个正常的收敛点呢?
老师在书中也提到了“多数的时候,我们训练到一个梯度很小的地方,参数不再更新,往往只是遇到了鞍点。”
批量
批量就是batch,这个其实比较好理解也是我们经常接触的参数。每次在更新参数的时候,会去取出B笔数据用来计算出损失和梯度更新参数。遍历所有批量的过程称为一个回合(epoch)。
这部分李老师提出了一个经验概念,就是越小的批量,可能会引入更多的噪声,但对于模型逃离局部极小值点和鞍点有更好地帮助。
假设用L1 算梯度的时候,梯度是零,就会卡住。但L2的函数跟L1又不一样,L2不一定会卡住,可以换下个批量的损失L2 计算梯度,模型还是可以训练,还是有办法让损失变小,所以这种有噪声的更新方式反而对训练其实是有帮助的。
小批量虽然在多数情况下可能对损失下降有一定的帮助,但是对于模型的训练速度可能会降低,同一个epoch,小批量需要更多长的训练时间。
动量
动量法(momentum method)是另外一个可以对抗鞍点或局部最小值的方法。类似与物理学中的概念当一个物体从高处滚落,遇到一个凹点他不会马上停住而会因为惯性继续向前。
引入动量后,每次在移动参数的时候,不是只往梯度的反方向来移动参数,而是根据梯度
的反方向加上前一步移动的方向决定移动方向。
自适应学习率
临界点其实不一定是在训练一个网络的时候会遇到的最大的障碍,有时候,训练一个网络,训练到后来发现损失不再下降的时候,有时候不是卡在局部最小值或鞍点,只是单纯的损失无法再下降。这个时候往往需要通过调整更适合的学习率来帮助模型收敛。
换句话说,当梯度大的时候,学习率就小一些,梯度小的时候,学习率就大一些。
如图对于平坦的山谷,梯度比较小,我们也就需要迈步子更大一些,帮助模型更好的走出局部最小值点和鞍点,当更尖锐的山谷时,梯度变化较大,所以学习率也要适当减小,减少步子,以免偏差太大。
这部分书中提到了三种优化器:
- AdaGrad:AdaGrad(Adaptive Gradient)是典型的自适应学习率方法,其能够根据梯度大小自动调整学习率。
- RMSProp:与AdaGrad不同之处在于,通过可调节的超参数α来决定那些梯度更重要,而AdaGrad的梯度都是同等重要的。
- Adam:最常用的优化的策略或者优化器(optimizer)是Adam(Adaptive moment estima
tion)。Adam 可以看作 RMSprop 加上动量,其使用动量作为参数更新方向,并且能够自
适应调整学习率。PyTorch 里面已经写好了 Adam 优化器,这个优化器里面有一些超参数需
要人为决定,但是往往用PyTorch预设的参数就足够好了。
学习率调度
在深度学习中,学习率决定了每次更新参数的步伐。如果学习率太大,模型可能会在损失函数的最小值附近来回跳动,甚至错过最优解。如果学习率太小,模型的训练速度会非常慢,而且可能陷入局部最优解。学习率衰减(学习率退火)是一种逐渐减小学习率的策略,通常在训练的后期使用,以便模型能够更精细地调整参数,从而找到更好的局部最优解。其实就是到训练后期了,适当的让学习率低一些,以免出现一些差错。
除了学习率下降以外,还有另外一个经典的学习率调度的方式—预热。预热的方法是让学习率先变大后变小,至于变到多大、变大的速度、变小的速度是超参数。残差网络里面是有预热的,在残差网络里面,学习率先设置成0.01,再设置成0.1,并且其论文还特别说明,一开始用0.1反而训练不好。除了残差网络,BERT和Transformer的训练也都使用了预热。
分类
分类与回归是深度学习最常见的两种问题
回归问题举个例子比如,预测明天的天气,明天的股市,要一个值或者一些数据这种都属于回归问题的范畴。
分类问题比如情感分类“一件商品好或者不好”“开心或者不开心”“明天到底是阴天还是晴天还是雨天”,这种都属于分类问题。
分类损失
计算分类损失的方式有很多种,比如均方误差。即y 里面每一个元素拿出来,计算它们的平方和当作误差。
交叉熵更常用,当 ˆ y跟y′ 相同时,可以最小化交叉熵的值,此时均方误差也是最小的。最小化交叉熵其实就是最大化似然
批量归一化
如果误差表面很崎岖,它比较难训练。能不能直接改误差表面的地貌,“把山铲平”,让它变得比较好训练呢?批量归一化(BatchNormalization,BN)就是其中一个“把山铲平”的想法。现在BN以及成为了深度学习领域必不可少的一个模块。
那为什么需要归一化呢,我通俗的解释一下李老师书中提到的例子,以这个简单的线性模型为例,相当于,如果你的输入数据x1很小,那么即使乘w1变化很大,那么对于结果y的影响也很小,这样对loss影响也很小。反之如果x2是一个非常大的数据,即使w2轻微地改变也会导致y产生较大的变化,这样带动的loss也会大幅变化。这样就形成了较为陡峭的误差表面。