Adam,一个强大优化算法模型 !!

文摘   2024-09-26 16:36   北京  

大家好~

今儿和大家聊聊一个很好用的优化算法,Adam!~

Adam 是机器学习和深度学习中常用的一种优化算法,它帮助模型更快、更高效地找到最佳解。

下面,咱们设计一个场景,大家会很容易就理解:

假设你在一个山谷里闭着眼睛,想要找到最底下的点(也就是最低谷),但你看不见路,只能通过脚下的地势来判断是上坡还是下坡。如果是下坡,你继续往下走。如果是上坡,你停下来,说明已经到了最低点。

这个过程就像我们在训练一个机器学习模型时,模型通过不断调整参数,尝试找到最好的「权重」来降低预测误差,这个最低点代表误差最小。

Adam优化器的角色

在这个山谷里,你不只是自己摸索前进,你还有两个工具:

  • 一个指南针,它会告诉你当前地势的陡峭程度(类似于梯度)。
  • 一双有弹性的鞋子,它可以帮助你在坡度陡的时候迈大步,平缓的时候迈小步。

这两个工具分别代表了Adam中的动量自适应学习率

  • 动量(Momentum):相当于帮助你记住之前的路程,当你走得比较顺畅时,步子可以迈大一点,不要总是慢慢摸索。
  • 自适应学习率:帮助你根据当前的「地势」调整步伐,在陡坡的时候迈大步,在平坦的地方迈小步,这样不会走得太快错过最低点,也不会走得太慢浪费时间。

详细过程

Adam的名字来源于自适应矩估计(Adaptive Moment Estimation)。它结合了两种思路:

  • 动量优化:跟踪之前的更新方向,平滑震荡,使你走得更稳。
  • RMSProp算法:根据不同方向的梯度大小调整步长,避免在一些不重要的方向上迈太大步。

这样,Adam可以在不确定的地形(复杂的损失函数)上帮助你更快找到最低点(最优解)。

再举一个例子: 

假设你在学习骑自行车。起初,你的平衡感不好,容易摔倒(错误率高)。Adam就像一个教练,它会根据你每次骑车的表现,及时调整你的训练方式。如果你骑得还不错(梯度平缓),教练会让你稍微大胆一点加速前进;但如果你摔得比较严重(梯度陡峭),教练会让你慢下来,仔细调整自己的姿势。

随着每一次调整,你的骑车技术(模型的表现)会越来越好,直到你最终学会了骑车(找到最佳解)。

总的来说,Adam是一个智能调整步伐的算法,帮助模型更快找到最佳解。

有了这个非常容易理解的例子。咱们下面就从Adam算法的原理、公式,并在推导后提供一个不依赖于现成优化器的Python实现案例。该案例将展示如何使用Adam优化器训练一个简单的模型,并且会生成多张与数据分析相关的图像。

Adam算法公式推导

Adam优化器结合了动量优化和RMSProp优化器的优势,核心思想是通过梯度的二阶矩估计动态调整学习率,同时加入动量来平滑更新。

设定:

  •  表示第  次迭代时的参数值。
  •  是当前梯度(即损失函数对参数的偏导数)。

动量更新(Momentum)

Adam通过指数加权移动平均的方法来计算梯度的动量:

其中, 是动量项, 是控制动量的衰减率(通常取 0.9)。

均方根(RMSProp)更新

类似地,Adam也通过移动平均来计算梯度平方的平均值:

其中, 是梯度平方的动量, 控制平方梯度的衰减率(通常取 0.999)。

偏差修正

因为    在前几次迭代时可能偏向零,所以需要对它们进行偏差修正:

参数更新

最终的参数更新公式如下:

其中:

  •  是学习率(一般取 0.001)。
  •  是一个小的常数,避免除零(一般取 )。

完整案例

名称:实现Adam优化器并生成复杂数据分析图像。

我们用Adam优化器来拟合一个简单的二次函数(虚拟数据集),并通过多种方式分析数据。

此过程中我们将生成4个或以上的图像,包含优化过程、误差变化、参数更新趋势等。这里不会使用现成的优化器包。

import numpy as np
import matplotlib.pyplot as plt

# 设置随机数种子,保证结果可重复
np.random.seed(42)

