大家好~
今儿和大家聊聊一个很好用的优化算法,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(-5, 5, n)
noise = np.random.normal(0, 1, n)
a, b, c = 2, -3, 5
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(2, 2, figsize=(14, 12))
# 图1:数据拟合结果
axs[0, 0].scatter(X, Y, color='blue', label='Data', alpha=0.5)
pred_Y = theta[0] * X**2 + theta[1] * X + theta[2]
axs[0, 0].plot(X, pred_Y, color='red', label='Fitted curve', linewidth=2)
axs[0, 0].set_title('Data Fitting with Adam Optimizer')
axs[0, 0].legend()
# 图2:损失值下降曲线
axs[0, 1].plot(range(iterations), loss_history, color='purple', linewidth=2)
axs[0, 1].set_title('Loss Over Iterations')
axs[0, 1].set_xlabel('Iterations')
axs[0, 1].set_ylabel('Loss')
# 图3:参数变化趋势
theta_history = np.array(theta_history)
axs[1, 0].plot(range(iterations), theta_history[:, 0], label='a', color='orange', linewidth=2)
axs[1, 0].plot(range(iterations), theta_history[:, 1], label='b', color='green', linewidth=2)
axs[1, 0].plot(range(iterations), theta_history[:, 2], label='c', color='red', linewidth=2)
axs[1, 0].set_title('Parameter Updates Over Iterations')
axs[1, 0].set_xlabel('Iterations')
axs[1, 0].legend()
# 图4:预测残差分析
residuals = Y - pred_Y
axs[1, 1].scatter(pred_Y, residuals, color='teal', alpha=0.6)
axs[1, 1].axhline(0, color='black', linestyle='--', linewidth=2)
axs[1, 1].set_title('Residuals Plot')
axs[1, 1].set_xlabel('Predicted')
axs[1, 1].set_ylabel('Residuals')
plt.tight_layout()
plt.show()
Adam优化器的实现:我们从头开始实现了Adam优化器的核心公式,不使用任何现成的深度学习包。
生成的4张图:
数据拟合图:展示模型对虚拟数据集的拟合结果。 损失下降图:展示Adam优化器迭代过程中损失的下降趋势。 参数更新图:展示模型参数在每次迭代中的变化趋势。 残差图:分析预测值和真实值的差异,帮助判断模型拟合的好坏。
通过,整个的原理和案例,大家有问题随时可以在评论区讨论~