系列文章
李沐《动手学深度学习》预备知识 张量操作及数据处理
李沐《动手学深度学习》预备知识 线性代数及微积分
李沐《动手学深度学习》线性神经网络 线性回归
李沐《动手学深度学习》线性神经网络 softmax回归
李沐《动手学深度学习》多层感知机 模型概念和代码实现
李沐《动手学深度学习》多层感知机 深度学习相关概念
李沐《动手学深度学习》深度学习计算
李沐《动手学深度学习》卷积神经网络 相关基础概念
李沐《动手学深度学习》卷积神经网络 经典网络模型
李沐《动手学深度学习》循环神经网络 相关基础概念
李沐《动手学深度学习》循环神经网络 经典网络模型
李沐《动手学深度学习》注意力机制
目录
- 系列文章
- 一、优化和深度学习
- (一)优化的目标
- (二)深度学习中优化的挑战
- 二、凸性
- (一)凸性的相关定义
- (二)凸函数的性质
- (三)约束
- 三、梯度下降
- (一)一维梯度下降
- (二)多元梯度下降
- (三)自适应方法
- 四、随机梯度下降
- (一)随机梯度下降法的概念
- (二)动态学习率
- (三)凸目标的收敛性分析
- 五、小批量随机梯度下降
- (一)向量化和缓存
- (二)从数据中有效地生成小批量
教材:李沐《动手学深度学习》
一、优化和深度学习
(一)优化的目标
- 优化的目标是减少训练误差,而深度学习的目标是减少泛化误差。(深度学习除了使用优化算法减少训练误差之外,还需要注意过拟合)
- 在深度学习中,大多数目标函数都很复杂,没有解析解。相反,我们必须使用数值优化算法。
(二)深度学习中优化的挑战
1. 局部最小值问题
对于任何目标函数 f ( x ) f(x) f(x),如果在 x x x处对应的 f ( x ) f(x) f(x)值小于在附近任意其他点的 f ( x ) f(x) f(x)值,那么 f ( x ) f(x) f(x)可能是局部最小值。如果 f ( x ) f(x) f(x)在 x x x处的值是整个域中目标函数的最小值,那么 f ( x ) f(x) f(x)是全局最小值。
深度学习模型的目标函数通常有许多局部最优解。当优化问题的数值解接近局部最优值时,随着目标函数解的梯度接近或变为零,通过最终迭代获得的数值解可能仅使目标函数局部最优,而不是全局最优。只有一定程度的噪声可能会使参数跳出局部最小值。
2. 鞍点
鞍点(saddle point)是指函数的所有梯度都消失但既不是全局最小值也不是局部最小值的任何位置。
假设函数的输入是k维向量,其输出是标量,因此其Hessian矩阵(也称黑塞矩阵)将有k个特征值。函数的解可能是局部最小值、局部最大值或函数梯度为零位置处的鞍点:
- 当函数在零梯度位置处的Hessian矩阵的特征值全部为正值时,我们有该函数的局部最小值;
- 当函数在零梯度位置处的Hessian矩阵的特征值全部为负值时,我们有该函数的局部最大值;
- 当函数在零梯度位置处的Hessian矩阵的特征值为负值和正值时,我们有该函数的一个鞍点。
3. 梯度消失
- 梯度消失是深度学习优化过程中可能遇到的最隐蔽问题;
- 梯度消失可能会导致优化停滞,重参数化通常会有所帮助,对参数进行良好的初始化也可能是有益的;
- 例如,以下函数如果恰好从 x = 4 x=4 x=4开始,其梯度接近0,因此在我们取得进展之前优化将会停滞很长一段时间。
二、凸性
(一)凸性的相关定义
-
凸集
- 凸集(convex set)是凸性的基础
- 如果对于任何 a , b ∈ χ a,b \in{\chi} a,b∈χ,连接 a a a和 b b b的线段也位于 χ \chi χ中,则向量空间中的一个集合 χ \chi χ是凸的,也就是对于所有$\lambda \in [0,1]:
λ a + ( 1 − λ ) b ∈ χ , 当 a , b ∈ χ \lambda a+(1-\lambda)b\in \chi,当a,b\in \chi λa+(1−λ)b∈χ,当a,b∈χ
- 凸集的交集是凸的,并集不是
-
凸函数
给定一个凸集 χ \chi χ,如果对于所有 x x x, x ′ ∈ χ x'\in \chi x′∈χ和所有 λ ∈ [ 0 , 1 ] \lambda\in[0,1] λ∈[0,1],函数 f f f是凸的,就会有:
λ f ( x ) + ( 1 − λ ) f ( x ′ ) ≥ f ( λ x + ( 1 − λ ) x ′ ) \lambda f(x)+(1-\lambda)f(x')\ge f(\lambda x+(1-\lambda)x') λf(x)+(1−λ)f(x′)≥f(λx+(1−λ)x′) -
詹森不等式
詹森不等式:凸函数的期望不小于期望的凸函数( α i \alpha_i αi是满足 ∑ i α i = 1 \sum_i{\alpha_i} =1 ∑iαi=1的非负实数, X X X是随机变量)
詹森不等式的一个常见应用:用一个较简单的表达式约束一个较复杂的表达式
(二)凸函数的性质
- 凸函数的局部极小值也是全局极小值
- 凸函数的下水平集是凸的
给定一个定义在凸集 χ \chi χ上的凸函数 f f f,其任意一个下水平集
S b : = x ∣ x ∈ χ a n d f ( x ) ≤ b S_b:={x|x\in \chi and f(x)\le b} Sb:=x∣x∈χandf(x)≤b
是凸的。
- 一个二次可微函数是凸函数,当且仅当其Hessian(二阶导数矩阵)是半正定的
(三)约束
凸优化能够让我们有效地处理约束,它使我们能够解决以下形式的约束优化问题:(其中 f f f是目标函数, c i c_i ci是约束函数)
满足约束条件的优化策略有多种:
- 拉格朗日函数
通常,求解一个有约束的优化问题是困难的,解决这个问题的一种方法来自物理中相当简单的直觉。 想象一个球在一个盒子里,球会滚到最低的地方,重力将与盒子两侧对球施加的力平衡。 简而言之,目标函数(即重力)的梯度将被约束函数的梯度所抵消(由于墙壁的“推回”作用,需要保持在盒子内)。 请注意,任何不起作用的约束(即球不接触壁)都将无法对球施加任何力。
拉格朗日函数:
拉格朗日函数是一种将带有约束条件的优化问题转化为无约束问题的方法。
鞍点优化问题:
鞍点优化问题则是指在优化过程中遇到的一种特殊情况,即目标函数既有局部最小值又有局部最大值的点。
鞍点优化问题与拉格朗日函数在优化理论中有一定的联系,尤其是在处理约束优化问题时
- 在拉格朗日函数的框架下,鞍点可以对应于拉格朗日函数的临界点,即导数为零的点,但其在某些方向上是局部最大值,而在其他方向上是局部最小值。
- 在解决约束优化问题时,通常会通过求解拉格朗日函数的鞍点来找到最优解。这包括求解拉格朗日函数对原始变量和拉格朗日乘子的偏导数为零的点,然后通过一些方法(如KKT条件)来验证这些点是否为最优解,以及如何选择适当的拉格朗日乘子。
- 因此,拉格朗日函数与鞍点优化问题之间存在一定的联系,尤其在处理带约束条件的优化问题时,可以借助拉格朗日函数的框架来求解鞍点和最优解。
只需要知道拉格朗日函数的鞍点是原始约束优化问题的最优解就足够了。
- 惩罚
- 添加惩罚是确保近似满足约束的一种好方法。
- 通过将约束条件的违反程度加入到目标函数中,构建一个惩罚项,使得在优化过程中约束条件被尽可能满足。常用的罚函数包括线性罚函数、二次罚函数等。
- 在实践中,这被证明比精确的满意度更可靠。 此外,对于非凸问题,许多使精确方法在凸情况下的性质(例如,可求最优解)不再成立。
- 投影
在每一步中,将当前点投影到约束集合上,以确保满足所有约束条件,然后沿着负梯度方向移动一定步长,直到满足收敛条件或达到最大迭代次数为止。
投影法的步骤:
- 初始化:选择一个初始点作为优化的起始点。
- 迭代:在每一步中,计算当前点关于目标函数的梯度,并计算该点到约束集合的投影。然后,沿着负梯度方向移动一定步长,直到满足收敛条件或达到最大迭代次数为止。
- 投影:在每一步中,通过将当前点投影到约束集合上来确保满足所有约束条件。这可以通过将当前点调整为约束集合内最近的点来实现。
- 收敛检查:检查当前点是否满足收敛条件,例如梯度的大小小于某个阈值,或者目标函数的变化量小于某个阈值。
投影法的优缺点:
优点:可以确保在每一步中都满足约束条件,因此适用于处理具有复杂约束的优化问题
缺点:由于每一步都需要进行投影操作,因此可能会增加计算成本。此外,投影法并不保证收敛到全局最优解,而只是保证在每一步都满足约束条件。
三、梯度下降
(一)一维梯度下降
一维梯度下降是一种优化算法,用于求解只有一个自变量的函数的最小值。
- 学习率:决定目标函数能否收敛到局部最小值,以及何时收敛到最小值;
- 一维梯度下降方法在求解简单的单变量函数的最小值时比较有效。但对于复杂的多变量函数,通常需要使用更高维度的优化算法。
(二)多元梯度下降
多元梯度下降用于求解具有多个自变量的函数的最小值。
- 多元梯度下降方法对于具有多个自变量的函数求解非常有效,但它可能会陷入局部最优解,特别是当函数具有多个局部最优解时。因此,在实际应用中,可能需要多次运行算法,或者结合其他优化算法来提高全局最优解的概率。
(三)自适应方法
自适应方法是一类优化算法,其学习率(步长)在优化过程中可以根据数据的特性进行自适应调整,以提高算法的性能和收敛速度。这些方法通常能够有效地应对不同维度、不同方向的梯度变化幅度不同的情况,从而更好地适应复杂的优化问题。
牛顿法(Newton’s method):
-
牛顿法是一种基于二阶导数信息的优化算法,用于求解无约束优化问题的最优解。它利用了目标函数的二阶导数(Hessian矩阵)信息,通过迭代更新当前点的位置,以逼近最优解。
-
牛顿法的基本步骤:
- 初始化:选择一个初始点 x 0 x_0 x0作为优化的起始点;
- 迭代更新:在每一步中,计算当前点 x k x_k xk处的目标函数的梯度 ∇ f ( x k ) \nabla f(x_k) ∇f(xk)和二阶导数(Hessian矩阵) H ( x k ) H(x_k) H(xk),然后通过求解方程 H ( x k ) Δ x = − ∇ f ( x k ) H(x_k)\Delta x=-\nabla f(x_k) H(xk)Δx=−∇f(xk)来计算更新步长 ∇ x \nabla x ∇x,最后更新当前点的位置: x k + 1 = x k + Δ x x_{k+1}=x_k+\Delta x xk+1=xk+Δx
- 收敛检查:检查当前点的函数值是否满足停止条件,例如函数值的变化量小于某个阈值,或者梯度的大小小于某个阈值。
- 迭代终止:如果满足停止条件,则停止迭代,输出当前点作为最优解;否则,继续进行下一轮迭代。
-
牛顿法通过利用二阶导数信息,通常能够更快地收敛到函数的最优解,尤其对于二次函数或近似二次函数的优化问题效果很好。然而,牛顿法可能会受到Hessian矩阵的不可逆性、计算代价较高以及局部收敛性等问题的影响。
-
通过对牛顿法进行预处理,可以降低计算成本:计算和存储完整的Hessian非常昂贵, 预处理回避了计算整个Hessian,而只计算“对角线”项。预处理有助于调节比例。
梯度下降和线搜索:
-
梯度下降:基于目标函数梯度信息的优化算法,其基本思想是沿着梯度的反方向迭代地更新当前点的位置,以减小函数值
-
线搜索:在每一步中确定适当的步长(学习率),以保证函数值在移动方向上能够减小。
-
结合使用线搜索和梯度下降:梯度下降的一个关键问题是我们可能会超过目标或进展不足, 解决这一问题的简单方法是结合使用线搜索和梯度下降。 也就是说,我们使用给出的方向(梯度), 然后进行二分搜索,以确定哪个学习率使取最小值。
四、随机梯度下降
(一)随机梯度下降法的概念
随机梯度下降法(Stochastic Gradient Descent,简称SGD)是梯度下降算法的一种变体,主要用于大规模数据集的优化问题。与传统的梯度下降法不同,SGD每次更新参数时只利用部分数据(即随机抽取的一个样本或者一小批样本),而不是全部数据,从而减少了计算量和内存消耗。
(二)动态学习率
随机梯度下降法采用动态学习率的原因:
由于在梯度中注入了不确定性的影响,随机梯度下降中变量的轨迹会比一般的梯度下降法中的轨迹嘈杂许多,即使经过多次迭代,最终的效果也不那么好,因此需要我们改变学习率。但是,如果我们选择的学习率太小,我们一开始就不会取得任何有意义的进展。另一方面,如果我们选择的学习率太大,我们将无法获得一个好的解决方案。解决这些相互冲突的目标的唯一方法是在优化过程中动态降低学习率。
动态学习率:
随机梯度下降法(SGD)的动态学习率是一种技术,用于根据优化过程中的迭代次数或其他指标来自适应地调整学习率的大小。
几种常见的动态学习率调整方法:
- 学习率衰减
- 学习率衰减是一种简单而有效的动态学习率调整方法,其思想是随着优化的迭代次数增加,逐渐降低学习率的大小,以确保算法在接近最优解时收敛更稳定。
- 常见的学习率衰减方法包括指数衰减、多项式衰减、余弦退火等。
- 动态调整
- 动态调整方法根据优化过程中的实时信息来自适应地调整学习率。例如,AdaGrad 算法通过累积梯度的平方来调整学习率,使得在训练过程中稀疏特征对应的学习率较大,而常见特征对应的学习率较小,从而适应不同特征的重要性。
- 其他常见的动态调整方法还包括 RMSprop、Adam 等,它们通过考虑梯度的历史信息来调整学习率,从而实现更加自适应的优化过程。
- 学习率预热
- 学习率预热是一种在优化开始阶段逐渐增加学习率的方法,以帮助算法更快地找到合适的优化方向。预热阶段通常采用较小的学习率,然后逐渐增加到设定的初始学习率。
(三)凸目标的收敛性分析
对于凸目标函数的随机梯度下降,可以通过理论分析、收敛速度分析、期望收敛性分析以及实验验证等方法来评估算法的收敛性和性能。通过合理选择学习率、样本大小等超参数,并满足一定的函数性质条件,可以保证随机梯度下降在凸目标函数上的有效收敛。
五、小批量随机梯度下降
小批量随机梯度下降法是使用完整数据集来计算梯度并更新参数的梯度下降法和一次处理一个训练样本来取得进展的随机梯度下降法的折中方案。
(一)向量化和缓存
向量化和缓存是优化算法执行速度的两种重要方法,特别在涉及大规模数据集或高维度数据时更为重要。
向量化:
- 概念:向量化是一种通过将操作应用于整个向量或矩阵而不是单个元素来提高代码执行效率的技术。在许多编程语言和库中,如NumPy、TensorFlow和PyTorch等,都支持向量化操作,可以在底层使用高效的线性代数库来加速运算。
- 优势:通过向量化,可以避免使用显式的循环,从而减少了不必要的迭代和内存访问开销,提高了代码的执行效率。
- 适用场景:向量化特别适用于处理大规模数据集或高维度数据的情况,例如在机器学习中的特征处理、模型预测等过程中,都可以通过向量化来加速计算。
缓存:
- 概念:缓存是一种将计算结果存储在内存中以供后续使用的技术。通过缓存,可以避免重复计算已经计算过的结果,从而减少计算时间。
- 优势:通过缓存,可以显著减少重复计算的次数,特别是对于计算密集型任务,可以极大地提高代码的执行效率。
- 适用场景:缓存特别适用于需要多次重复计算相同结果的情况,例如在递归算法、动态规划算法等中,可以通过缓存来避免重复计算子问题的结果。
(二)从数据中有效地生成小批量
#@save
#使用NASA开发的测试机翼的数据集不同飞行器产生的噪声
d2l.DATA_HUB['airfoil'] = (d2l.DATA_URL + 'airfoil_self_noise.dat','76e5be1548fd8222e5074cf0faae75edff8cf93f')#@save
def get_data_ch11(batch_size=10, n=1500):data = np.genfromtxt(d2l.download('airfoil'),dtype=np.float32, delimiter='\t')#将数据转换为pytorch的张量,并对数据进行标准化data = torch.from_numpy((data - data.mean(axis=0)) / data.std(axis=0))#创建数据迭代器,用于生成指定批量大小的数据样本data_iter = d2l.load_array((data[:n, :-1], data[:n, -1]),batch_size, is_train=True)return data_iter, data.shape[1]-1