问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Adam优化算法理解与实现

创作时间:
作者:
@小白创作中心

Adam优化算法理解与实现

引用
CSDN
1.
https://blog.csdn.net/weixin_44575152/article/details/112683223

Adam优化算法是深度学习中常用的优化算法之一,它结合了动量梯度下降法和RMSprop的优点,能够自适应地调整每个参数的学习率。本文将从理论到实践,详细讲解Adam优化算法的原理和实现方法。

引入

在使用深度学习框架时,Adam优化器的出现频率非常高。那么,Adam优化算法究竟是什么?它为什么如此受欢迎?本文将为你解答这些问题。

1 Adam介绍

Adam优化算法是目前最流行的优化算法之一,它结合了动量梯度下降法(Momentum)和RMSprop的优点。Adam算法通过自适应地调整每个参数的学习率,使得优化过程更加高效。

Adam算法的更新过程如下:

$$
\begin{aligned}
v_t & = \beta_1 v_{t - 1} + (1 + \beta_1)grad_t\
s_t & = \beta_2 s_{t - 1} + (1 - \beta_2)grad_t^2
\end{aligned}
$$

这里$v$和$s$是不同的动量,前者用于记录上一次的梯度,后者则保留RMSprop的特长。

$v$和$s$的偏导计算如下:

$$
\begin{aligned}
v_t' & = \frac{v_t}{1 - \beta_1^t}\
s_t' & = \frac{s_t}{1-\beta_2^t}
\end{aligned}
$$

最终的更新如下:

$$
\begin{aligned}
grad_t' & = \frac{lr * v_t'}{\sqrt{s_t'} + \epsilon}\
\theta_t & = \theta_{t - 1} - grad_t'
\end{aligned}
$$

2 具体实现

为了更好地理解Adam优化算法,我们通过一个具体的线性回归例子来展示其实现过程。假设我们有一个线性函数$f(x) = ax + b$,我们的目标是通过最小化损失函数来找到最优的$a$和$b$。

损失函数定义为:

$$
\begin{aligned}
f(x) &= a x+b \
(y-f(x))^{2} & =(y-(a x+b))^{2} \
\frac{d y}{d a} &=-2 x(y-(a x+b)) \
\frac{d y}{d b} &=-2(y-(a x+b))
\end{aligned}
$$

下面是具体的Python实现代码:

import numpy as np
import matplotlib.pyplot as plt
from sympy import symbols, diff

def get_data():
    ret_x = np.linspace(-1, 1, 100)
    return ret_x, [(lambda x: 2 * x + 3)(x) for x in ret_x]

def grad():
    x, y, a, b = symbols(["x", "y", "a", "b"])
    loss = (y - (a * x + b))**2
    return diff(loss, a), diff(loss, b)

def test2(n_iter=50, lr=0.1, batch_size=20, beta1=0.9, beta2=0.999, epsilon=1e-6, shuffle=True):
    x, y = get_data()
    ga, gb = grad()
    n = len(x)
    idx = np.random.permutation(n)
    s, v = 0, 0
    a, b = 0, 0
    move_a, move_b = [a], [b]
    move_lr_a, move_lr_b = [lr], [lr]
    t = 1
    for _ in range(n_iter):
        if shuffle:
            np.random.shuffle(idx)
        batch_idxes = [idx[k: k + batch_size] for k in range(0, n, batch_size)]
        for idxes in batch_idxes:
            sum_ga, sum_gb = 0, 0
            for j in idxes:
                sum_ga += ga.subs({"x": x[j], "y": y[j], "a": a, "b": b})
                sum_gb += gb.subs({"x": x[j], "y": y[j], "a": a, "b": b})
            sum_ga /= batch_size
            sum_gb /= batch_size
            g = np.array([sum_ga, sum_gb])
            v = beta1 * v + (1 - beta1) * g
            s = beta2 * s + (1 - beta2) * g * g
            v_norm = v / (1 - np.power(beta1, t))
            s_norm = s / (1 - np.power(beta2, t))
            t += 1
            lr_a, lr_b = lr * v_norm[0], lr * v_norm[1]
            move_lr_a.append(lr_a)
            move_lr_b.append(lr_b)
            g_a_norm = lr_a / (np.sqrt(float(s_norm[0])) + epsilon)
            g_b_norm = lr_b / (np.sqrt(float(s_norm[1])) + epsilon)
            a -= g_a_norm
            b -= g_b_norm
            move_a.append(a)
            move_b.append(b)
    plt.subplot(211)
    plt.plot(move_a)
    plt.plot(move_b)
    plt.legend(["a", "b"])
    plt.subplot(212)
    plt.plot(move_lr_a)
    plt.plot(move_lr_b)
    plt.legend(["a", "b"])
    plt.show()

if __name__ == '__main__':
    test2()

运行上述代码,可以得到参数$a$和$b$的更新过程以及学习率的变化情况,如图所示:

从图中可以看出,Adam优化算法能够自适应地调整学习率,使得参数更新更加平稳和高效。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号