7.5.1 Momentum
![图片[1]-7.5 参数更新方法-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-317.png)
import torch
import numpy as np
import matplotlib.pyplot as plt
def gradient_descent(X, optimizer, n_iters):
X_arr = X.detach().numpy().copy() # 拷贝,用于记录优化过程
for epoch in range(n_iters):
y = X**2 @ w
y.backward() # 反向传播
optimizer.step() # 更新参数
optimizer.zero_grad() # 清空梯度
X_arr = np.vstack([X_arr, X.detach().numpy()]) # 记录优化过程
return X_arr
# 从(-7, 2)出发
X = torch.tensor([-7, 2], dtype=torch.float32, requires_grad=True)
w = torch.tensor([[0.05], [1.0]], requires_grad=True)
lr = 1e-2 # 学习率
n_iters = 500 # 迭代次数
# 普通梯度下降
X_clone = X.clone().detach().requires_grad_(True)
X_arr1 = gradient_descent(X_clone, torch.optim.SGD([X_clone], lr=lr), n_iters=n_iters)
plt.plot(X_arr1[:, 0], X_arr1[:, 1], "r")
# 动量法
X_clone = X.clone().detach().requires_grad_(True)
X_arr2 = gradient_descent(X_clone, torch.optim.SGD([X_clone], lr=lr, momentum=0.9), n_iters=n_iters)
plt.plot(X_arr2[:, 0], X_arr2[:, 1], "b")
# 绘制等高线图
x1_grid, x2_grid = np.meshgrid(np.linspace(-7, 7, 100), np.linspace(-2, 2, 100))
y_grid = w.detach().numpy()[0, 0] * x1_grid**2 + w.detach().numpy()[1, 0] * x2_grid**2
plt.contour(x1_grid, x2_grid, y_grid, levels=30, colors="gray")
plt.legend(["SGD", "Momentum"])
plt.show()
7.5.2 学习率衰减
- 等间隔衰减
可以通过torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma)来实现学习率的等间隔衰减。
- optimizer:要实现学习率衰减的优化器
- step_size:间隔
- gamma:衰减的比例
例如,使学习率每隔20 epoch衰减为之前的0.7:
![图片[2]-7.5 参数更新方法-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-318.png)
import torch
import numpy as np
import matplotlib.pyplot as plt
# 从(-7, 2)出发
X = torch.tensor([-7, 2], dtype=torch.float32, requires_grad=True)
w = torch.tensor([[0.05], [1.0]], requires_grad=True)
lr = 0.9 # 初始学习率
n_iters = 1000 # 迭代次数
optimizer = torch.optim.SGD([X], lr=lr)
scheduler_lr = torch.optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.7) # 学习率衰减
X_arr = X.detach().numpy().copy() # 拷贝,用于记录优化过程
lr_list = [] # 记录学习率变化
for epoch in range(n_iters):
y = X**2 @ w
y.backward() # 反向传播
optimizer.step() # 更新参数
optimizer.zero_grad() # 清空梯度
X_arr = np.vstack([X_arr, X.detach().numpy()]) # 记录优化过程
lr_list.append(optimizer.param_groups[0]["lr"]) # 记录学习率变化
scheduler_lr.step() # 学习率衰减
plt.rcParams["font.sans-serif"] = ["KaiTi"]
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
x1_grid, x2_grid = np.meshgrid(np.linspace(-7, 7, 100), np.linspace(-2, 2, 100))
y_grid = w.detach().numpy()[0, 0] * x1_grid**2 + w.detach().numpy()[1, 0] * x2_grid**2
ax[0].contour(x1_grid, x2_grid, y_grid, levels=30, colors="gray")
ax[0].plot(X_arr[:, 0], X_arr[:, 1], "r")
ax[0].set_title("梯度下降过程")
ax[1].plot(lr_list, "k")
ax[1].set_title("学习率衰减")
plt.show()
2.指定间隔衰减
可以通过torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma)来实现学习率的指定间隔衰减。
- optimizer:要实现学习率衰减的优化器
- milestones:指定衰减的间隔
- gamma:衰减的比例
例如,使学习率在epoch达到[10,50,200]时衰减为之前的0.7:
![图片[3]-7.5 参数更新方法-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-319.png)
import torch
import numpy as np
import matplotlib.pyplot as plt
# 从(-7, 2)出发
X = torch.tensor([-7, 2], dtype=torch.float32, requires_grad=True)
w = torch.tensor([[0.05], [1.0]], requires_grad=True)
lr = 0.9 # 初始学习率
n_iters = 400 # 迭代次数
optimizer = torch.optim.SGD([X], lr=lr)
scheduler_lr = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[10, 50, 200], gamma=0.7) # 学习率衰减
X_arr = X.detach().numpy().copy() # 拷贝,用于记录优化过程
lr_list = [] # 记录学习率变化
for epoch in range(n_iters):
y = X**2 @ w
y.backward() # 反向传播
optimizer.step() # 更新参数
optimizer.zero_grad() # 清空梯度
X_arr = np.vstack([X_arr, X.detach().numpy()]) # 记录优化过程
lr_list.append(optimizer.param_groups[0]["lr"]) # 记录学习率变化
scheduler_lr.step() # 学习率衰减
plt.rcParams["font.sans-serif"] = ["KaiTi"]
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
x1_grid, x2_grid = np.meshgrid(np.linspace(-7, 7, 100), np.linspace(-2, 2, 100))
y_grid = w.detach().numpy()[0, 0] * x1_grid**2 + w.detach().numpy()[1, 0] * x2_grid**2
ax[0].contour(x1_grid, x2_grid, y_grid, levels=30, colors="gray")
ax[0].plot(X_arr[:, 0], X_arr[:, 1], "r")
ax[0].set_title("梯度下降过程")
ax[1].plot(lr_list, "k")
ax[1].set_title("学习率衰减")
plt.show()
3.指数衰减
![图片[4]-7.5 参数更新方法-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-321.png)
![图片[5]-7.5 参数更新方法-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-320.png)
import torch
import numpy as np
import matplotlib.pyplot as plt
# 从(-7, 2)出发
X = torch.tensor([-7, 2], dtype=torch.float32, requires_grad=True)
w = torch.tensor([[0.05], [1.0]], requires_grad=True)
lr = 0.9 # 初始学习率
n_iters = 400 # 迭代次数
optimizer = torch.optim.SGD([X], lr=lr)
scheduler_lr = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.99) # 学习率衰减
X_arr = X.detach().numpy().copy() # 拷贝,用于记录优化过程
lr_list = [] # 记录学习率变化
for epoch in range(n_iters):
y = X**2 @ w
y.backward() # 反向传播
optimizer.step() # 更新参数
optimizer.zero_grad() # 清空梯度
X_arr = np.vstack([X_arr, X.detach().numpy()]) # 记录优化过程
lr_list.append(optimizer.param_groups[0]["lr"]) # 记录学习率变化
scheduler_lr.step() # 学习率衰减
plt.rcParams["font.sans-serif"] = ["KaiTi"]
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
x1_grid, x2_grid = np.meshgrid(np.linspace(-7, 7, 100), np.linspace(-2, 2, 100))
y_grid = w.detach().numpy()[0, 0] * x1_grid**2 + w.detach().numpy()[1, 0] * x2_grid**2
ax[0].contour(x1_grid, x2_grid, y_grid, levels=30, colors="gray")
ax[0].plot(X_arr[:, 0], X_arr[:, 1], "r")
ax[0].set_title("梯度下降过程")
ax[1].plot(lr_list, "k")
ax[1].set_title("学习率衰减")
plt.show()
7.5.3 AdaGrad
![图片[6]-7.5 参数更新方法-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-323.png)
import torch
import numpy as np
import matplotlib.pyplot as plt
def adagrad(X, lr, n_iters):
"""AdaGrad手动实现"""
X_arr = X.detach().numpy().copy() # 拷贝,用于记录优化过程
H = torch.zeros_like(X) # 存放历史梯度信息
for epoch in range(n_iters):
grad = 2 * X * w.T # 当前梯度
grad.squeeze_() # 降维
H += grad**2 # 平方和
X.data -= lr / (torch.sqrt(H) + 1e-8) * grad # 更新参数,这里H后面加1e-8防止分母为0
X_arr = np.vstack([X_arr, X.detach().numpy()]) # 记录优化过程
return X_arr
def gradient_descent(X, optimizer, n_iters):
X_arr = X.detach().numpy().copy() # 拷贝,用于记录优化过程
for epoch in range(n_iters):
y = X**2 @ w
y.backward() # 反向传播
optimizer.step() # 更新参数
optimizer.zero_grad() # 清空梯度
X_arr = np.vstack([X_arr, X.detach().numpy()]) # 记录优化过程
return X_arr
# 从(-7, 2)出发
X = torch.tensor([-7, 2], dtype=torch.float32, requires_grad=True)
w = torch.tensor([[0.05], [1.0]], requires_grad=True)
lr = 0.9 # 学习率
n_iters = 500 # 迭代次数
# 普通梯度下降
X_clone = X.clone().detach().requires_grad_(True)
X_arr1 = gradient_descent(X_clone, torch.optim.SGD([X_clone], lr=lr), n_iters=n_iters)
plt.plot(X_arr1[:, 0], X_arr1[:, 1], "r")
# AdaGrad
X_clone = X.clone().detach().requires_grad_(True)
X_arr2 = gradient_descent(X_clone, torch.optim.Adagrad([X_clone], lr=lr), n_iters=n_iters)
plt.plot(X_arr2[:, 0], X_arr2[:, 1], "b")
# AdaGrad手动实现
X_clone = X.clone().detach().requires_grad_(True)
X_arr1 = adagrad(X_clone, lr=lr, n_iters=n_iters)
plt.plot(X_arr1[:, 0], X_arr1[:, 1], c="orange", linestyle="--", linewidth=3)
# 绘制等高线图
x1_grid, x2_grid = np.meshgrid(np.linspace(-7, 7, 100), np.linspace(-2, 2, 100))
y_grid = w.detach().numpy()[0, 0] * x1_grid**2 + w.detach().numpy()[1, 0] * x2_grid**2
plt.contour(x1_grid, x2_grid, y_grid, levels=30, colors="gray")
plt.legend(["SGD", "AdaGrad", "Manual AdaGrad"])
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END















请登录后查看评论内容