# ADAM与二阶优化算法的联系

By [jingz0.eth](https://paragraph.com/@jingz0) · 2022-05-29

---

* * *

ADAM（Adaptive Moment Estimation）对参数向量 的更新式是这样的：

![\textbf{v}\leftarrow \beta\_1\textbf{v}+\left(1-\beta\_1\right)\nabla f\left(\textbf{w}\right)\\\\textbf{s}\leftarrow\beta\_2\textbf{s}+\left(1-\beta\_2\right)\nabla f\left(\textbf{w}\right) \odot \nabla f\left(\textbf{w}\right)\\\\textbf{w}\leftarrow \textbf{w}-\eta \frac{\textbf{v}}{\sqrt{\textbf{s}}}](https://storage.googleapis.com/papyrus_images/689175240869be1fcf8b0cab4a9262dc9acbb93fa2d3ac2208385c65136f12b1.svg)

\\textbf{v}\\leftarrow \\beta\\\_1\\textbf{v}+\\left(1-\\beta\\\_1\\right)\\nabla f\\left(\\textbf{w}\\right)\\\\\\\\textbf{s}\\leftarrow\\beta\\\_2\\textbf{s}+\\left(1-\\beta\\\_2\\right)\\nabla f\\left(\\textbf{w}\\right) \\odot \\nabla f\\left(\\textbf{w}\\right)\\\\\\\\textbf{w}\\leftarrow \\textbf{w}-\\eta \\frac{\\textbf{v}}{\\sqrt{\\textbf{s}}}

表示“赋值”，将右边计算出来的值赋给左边。我们先看第一个更新式，它用一个位于 区间的参数 乘当前 向量（数乘），再用 乘损失函数 在当前参数 处的梯度 。迭代一开始时，可将 设为零向量。 一般取接近 1 的值，比如 0.9 。这其实是以滑动平均将 在迭代过程中每个参数向量 位置处的梯度积累到向量 中。如果我们直接用 向量更新参数向量 ，这就是冲量法（Momentum）。向量 积累了 的历史梯度，削弱了梯度的随机变化，本质上这也是一种正则化手段。 作为滑动平均的衰减系数，在接近 1 时会更多保留梯度历史信息。当前 处的梯度经过很小的缩放（ ）才进入 中。 越大则“惯性”越大。

第二个式子仍是一个滑动平均，衰减系数为 （一般取 0.99）。信息被积累在向量 中，这次积累的信息是 。符号 表示将两个向量的对应元素相乘，得到一个新向量。于是 的每个分量就是 对应分量的平方。可以简单说它是梯度 的“平方”。

最后终于来到了参数向量 的更新式。 是学习率（Learning Rate）。首先 表示将向量 的各分量开方。 积累了历史梯度的分量平方，使用时需要把每个分量开方，使它回到与梯度同样的数量级。 表示用 的各分量除以 的对应分量。如果这里不是 ，而是 ，则 就是用积累的历史梯度各分量的平方的开方，来除当前梯度的各分量，这其实就是 RMSProp 法。本质上，它是对当前梯度的各分量施加不同的“惩罚”。若梯度的某个分量在历史上一直有较大的绝对值，则 的相应分量会积累一个较大的值，用 的这个分量的开方去除当前梯度的对应分量，相当于对当前梯度的这个分量施加了一个较大的“惩罚”。若梯度的某个分量的绝对值在历史上一直较小，则对当前梯度对应分量的“惩罚”就会较轻。滑动平均衰减系数 和 都小于 1 ，所以过于“久远”的历史梯度就会被慢慢“遗忘”掉。我们通过一个具体例子来看一下这么做的意义：

![](https://storage.googleapis.com/papyrus_images/3da96e17630c0565dbc99e73f5328425350a84158ef9cdd15febc2e05d917f8b.jpg)

狭长峡谷中的梯度下降

上图中，待优化的函数 是一个比较“病态”的二元（两个自变量）二次函数。它的赫森矩阵（Hessian Matrix）是正定的（Positive Definite），它的两个特征值都为正，但是一大一小，相差较大。 在大特征值的特征方向上的二阶导大，在小特征值的特征方向上的二阶导小，于是这个函数的等高线（Contour）是非常“扁”的椭圆：长轴长，短轴小。

上图的四个子图分别是采用不同学习率的（原始）梯度下降法。但无论学习率是大是小，梯度在大特征值的特征方向上的分量总是大于在小特征值方向上的分量，它总是指向“狭长峡谷”的“对岸”，而不是指向谷底最低位置。这就导致了（原始）梯度下降法的“震荡”（如左上）。若学习率取得更大，甚至有可能跃上“对岸”更高处，导致训练不收敛。后面三个子图采用了更小的学习率，从轨迹上看是抑制了震荡，但是代价是更多的迭代步数，更长的训练时间。现在若我们采用 RMSProp 法，则起到的效果如下图示意：

![](https://storage.googleapis.com/papyrus_images/65712a2802485e11297c3287de3915e202b90d72c020fc1d78e72326abc0a901.jpg)

RMSProp 对（反）梯度方向的修正

上图展示了“峡谷”损失函数 的等高线图。注意这里我们取了一个比较简单的情况，即 的赫森矩阵是对角阵（非对角线元素为 0 ），所以它的两个特征方向就是自变量的两个坐标轴。纵轴是较大特征值的特征方向， 在该方向上有较大二阶导数，所以函数值快速下降又快速上升，这是横穿峡谷的方向。横轴是较小特征值的特征方向， 在该方向上有较小的二阶导数，函数值缓慢下降再缓慢上升，这是沿着谷底行走的方向。假设 位于图中所示的位置， 在 处的（反）梯度是图中标记为 的箭头。它指向了对岸，而不是最优点（原点）。

在当前以及历史上，梯度沿纵轴的分量一直（绝对值）较大，沿横轴的分量一直（绝对值）较小。于是 在纵轴上的分量较大，在横轴上的分量较小。经过除以 的“惩罚”，（反）梯度的纵轴分量被缩短较多，横轴分量被缩短较小。于是我们看到，经过调整后的 向量一定程度上偏向了指向原点的方向。这就是 RMSProp 的作用，它以不同的强度惩罚梯度的不同分量，调整（反）梯度方向，减弱二阶导较大的方向的影响。而 ADAM 综合了冲量法和 RMSProp 法。现在我们从一个更有趣、更深刻的角度来看待这些方法。

* * *

一个函数（数学上需要满足的严格条件我们不说了，就默认都满足） 可以在自变量 处泰勒展开：

![f\left(\textbf{w}+d\textbf{w}\right)=f\left(\textbf{w}\right)+\nabla f\left(\textbf{w}\right)^Td\textbf{w}+\frac{1}{2}d\textbf{w}^T\textbf{H}\_{\textbf{w}}d\textbf{w}+O\left(\left|d\textbf{w}\right|^2\right)](https://storage.googleapis.com/papyrus_images/e512af6396e01cf99559b3a4a1cc17542c3f52ac18458ec557b9b552d91f1b96.svg)

f\\left(\\textbf{w}+d\\textbf{w}\\right)=f\\left(\\textbf{w}\\right)+\\nabla f\\left(\\textbf{w}\\right)^Td\\textbf{w}+\\frac{1}{2}d\\textbf{w}^T\\textbf{H}\\\_{\\textbf{w}}d\\textbf{w}+O\\left(\\left|d\\textbf{w}\\right|^2\\right)

是对于变化向量 的长度 的二阶无穷小量。这不是重点，我们不详述，就认为它是可忽略的误差即可。 是从 出发的一个变化向量。函数 在新位置 处的值等于右边。右边第一项是函数 在原位置 处的值。第二项是函数 在原位置 处的梯度 与变化向量 的内积。到这一项为止是一阶泰勒展开。

函数 在 处沿任意方向（用单位向量 表示）的方向导数等于 在 处的梯度 与 的内积。沿变化向量 的单位向量是 ，于是 沿该方向的方向导数是： 。沿该方向前进的距离是 ，所以自变量发生变化 后函数值变化量的一阶（线性）近似是（方向导数乘上移动距离） 。这正是泰勒展开的第二项。方向导数既然是 ， 是 与 之间的（锐）夹角，那么当 ，即 ，也就是 取梯度反方向时，函数有最小（负）的方向导数。**梯度反方向是函数值瞬时下降最快的方向**，这就是梯度下降法的原理。

一阶泰勒展开是在局部用线性函数近似拟合原函数。如果纳入上式的第二项，就是函数在 处的二阶泰勒展开。这一项是关于变化向量 的二次型（Quadratic Form）。二阶泰勒展开是在局部用二次函数近似拟合原函数。矩阵 是函数 在 处的赫森矩阵（Hessian Matrix），它是：

![\textbf{H}\_{\textbf{w}}=\left(\begin{array}{ccc}\frac{\partial f}{\partial w\_1\partial w\_1}\left(\textbf{w}\right) \\\\frac{\partial f}{\partial w\_1\partial w\_2}\left(\textbf{w}\right) \\\\vdots\\\\frac{\partial f}{\partial w\_1\partial w_n}\left(\textbf{w}\right) \end{array}\begin{array}{ccc}\frac{\partial f}{\partial w\_2\partial w\_1}\left(\textbf{w}\right) \\\\frac{\partial f}{\partial w\_2\partial w\_2}\left(\textbf{w}\right) \\\\vdots\\\\frac{\partial f}{\partial w\_2 \partial w_n}\left(\textbf{w}\right)\end{array}\begin{array}{ccc}\cdots\\\\cdots\\\\ddots\\\\cdots\end{array}\begin{array}{ccc}\frac{\partial f}{\partial w_n \partial w\_1}\left(\textbf{w}\right) \\\\frac{\partial f}{\partial w_n \partial w\_2}\left(\textbf{w}\right) \\\\vdots\\\\frac{\partial f}{\partial w_n \partial w_n}\left(\textbf{w}\right)\end{array}\right)](https://storage.googleapis.com/papyrus_images/4a4a4bbbc342e34bb401f9e2b7b7ce1e4e8f54b0449191eb6ab587fde343fa8b.svg)

\\textbf{H}\\\_{\\textbf{w}}=\\left(\\begin{array}{ccc}\\frac{\\partial f}{\\partial w\\\_1\\partial w\\\_1}\\left(\\textbf{w}\\right) \\\\\\\\frac{\\partial f}{\\partial w\\\_1\\partial w\\\_2}\\left(\\textbf{w}\\right) \\\\\\\\vdots\\\\\\\\frac{\\partial f}{\\partial w\\\_1\\partial w\_n}\\left(\\textbf{w}\\right) \\end{array}\\begin{array}{ccc}\\frac{\\partial f}{\\partial w\\\_2\\partial w\\\_1}\\left(\\textbf{w}\\right) \\\\\\\\frac{\\partial f}{\\partial w\\\_2\\partial w\\\_2}\\left(\\textbf{w}\\right) \\\\\\\\vdots\\\\\\\\frac{\\partial f}{\\partial w\\\_2 \\partial w\_n}\\left(\\textbf{w}\\right)\\end{array}\\begin{array}{ccc}\\cdots\\\\\\\\cdots\\\\\\\\ddots\\\\\\\\cdots\\end{array}\\begin{array}{ccc}\\frac{\\partial f}{\\partial w\_n \\partial w\\\_1}\\left(\\textbf{w}\\right) \\\\\\\\frac{\\partial f}{\\partial w\_n \\partial w\\\_2}\\left(\\textbf{w}\\right) \\\\\\\\vdots\\\\\\\\frac{\\partial f}{\\partial w\_n \\partial w\_n}\\left(\\textbf{w}\\right)\\end{array}\\right)

赫森矩阵的第 行、第 列元素是函数 在 处先对 再对 的二阶偏导数。在满足连续性条件时（我们默认 满足）求偏导的顺序没影响，所以 是对称矩阵（这很重要，后文自明）。所有二阶偏导数都是关于 的函数，所以赫森矩阵也随着自变量 变化而变化（在自变量空间的每个位置都有不同的赫森矩阵，这是二阶张量场）。还有一点，我们假设赫森矩阵是正定的，也就是它的所有（ 个）特征值都为正。二次函数的二阶泰勒展开就精确是它本身。二次函数的赫森矩阵是常矩阵，不随自变量位置变化而变化。赫森矩阵正定的二次函数是开口向上的“碗”。

将函数 的二阶泰勒展开视作以变化量 为自变量的二次函数。赫森矩阵正定的二次函数有全局最小值，也是这个二次函数唯一的驻点 —— 梯度向量为零向量的点。求这个全局最小点，只需要求该二次函数对 的梯度，令梯度为零向量再解方程即可。二阶泰勒展开对 的梯度是：

![\nabla f\left(\textbf{w}\right)+\textbf{H}\_\textbf{w}d\textbf{w}=\textbf{0}](https://storage.googleapis.com/papyrus_images/cd7fac3f9a1638870723c220614bcbfefb9332c02ddd350c4670f7c498ecb559.svg)

\\nabla f\\left(\\textbf{w}\\right)+\\textbf{H}\\\_\\textbf{w}d\\textbf{w}=\\textbf{0}

解得： 。也就是说当变化向量 取这个值时，就一步走到了函数 在 处的近似二次函数的全局最小点。这就是“牛顿法”。梯度下降法根据函数局部的线性一阶近似判断函数值下降最快的方向，而牛顿法根据函数的局部二阶（二次）近似直接来到二次近似的全局最小点。梯度下降法利用了函数的局部一阶信息，而牛顿法利用了函数的局部二阶信息，它是基于二阶信息的优化算法。下图展示了在一个（我构造的）函数上执行牛顿法的四步迭代：

![](https://storage.googleapis.com/papyrus_images/c5fb34b82411646e7e1380b7fbeba8157d722504ddaa7307068448fc33f02f4c.jpg)

牛顿法的四步迭代

我们看到：牛顿法每一步的更新量 也“大体上”是 处的反梯度。但是反梯度被做了一个修正：左乘 处的赫森矩阵 的逆矩阵。这会起到一个什么效果呢？我们之前说了， 是对称矩阵，对阵矩阵可以进行特征值分解（谱分解）：

![\textbf{H}\_\textbf{w}=\Gamma\Lambda\Gamma^T=\left(\textbf{v}\_1,\textbf{v}\_2,\dots,\textbf{v}\_n\right)\left(\begin{array}{ccc}\lambda\_1\\\0 \\\\vdots\\\0 \end{array}\begin{array}{ccc}0 \\\\lambda\_2\\\\vdots\\\0\end{array}\begin{array}{ccc}\cdots\\\\cdots\\\\ddots\\\\cdots\end{array}\begin{array}{ccc}0\\\0 \\\\vdots\\\\lambda_n\end{array}\right)\left(\begin{array}{ccc}\textbf{v}\_1^T\\\\textbf{v}\_2^T\\\\vdots\\\\textbf{v}\_n^T\end{array}\right)](https://storage.googleapis.com/papyrus_images/003e0bdf2f94303dd3036dc1d86ad7615c7a12dbce1ee0c8a853c9db861d9b22.svg)

\\textbf{H}\\\_\\textbf{w}=\\Gamma\\Lambda\\Gamma^T=\\left(\\textbf{v}\\\_1,\\textbf{v}\\\_2,\\dots,\\textbf{v}\\\_n\\right)\\left(\\begin{array}{ccc}\\lambda\\\_1\\\\\\0 \\\\\\\\vdots\\\\\\0 \\end{array}\\begin{array}{ccc}0 \\\\\\\\lambda\\\_2\\\\\\\\vdots\\\\\\0\\end{array}\\begin{array}{ccc}\\cdots\\\\\\\\cdots\\\\\\\\ddots\\\\\\\\cdots\\end{array}\\begin{array}{ccc}0\\\\\\0 \\\\\\\\vdots\\\\\\\\lambda\_n\\end{array}\\right)\\left(\\begin{array}{ccc}\\textbf{v}\\\_1^T\\\\\\\\textbf{v}\\\_2^T\\\\\\\\vdots\\\\\\\\textbf{v}\\\_n^T\\end{array}\\right)

是对角矩阵，对角线元素是 从大到小（顺序不是必须的）排列的 个可重复的特征值（Eigenvalue）： 。 是赫森矩（方）阵的行/列数，也是函数 的“元数”，即自变量空间的维数。 也是 方阵。它的 个列是 个特征值对应的特征向量（Eigenvector），或者叫特征方向。这 个特征向量是标准正交的，即它们本身是标准向量（模为 1），且两两之间正交。

是 的转置，它的每一行是每个特征向量“躺平”。最大特征值 的特征向量 是函数 在 处二阶导数最大的方向，这最大的二阶导数就是 。第二大特征值 的特征向量 是函数 在 处与 正交（垂直）的前提下二阶导数最大的方向，这个“次”大的二阶导数就是 ，以此类推。

个特征向量彼此正交，于是它们线性独立。所以它们构成 维向量空间（也就是自变量空间）的一组标准正交基。也就是说它们构成了自变量空间的一个坐标系。 的列两两正交且都是标准向量，所以 是正交矩阵： 。有了谱分解， 的逆矩阵就很容易得到了：

![\textbf{H}\_\textbf{w}^{-1}=\Gamma\Lambda^{-1}\Gamma^T=\Gamma\left(\begin{array}{ccc}\frac{1}{\lambda\_1}\\\0 \\\\vdots\\\0 \end{array}\begin{array}{ccc}0 \\\\frac{1}{\lambda\_2}\\\\vdots\\\0\end{array}\begin{array}{ccc}\cdots\\\\cdots\\\\ddots\\\\cdots\end{array}\begin{array}{ccc}0\\\0 \\\\vdots\\\\frac{1}{\lambda_n}\end{array}\right)\Gamma^T](https://storage.googleapis.com/papyrus_images/7f83efb07f0c2054cd8522cc2b32010024e5d993ce9446cb7a08af6b9905f4a3.svg)

\\textbf{H}\\\_\\textbf{w}^{-1}=\\Gamma\\Lambda^{-1}\\Gamma^T=\\Gamma\\left(\\begin{array}{ccc}\\frac{1}{\\lambda\\\_1}\\\\\\0 \\\\\\\\vdots\\\\\\0 \\end{array}\\begin{array}{ccc}0 \\\\\\\\frac{1}{\\lambda\\\_2}\\\\\\\\vdots\\\\\\0\\end{array}\\begin{array}{ccc}\\cdots\\\\\\\\cdots\\\\\\\\ddots\\\\\\\\cdots\\end{array}\\begin{array}{ccc}0\\\\\\0 \\\\\\\\vdots\\\\\\\\frac{1}{\\lambda\_n}\\end{array}\\right)\\Gamma^T

现在我们再来看牛顿法的更新式：

![d\textbf{w}=-\textbf{H}\_\textbf{w}^{-1}\nabla f\left(\textbf{w}\right)=\left(\textbf{v}\_1,\textbf{v}\_2,\dots,\textbf{v}\_n\right)\left(\begin{array}{ccc}\frac{1}{\lambda\_1}\\\0 \\\\vdots\\\0 \end{array}\begin{array}{ccc}0 \\\\frac{1}{\lambda\_2}\\\\vdots\\\0\end{array}\begin{array}{ccc}\cdots\\\\cdots\\\\ddots\\\\cdots\end{array}\begin{array}{ccc}0\\\0 \\\\vdots\\\\frac{1}{\lambda_n}\end{array}\right)\left(\begin{array}{ccc}\textbf{v}\_1^T\\\\textbf{v}\_2^T\\\\vdots\\\\textbf{v}\_n^T\end{array}\right)\left(-\nabla f\left(\textbf{w}\right)\right)](https://storage.googleapis.com/papyrus_images/c305f476fdb0498fd568f555b84be1f27e87a9e09f48fbc0662d0300fd590613.svg)

d\\textbf{w}=-\\textbf{H}\\\_\\textbf{w}^{-1}\\nabla f\\left(\\textbf{w}\\right)=\\left(\\textbf{v}\\\_1,\\textbf{v}\\\_2,\\dots,\\textbf{v}\\\_n\\right)\\left(\\begin{array}{ccc}\\frac{1}{\\lambda\\\_1}\\\\\\0 \\\\\\\\vdots\\\\\\0 \\end{array}\\begin{array}{ccc}0 \\\\\\\\frac{1}{\\lambda\\\_2}\\\\\\\\vdots\\\\\\0\\end{array}\\begin{array}{ccc}\\cdots\\\\\\\\cdots\\\\\\\\ddots\\\\\\\\cdots\\end{array}\\begin{array}{ccc}0\\\\\\0 \\\\\\\\vdots\\\\\\\\frac{1}{\\lambda\_n}\\end{array}\\right)\\left(\\begin{array}{ccc}\\textbf{v}\\\_1^T\\\\\\\\textbf{v}\\\_2^T\\\\\\\\vdots\\\\\\\\textbf{v}\\\_n^T\\end{array}\\right)\\left(-\\nabla f\\left(\\textbf{w}\\right)\\right)

最右边是 。这是用 方阵乘 维向量，得到还是一个 维向量。它的分量是各特征向量（特征方向）与反梯度的内积，也就是反梯度在各特征方向上的投影。之后再左乘矩阵 ，这等于是用每个特征方向对应的特征值去除相应的投影分量。前文说过这些特征值是函数 在各个特征方向上的二阶导数，于是这就是用各特征方向的二阶导数去除反梯度在各特征方向上的投影分量，这些投影分量就受到了相应的“惩罚”：二阶导大的特征方向上的分量受到的惩罚重，二阶导小的特征方向上的分量受到的惩罚轻。最后，再用惩罚后的各分量将各特征向量线性组合起来。这个过程其实就是：将反梯度向各特征方向投影，用对应的二阶导数缩放（惩罚）各分量，然后再组合回来。组合回来后就不再是反梯度了，它对反梯度进行了调整，惩罚削弱了二阶导数较大的方向。直观看下图：

![](https://storage.googleapis.com/papyrus_images/81a9c949e2eb6628cf4281547e96f8d35e9518d1da4d9b965c4a4a901c2e0ecd.jpg)

牛顿法对反梯度方向的调整

上图展示了四个二元（ ）二次函数。二次函数的赫森矩阵是常矩阵，不随自变量变化而变化。图中展示了某位置处的反梯度向量，两个特征值以及对应的特征向量（特征方向），反梯度向两个特征方向的投影分量（灰色），经过惩罚（除以特征值/二阶导数）后的分量，用惩罚后的分量再将两个特征向量线性组合回来的向量，即 。我们看到， 直接指到了二次函数全局最小点 —— 在上图例子中是原点，因为我们构造的这四个二次函数都是二次型，没有常数项和一次项。

因为二次函数的二阶泰勒展开就精确是它自身（余项为 0 ），牛顿法一步定位到二阶泰勒展开的全局最小点，当然也就是原二次函数的全局最小点。而对于普通函数，二阶泰勒展开不是原函数本身，只是一个足够好的二次近似，所以牛顿法起到的作用是根据二阶信息调整反梯度，惩罚二阶导较大的方向，削弱不平衡的二阶导造成的恶劣影响。

* * *

现在我们回顾一下 RMSProp 和 ADAM 。它们记录了历史上梯度各分量的平方，这些分量并非是在赫森矩阵特征方向上的分量，而只是在原天然坐标系上的分量。它们根据这些分量的历史平方和惩罚梯度的各分量。我们知道，导数是变化率，二阶导是一阶导的变化率，而根据历史可以估计变化率。就好像记录苏炳添每个时刻的位置（历史）就可以近似估计他的速度。

记录梯度各分量的历史就可以估计它的各分量（即各偏导数）的变化率，也就是函数在原天然坐标系的各坐标轴方向上的二阶变化率（二阶导）。RMSProp 和 ADAM 不计算赫森矩阵，它们不是二阶优化算法，只是一阶优化算法。但它们记录一阶信息（梯度）的历史，用之估计二阶信息，并对二阶导数较大的（原天然）方向施加惩罚。这些方向不是真正的二阶导最大、次大、次次大 ...... 的方向，那些方向是赫森矩阵的特征方向。RMSProp 和 ADAM 不计算特征矩阵，它们只是在原天然坐标系的各个方向上估二阶导并施加相应的惩罚。结论\*\*：RMSProp 和 ADAM 是利用一阶梯度信息对如牛顿法的二阶优化算法的近似模拟。\*\*

---

*Originally published on [jingz0.eth](https://paragraph.com/@jingz0/adam)*
