结合李宏毅老师《机器学习/深度学习课程》以及《深度学习详解》一书做的笔记,图片并非完全由本人原创,侵删。这里附上视频链接和书本pdf地址:
李宏毅《机器学习/深度学习》2021课程(国语版本,已授权)_哔哩哔哩_bilibili
目录
自适应学习率(adaptive learning rate)的提出
学习率衰减(learning rate decay)/ 学习率退火(learning rateannealing)
Task2.1
一般梯度下降法遇到的尴尬问题
在一般的梯度下降中,学习率()是一个人为设定的固定超参数,相当于在梯度的方向指引下在误差表面向下迈出的一个个“步伐”,学习率的固定意味着“步伐”的固定。我们可以把误差表面想象成一片丘陵,充斥着局部最值与鞍点,如果“地势“平缓,梯度很小,那么我们需要一个较大的”步伐“来快速走出这片”平原“,如果”地势“陡峭,梯度较大,我们则需要较小的”步伐“,以保持梯度下降的稳定,防止震荡。以下是两种情况的直观理解:
学习率(”步伐“)太大引起的问题:
可以直观地看出学习率较大带来的影响,当梯度下降接近局部最值时,梯度下降会因为"步伐"太大而来回摇摆。书上有一张图片更真实的反应了这个现象:
损失表面上的”等高线“非常密集,损失函数的梯度很大,但是参数更新却在来回摇摆,就是因为学习率太大,”步伐“太长。
补:
学习率过大除了导致损失值在训练过程中剧烈波动外,还可能造成其他关键问题:
- 梯度爆炸:虽然现在已经有很成熟的应对方法,比如参数修剪等,这仍然是最严重的问题之一。学习率太大也是梯度爆炸产生的原因之一。
- 数值不稳定性:大的学习率可能会导致数值计算上的不稳定性,比如在参数更新时出现数值溢出。
学习率(”步伐“)太小引起的问题:
最直接的影响是训练速度慢,这也是书中强调的问题,书中同样用一张误差表面图真实反映了这个问题:
在减小了学习率后,振荡现象明显缓解,但是在BC间的”平原“地带,梯度过小+学习率过小导致参数更新速度极慢,出现了梯度消失现象。 此时增加再多的训练次数也难以使之接近局部最小值,梯度下降很难训练。
补:
收敛速度慢只是学习率过小引起的最基础的问题,此外,还有其他一些应该被重视的问题:
- 容易陷入局部最小值:当局部最优值附近梯度很小时,学习率太小可能会导致模型在局部最优值附近徘徊,难以走出这些”坑“。
- 难以克服噪声:实际数据中可能存在噪声或异常值,小的学习率会使模型对噪声异常敏感
- 导致过拟合:小的学习率会导致模型过分细致的为了数据中的某一个波动调整参数,进而导致过拟合
自适应学习率(adaptive learning rate)的提出
鉴于以上问题,人们提出了”自适应学习率“的概念。原理很简单,在误差表面上梯度大、坡度大的”陡坡“,我们就减小学习率,让梯度下降稳定收敛:而梯度小、坡度小的”平原“,我们就增加学习率,增大步伐,加速参数更新。通过这样的方式,使学习率这一深度学习中算是最重要的超参得到灵活的调节。下面介绍几种经典方法。
AdaGrad
AdaGrad(Adaptive Gradient)是典型的自适应学习率方法,其能够根据梯度大小自动调整学习率。AdaGrad 可以做到梯度比较大的时候,学习率就减小,梯度比较小的时候,学习率就放大。
一般梯度下降更新参数 的过程为:
,
表示第次迭代参数对L的微分,这里学习率固定不变
adagrad就是让学习率 变得参数相关,将 改为 ,得:
与迭代次数 ,参数 相关,意味着不同参数、不同迭代次数都将影响学习率
梯度均方根参数相关的adagrad
adagrad一种常见的参数相关的类型是算梯度的均方根。第一次参数更新过程为:
是初始化参数, 的计算过程为:
将 带入得 为1,说明第一次参数更新只与 的大小有关,梯度只控制下降方向
第二次参数更新过程为:
是过去所有梯度的均方根,即为:
...........................
第 次更新参数时,即:
,
我们认为 为新的学习率,用以更新参数
上图直观地对比了不同梯度下的学习率,可以看出在均方根相关的adagrad下,学习率与梯度累积的均方根之间存在反向关系。
拓:
AdaGrad的学习率衰减问题
adagrad的一个主要问题是它的学习率随着参数更新次数的增加而衰减,以上述rms相关的adagrad举例,随着梯度累积的均方根的增加,每个参数的学习率不断降低,这可能导致在训练后期,模型训练的学习率变得非常小,算法收敛速度极慢,难以达到全局最优。特别的,在处理序列数据(如自然语言处理中的长序列数据)时,adagrad的性能会受到影响,因为难以处理大量更新步骤
AdaGrad的对初始学习率敏感问题
通常一般形式的adagrad的参数更新公式为:
是针对参数 从开始到第 轮迭代时累积的梯度平方和:
由上式可看出,初始学习率 直接影响 累积过程的速度。如果 设置过高, 会迅速增大,从而使学习率快速衰减,使得模型在训练后期几乎停止学习,难以收敛。反之,如果 设置过低,尽管学习率的衰减问题可以缓解,但整个训练过程的收敛速度可能会变得过慢。
总结
Adagrad自从被提出以来,在优化算法中举足轻重,尤其是应用在处理稀疏和高维数据的机器学习任务中。它的自适应学习率、简单易用的特性使之流行。尽管现在很多任务中它已不再是首选,在处理学习率衰减问题上基于AdaGrad的RMSProp,Adam等等表现更好,它依然是一个值得学习的合格的基准算法。
RMSProp
补:RMSProp产生的背景——指数加权移动平均(EMA)
EMA常用于时间序列处理和信号处理,它能平滑数据,强调最近的观测值,同时逐步调整最早观测值的影响,与简单移动平均(SMA)相比,EMA对新数据更敏感,适合捕捉快速变化的数据。
EMA的计算公式
对于一个序列 , EMA在时间t的值可以递归地表示为:
- 表示在时间 时的指数加权移动平均值。
- 是加权因子,取值在 [0,1) 之间,通常接近1(如0.9)。它决定了历史数据在当前平均值中的影响程度。
- 是当前时间 的数据点。
EMA的特性
EMA的当前值依赖当前数据点和过去的EMA值 ,使其能够捕捉数据的长期趋势,而加权因子 决定了这一历史依赖性。 值越大,则EMA对较早的数据更为敏感。
第二点是通过逐渐减小较早数据点的权重,通过逐步减小它们的影响,降低短期波动的影响,从而准确反应数据的整体变化趋势,达到平滑数据的效果。
RMSProp计算公式
RMSProp学习率的第一步与Adagrad相同,即:
第二步为更新参数 , (参数含义见AdaGrad)
将同样的操作继续下去:
..........................
其中 , 是一个可以调整的超参数。在AdaGrad里面,每一个参数过去产生的梯度都有相同的重要性;而这里可以自行调整当前梯度的重要性。在第 次参数更新时, 的更新方程为:
当 接近1使,过去的梯度比较重要,反之当前的梯度比较重要。
RMSProp参数更新示例
RMSProp 通过 可以决定, 相较于之前存在 里面的 的重要性有多大。下图展示了一个误差表面:
AB间相对平坦,梯度很小,更新参数时学习率较大;进入BC段,AdaGrad反应较慢,而RMSProp通过减小 ,增加现有梯度的影响,从而积极减小学习率;进入CD段,梯度又变小,这时通过增大 ,增加之前看到的梯度的影响,达到增大学习率的目的。
拓:
RMSProp在深度学习中的应用案例
在图像分类任务中,卷积神经网络(CNN)由于擅长处理图像数据而广泛使用。然而,训练深度CNN时,常常会遇到梯度消失和梯度爆炸问题,尤其是在较深的网络结构中。RMSProp通过调整每个参数的学习率,有效减轻了这一问题。通过自动调整学习率,确保模型在训练过程中稳定收敛。
在处理序列数据,如文本、时间序列预测任务中,由于梯度的累积效应,传统的SGD在长序列训练中可能会导致不稳定的学习过程。通过应用RMSProp,稳定每一个时间步的梯度贡献,从而稳定模型训练。实验结果显示,在字符级文本生成任务中,使用RMSProp优化的LSTM模型比使用SGD更快地收敛,并且生成的文本更加连贯。
RMSProp对学习率的敏感性
尽管RMSProp能够自适应地调整学习率,但它对初始学习率的选择仍然非常敏感。如果学习率设置得太高,模型可能会出现不稳定的收敛,甚至完全不收敛;如果学习率太低,模型则可能会收敛得非常缓慢,导致训练时间显著增加。
由于RMSProp在处理学习率时并没有明确的全局准则,因此在实际应用中,通常需要通过实验来调整合适的学习率,这也会增加调参的复杂性。
RMSProp长期依赖问题
RMSProp利用EMA来平滑梯度的平方和,从而自适应调整学习率。然而,这种平滑技术引入了“长期记忆”的问题,即在长期训练过程中,旧的梯度信息可能会被过度保存,这可能会导致模型在面对新的数据分布时适应性变差。
在某些情况下,RMSProp可能会表现出较慢的响应速度,特别是在模型需要快速适应新的趋势或突然变化时。
总结
尽管RMSProp是一种非常有效的优化算法,仍具有一些固有局限性,在实际应用中时需要仔细调整学习率,可能需要结合其他优化算法一起使用。在更复杂的场景下,Adam算法可能更为适用。
Adam
最常用的优化的策略或者优化器(optimizer)是Adam(Adaptive moment estimation)。Adam 可以看作 RMSprop 加上动量,其使用动量作为参数更新方向,并且能够自适应调整学习率。PyTorch 里面已经写好了 Adam 优化器,这个优化器里面有一些超参数需要人为决定,但是往往用 PyTorch 预设的参数就足够好了。
拓:Adam参数更新方程及超参设置
动量法是在梯度下降中引入过去梯度的累积,使之一定程度考虑到过去的梯度信息,达到加速收敛的目的。特别试用于有较大噪声和长谷的情景。以下是动量法更新公式:
为动量的衰减率(通常取值为0.9), 为动量项,它是当前梯度与过去梯度的指数加权平均。
RMSProp优化器通过引入二阶矩(梯度平方的平均)来调节学习率,更新公式为:
在初始时,动量项和RMSProp项的估计值可能会偏向于零。为了解决这个问题,Adam引入了偏差修正技术。具体公式为:
通过偏差修正,能够更准确地反映梯度的移动平均值,尤其是在初始阶段。
结合动量法和RMSProp的优势,并引入偏差修正,Adam的最终参数更新公式为:
其中:
是一阶矩的偏差修正估计
是二阶矩的偏差修正估计
超参数设置
Adam中的关键超参数包括:
- 学习率 ,通常设置为0.001;
- 动量参数 ,通常设置为0.9;
- 二阶矩参数 ,通常设置为0.999;
- 微小数值 ϵ ,通常设置为 。
公式回顾
总结一下,Adam综合了动量和RMSProp的优点,通过自适应学习率和动量的结合,能够在许多深度学习任务中表现出色,尤其是在处理噪声数据和稀疏梯度时。Adam的更新公式不仅考虑了梯度的一阶矩信息(动量),还考虑了梯度的二阶矩信息(RMSProp),并使用了偏差修正来保证算法的准确性和稳定性。
学习率调度
遇到的问题
在使用AdaGrad时,当梯度下降从梯度较小的位置走到梯度较大的位置时,由于很小的 ,步伐变得很大,就会在梯度较大的位置来回振荡,直到 在振荡中增大,书上的一张图片很直观:
学习率衰减(learning rate decay)/ 学习率退火(learning rateannealing)
可以通过学习率调度来解决。在之前的学习率调整方法中, 是一个定值,而在学习率调度中,与时间有关。随着参数不断更新, 不断减小,加上学习率下降,就能平滑地走到终点。下图是书上加了学习率衰减后的效果:
可以看到梯度下降更加平滑,其中 的变化为:
拓:余弦退火
余弦退火(Cosine Annealing)是一种动态调整学习率的策略,其基本思想是将学习率按一个余弦函数的形式逐步减小,从而在训练接近结束时将学习率调低,以避免模型跳出已经找到的最优解或在最优解附近震荡。是一种很流行的学习率退火的方法
工作原理
余弦退火的公式通常表达为:
其中:
- 是第 t 个训练周期(epoch)的学习率。
- 是最小学习率。
- 是初始最大学习率。
- 是当前的训练周期。
- 是总的训练周期数。
余弦退火的特点和优势
余弦退火通过平滑的方式逐步降低学习率,避免学习率突然下降带来的不稳定性。通常用于神经网络的训练过程,尤其是在使用大数据集和复杂模型(如深度卷积神经网络)时。例如,在训练图像分类模型时,余弦退火可以帮助模型在后期更稳健地收敛到一个更优的解。
学习率调度方式---预热
预热(Warmup)是一种经典的学习率调度策略,旨在在模型训练的初期逐步增加学习率,然后再开始常规的学习率下降过程。这种策略在深度学习中被广泛应用,特别是在残差网络(ResNet)、BERT和Transformer等模型的训练中。
为什么需要预热?
在使用Adam等自适应优化器时,常常需要计算参数的统计特性(如 ),这些统计数据在训练初期往往不够准确。如果在训练初期使用较大的学习率,可能会导致不稳定的训练过程。因此,预热通过在训练的最初阶段使用较小的学习率,帮助优化器收集更加准确的统计数据,缓解初始不稳定性。
在预热过程中,随着统计数据的逐渐准确,学习率也逐步提升至常规水平。例如,在ResNet的训练中,最初的学习率设置为0.01,然后逐步提高到0.1,这种方式被证明比直接使用较大的学习率效果更好。
预热期间使用较小的学习率,还有助于模型更好地探索误差表面,收集有关梯度方向和陡峭程度的信息。这有助于优化器在后续训练中更有效地进行参数更新。
Task2.2
分类
分类与回归问题是机器学习中最常见的问题,二者的区别如下:
分类:分类任务的目标是将输入数据分配到预定义的离散类别中,模型输出的是离散的类别标签。
回归:回归任务的目标是预测连续的数值,模型输出的是一个连续的实数值。
补:独热编码(one-hot 编码)
One-Hot 编码是一种将分类数据(即离散数据)转化为机器学习模型可以处理的数值格式的常用技术。它特别适用于将类别标签转换成模型能够直接使用的输入形式。
One-Hot 编码的核心思想是将每个类别表示为一个二进制向量。假设包含 n 个不同的类别的集合,那么每个类别将被表示为一个长度为 n 的二进制向量,其中只有一个位置为1,其余位置均为0。该位置对应于类别在集合中的位置。
假设我们有三个类别:"红色"、"绿色"和"蓝色"。
- "红色" 被编码为
[1, 0, 0]
- "绿色" 被编码为
[0, 1, 0]
- "蓝色" 被编码为
[0, 0, 1]
one-hot编码的优点与局限性
避免数值大小带来的偏差:通过将类别转换为独立的二进制向量,避免了将类别用数字表示(如1, 2, 3)时,模型可能会误解这些数字之间存在某种顺序或大小关系。原理直观,容易理解应用。
维度增加:如果类别的数量很多,One-Hot 编码会导致生成的向量非常稀疏(大部分值为0),并且维度非常高。这种情况下,计算和存储的开销可能会显著增加。
不适用于高基数特征:当类别数量(基数)非常大时,如用户ID、产品ID等,One-Hot 编码可能会生成巨大的特征矩阵,导致计算资源消耗巨大。因此,在这种情况下,可能需要考虑其他编码方法,如目标编码(Target Encoding)或嵌入(Embeddings)。
softmax函数
在多分类任务中,softmax函数十分常见,它可以将一个未归一化的向量(通常是神经网络的输出)转换为一个概率分布,确保输出向量的每个分量都在0到1之间,并且所有分量的和等于1。这使得Softmax函数特别适合用于分类问题的输出层,其中需要为每个类别分配一个概率值。
对于一个输入向量 ,softmax函数定义为:
其中:
- 是向量中第 个元素
- 是softmax函数在 上的输出值
Softmax函数通过将输入向量中的每个元素通过指数函数进行放大,然后除以所有放大值的总和,来实现归一化。这意味着输入向量中较大的值在输出中的概率分布占比更高,而较小的值占比更低。
补:二分类问题常用的sigmod函数
在二分类问题中,常用的激活函数是 Sigmoid函数。Sigmoid函数能够将任意实数值映射到 (0, 1) 区间内,因此非常适合用于输出概率值,从而表示某一类的可能性。数学表达式为:
Sigmoid函数将输入映射到0和1之间,对于二分类问题,输出值接近1表示正类的概率高,接近0表示负类的概率高。
Sigmoid函数通常作为神经网络输出层的激活函数。其输出被解释为预测属于正类的概率。如输出大于0.5,模型通常会预测为正类;否则,预测为负类。
使用softmax函数作为输出层激活函数的例子
上图是一个以softmax函数作为最后输出层激活函数的例子,最后会输出每个类别归一化后的结果,取最大的值对应的类别为分类类别。
分类问题中的损失函数
举一个用于分类神经网络的例子:
常见的可以用均方差或者交叉熵作为损失函数
均方差损失函数
很直观,计算 与 间距离的方法就是拿出 向量的每一个元素,将差的平方和作为误差
交叉熵损失函数
分类问题中用的最多的损失函数,当 跟 相同时,可以最小化交叉熵的值,此时均方误差也是最小的。最小化交叉熵其实就是最大化似然(maximize likelihood)公式如下:
交叉熵通过计算真实类别的对数概率来衡量模型预测的好坏。当模型预测的概率与真实标签接近时,对数值的绝对值较小,交叉熵损失也较小,反之则较大。交叉熵损失能够有效推动模型优化,使其预测更加准确。
拓:多类别分类中的焦点损失(Focal Loss)
在处理类别不平衡的多分类任务时,标准的交叉熵损失可能导致模型偏向于预测占多数的类别。为此,焦点损失(Focal Loss)被提出,用于减少对易分类样本的关注,并增加对难分类样本的关注。
公式:焦点损失在交叉熵损失的基础上引入了一个调节因子,使得对分类错误的样本的惩罚更大
其中, 是正确类别的预测概率, 和 是调节因子
在物体检测任务中,焦点损失被广泛应用于像Faster R-CNN和RetinaNet这样的模型中,特别是在处理类别不平衡问题时表现突出。Focal Loss通过减少易分类样本的权重,聚焦于那些难以区分的少数类样本,从而改善模型在小物体或罕见类别上的检测性能。