# 生成虚拟数据集 (二次函数: y = ax^2 + bx + c)
def generate_data(n=100):
    X = np.linspace(-55, n)
    noise = np.random.normal(01, n)
    a, b, c = 2-35
    Y = a * X**2 + b * X + c + noise
    return X, Y

X, Y = generate_data()

# Adam优化器
class AdamOptimizer:
    def __init__(self, learning_rate=0.01, beta1=0.9, beta2=0.999, epsilon=1e-8):
        self.lr = learning_rate
        self.beta1 = beta1
        self.beta2 = beta2
        self.epsilon = epsilon
        self.m = 0
        self.v = 0
        self.t = 0

    def update(self, grad):
        self.t += 1
        self.m = self.beta1 * self.m + (1 - self.beta1) * grad
        self.v = self.beta2 * self.v + (1 - self.beta2) * grad**2

        m_hat = self.m / (1 - self.beta1**self.t)
        v_hat = self.v / (1 - self.beta2**self.t)

        update_value = self.lr * m_hat / (np.sqrt(v_hat) + self.epsilon)
        return update_value

# 定义损失函数和梯度
def loss_function(theta, X, Y):
    a, b, c = theta
    pred = a * X**2 + b * X + c
    loss = np.mean((pred - Y) ** 2)
    return loss

def gradients(theta, X, Y):
    a, b, c = theta
    grad_a = np.mean(2 * (a * X**2 + b * X + c - Y) * X**2)
    grad_b = np.mean(2 * (a * X**2 + b * X + c - Y) * X)
    grad_c = np.mean(2 * (a * X**2 + b * X + c - Y))
    return np.array([grad_a, grad_b, grad_c])

# 初始化参数
theta = np.random.randn(3)
adam = AdamOptimizer(learning_rate=0.1)

# 存储迭代过程的值
loss_history = []
theta_history = []

# 迭代优化
iterations = 1000
for i in range(iterations):
    grad = gradients(theta, X, Y)
    theta -= adam.update(grad)
    
    # 存储历史记录
    loss_history.append(loss_function(theta, X, Y))
    theta_history.append(theta.copy())

# 画图分析
fig, axs = plt.subplots(22, figsize=(1412))

# 图1:数据拟合结果
axs[00].scatter(X, Y, color='blue', label='Data', alpha=0.5)
pred_Y = theta[0] * X**2 + theta[1] * X + theta[2]
axs[00].plot(X, pred_Y, color='red', label='Fitted curve', linewidth=2)
axs[00].set_title('Data Fitting with Adam Optimizer')
axs[00].legend()

# 图2:损失值下降曲线
axs[01].plot(range(iterations), loss_history, color='purple', linewidth=2)
axs[01].set_title('Loss Over Iterations')
axs[01].set_xlabel('Iterations')
axs[01].set_ylabel('Loss')

# 图3:参数变化趋势
theta_history = np.array(theta_history)
axs[10].plot(range(iterations), theta_history[:, 0], label='a', color='orange', linewidth=2)
axs[10].plot(range(iterations), theta_history[:, 1], label='b', color='green', linewidth=2)
axs[10].plot(range(iterations), theta_history[:, 2], label='c', color='red', linewidth=2)
axs[10].set_title('Parameter Updates Over Iterations')
axs[10].set_xlabel('Iterations')
axs[10].legend()

# 图4:预测残差分析
residuals = Y - pred_Y
axs[11].scatter(pred_Y, residuals, color='teal', alpha=0.6)
axs[11].axhline(0, color='black', linestyle='--', linewidth=2)
axs[11].set_title('Residuals Plot')
axs[11].set_xlabel('Predicted')
axs[11].set_ylabel('Residuals')

plt.tight_layout()
plt.show()

Adam优化器的实现:我们从头开始实现了Adam优化器的核心公式,不使用任何现成的深度学习包。

生成的4张图

  1. 数据拟合图:展示模型对虚拟数据集的拟合结果。
  2. 损失下降图:展示Adam优化器迭代过程中损失的下降趋势。
  3. 参数更新图:展示模型参数在每次迭代中的变化趋势。
  4. 残差图:分析预测值和真实值的差异,帮助判断模型拟合的好坏。

通过,整个的原理和案例,大家有问题随时可以在评论区讨论~

机器学习和人工智能AI
让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
 最新文章