模型优化
torch.optim.SGD
torch.optim.SGD
是 PyTorch 中用于实现随机梯度下降(Stochastic Gradient Descent, SGD)优化算法的类。SGD 是一种常用的优化方法,广泛用于训练深度学习模型。
1. 基本语法
torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)
params
:要优化的模型参数,通常传递model.parameters()
。lr
:学习率(learning rate),控制每次参数更新的步长。学习率是 SGD 的一个重要超参数。momentum
:动量项(Momentum),用于加速 SGD 收敛,尤其是在存在噪声的情况下。默认值为0
,表示不使用动量。dampening
:用于控制动量的衰减,默认值为0
,即没有衰减。weight_decay
:权重衰减(L2 正则化),用于控制模型复杂度,防止过拟合。默认值为0
,表示不使用权重衰减。nesterov
:布尔值,表示是否使用 Nesterov 动量,默认值为False
,即不使用。
2. 随机梯度下降(SGD)
SGD 是一种逐个小批量(mini-batch)更新模型参数的优化方法。每次从数据集中随机抽取一个或多个样本进行梯度计算并更新参数。相比于标准的梯度下降(batch gradient descent)使用整个数据集计算梯度,SGD 能加速训练,但会带来一些噪声。
SGD 通过以下公式更新参数:
是模型参数。 是学习率。 是损失函数关于 的梯度。
3. 带动量的 SGD
动量是 SGD 的一种改进版本,通过在梯度更新中引入动量项,动量可以减少训练过程中的震荡,加速收敛。动量项累积之前的梯度,使得优化方向更稳定。
带动量的 SGD 更新规则为:
其中:
是速度(velocity),它是在梯度上累积的动量。 是动量系数,表示之前更新的权重。通常取值范围为 [0, 1]
,如0.9
。
4. 带 Nesterov 动量的 SGD
Nesterov 动量是一种动量的改进版本,它在参数更新时使用了提前更新的梯度,这样可以更好地调整学习方向。Nesterov 动量的更新公式为:
在 PyTorch 中,你可以通过设置 nesterov=True
来使用 Nesterov 动量。
5. 参数说明
学习率(
lr
):学习率是控制优化器步长的重要参数。值太大会导致训练不稳定,太小则会收敛过慢。通常,学习率会随着训练进行而调整(如使用学习率调度器)。动量(
momentum
):动量在优化过程中积累之前的梯度,使得参数更新不仅考虑当前的梯度,还考虑之前的梯度。常见值为0.9
或0.99
。权重衰减(
weight_decay
):权重衰减对应于 L2 正则化项,通常用于防止模型过拟合。它会对每次更新的权重进行一定的衰减。权重衰减公式如下:
其中 λ
是权重衰减因子,也就是 weight_decay
。
- dampening:动量的衰减参数,通常与
momentum
一起使用。当dampening
为非零值时,动量的更新会随着时间逐渐减小。默认0
不衰减。
6. 示例代码
不带动量的 SGD
import torch
import torch.optim as optim
# 定义模型
model = torch.nn.Linear(2, 1)
# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 训练循环
for epoch in range(100):
# 前向传播
outputs = model(torch.randn(10, 2))
loss = torch.mean((outputs - torch.randn(10, 1)) ** 2)
# 梯度清零
optimizer.zero_grad()
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
带动量的 SGD
import torch
import torch.optim as optim
# 定义模型
model = torch.nn.Linear(2, 1)
# 定义带动量的优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# 训练循环
for epoch in range(100):
outputs = model(torch.randn(10, 2))
loss = torch.mean((outputs - torch.randn(10, 1)) ** 2)
optimizer.zero_grad()
loss.backward()
optimizer.step()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
带 Nesterov 动量的 SGD
import torch
import torch.optim as optim
# 定义模型
model = torch.nn.Linear(2, 1)
# 定义带 Nesterov 动量的优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, nesterov=True)
# 训练循环
for epoch in range(100):
outputs = model(torch.randn(10, 2))
loss = torch.mean((outputs - torch.randn(10, 1)) ** 2)
optimizer.zero_grad()
loss.backward()
optimizer.step()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
7. 注意事项
- 学习率调整:SGD 对学习率敏感,通常需要在训练过程中使用调度器(如
torch.optim.lr_scheduler
)来动态调整学习率。 - 小批量数据:SGD 通常在小批量(mini-batch)数据上运行,这可以减少内存消耗并提高模型更新频率。
- 动量设置:大多数情况下,使用
momentum=0.9
是一种常见的选择,尤其是当数据中有噪声时,动量能够加速收敛并减少震荡。
总结
torch.optim.SGD
是 PyTorch 中实现随机梯度下降(SGD)的优化器类。它可以通过引入动量和权重衰减等增强功能来改善模型的训练效果,特别是在深度学习中的应用。
torch.optim.Adam
是 PyTorch 中实现 Adam 优化算法的类。Adam(Adaptive Moment Estimation,自适应矩估计)是深度学习中一种非常流行的优化算法,它结合了动量法和RMSProp 的优点,能够高效处理大规模的数据并且无需手动调整学习率。
torch.optim.Adam
1. 基本语法
torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
params
:要优化的参数(通常传递model.parameters()
)。lr
:学习率,控制每次更新的步长。Adam 的默认学习率是0.001
,通常比 SGD 的默认学习率小,因为 Adam 会根据梯度变化自适应调整步长。betas
:一对控制一阶和二阶矩估计的系数。默认值为(0.9, 0.999)
,分别对应一阶矩(动量项)和二阶矩(梯度平方的指数加权移动平均)。eps
:为了防止除以零,Adam 算法在更新时加上的一个非常小的数值。默认值是1e-08
。weight_decay
:权重衰减,等价于 L2 正则化,用于防止模型过拟合。默认值为0
。amsgrad
:布尔值,是否启用 AMSGrad 算法的改进版本。默认值为False
。
2. Adam 优化算法原理
Adam 算法结合了 SGD 中的动量法和 RMSProp。与标准的梯度下降方法不同,Adam 使用两个动量项:一个是梯度的动量(类似于 SGD + momentum
),另一个是梯度平方的动量,用来调整学习率。
一阶和二阶矩估计
Adam 主要通过一阶和二阶矩的指数移动平均值来进行参数更新:
- 一阶矩估计:对梯度进行指数加权移动平均,类似于动量法。
- 二阶矩估计:对梯度平方进行指数加权移动平均,用于调节学习率。
更新公式如下:
- 一阶矩动量(动量):
其中,m_t
是当前时刻的梯度一阶矩动量,g_t
是当前时刻的梯度,β_1
是一阶矩的衰减系数,通常取 0.9
。
- 二阶矩动量:
其中,v_t
是当前时刻的梯度二阶矩动量,g_t^2
是当前时刻的梯度平方,β_2
是二阶矩的衰减系数,通常取 0.999
。
- 偏差修正:为了修正初始时的偏差,Adam 引入了以下修正公式:
- 参数更新:
其中,θ_t
是模型的参数,η
是学习率,ε
是为了避免除零的数值(默认值 1e-8
)。
3. 参数解释
lr
(学习率):Adam 的学习率默认是0.001
,通常它不需要像 SGD 那样频繁调整,因为它对不同参数使用自适应学习率。如果要微调学习率,可以根据模型的具体情况调整。betas
(动量系数):beta1=0.9
:控制一阶矩估计的衰减率。较高的beta1
值会平滑梯度更新,但可能会导致模型学习速度变慢。beta2=0.999
:控制二阶矩估计的衰减率,用于调整学习率。如果beta2
取值太小,学习率会波动过大。
eps
(小数值):用于数值稳定性,防止除以零的错误。通常不需要调整。weight_decay
(权重衰减):在 Adam 中,权重衰减等价于 L2 正则化,用于防止过拟合。较大的weight_decay
值会对模型施加更强的正则化。amsgrad
:这个参数是Adam
的一个改进版本。AMSGrad 通过记录历史最大值来保证优化器的收敛性。默认False
即为标准的 Adam,True
时为 AMSGrad。
4. 示例代码
标准 Adam 优化器
import torch
import torch.optim as optim
# 定义一个简单的模型
model = torch.nn.Linear(2, 1)
# 定义 Adam 优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练循环
for epoch in range(100):
outputs = model(torch.randn(10, 2))
loss = torch.mean((outputs - torch.randn(10, 1)) ** 2)
# 梯度清零
optimizer.zero_grad()
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
带权重衰减和自适应动量的 Adam 优化器
import torch
import torch.optim as optim
# 定义模型
model = torch.nn.Linear(2, 1)
# 带有权重衰减的 Adam 优化器
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4, betas=(0.9, 0.999))
# 训练循环
for epoch in range(100):
outputs = model(torch.randn(10, 2))
loss = torch.mean((outputs - torch.randn(10, 1)) ** 2)
optimizer.zero_grad()
loss.backward()
optimizer.step()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
启用 AMSGrad 的 Adam 优化器
import torch
import torch.optim as optim
# 定义模型
model = torch.nn.Linear(2, 1)
# 使用 AMSGrad 的 Adam 优化器
optimizer = optim.Adam(model.parameters(), lr=0.001, amsgrad=True)
# 训练循环
for epoch in range(100):
outputs = model(torch.randn(10, 2))
loss = torch.mean((outputs - torch.randn(10, 1)) ** 2)
optimizer.zero_grad()
loss.backward()
optimizer.step()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
5. Adam 优化器的优缺点
优点
- 自适应学习率:Adam 的每个参数都拥有自适应的学习率,不同参数的学习率会根据其梯度更新情况进行自动调整。
- 动量:Adam 在参数更新中引入了动量项,有效地平滑了更新方向,减少了噪声影响,加快了收敛速度。
- 无需手动调参:相比于 SGD,Adam 对学习率的要求相对宽松,训练过程较为稳定。
- 高效计算:Adam 的计算效率高,占用内存小,非常适合大规模数据和模型的训练。
缺点
- 过拟合风险:由于 Adam 可以快速适应参数变化,可能会导致过拟合,尤其是当模型复杂度较高且训练数据量较少时。
- 学习率退化:在一些特定任务中(如自然语言处理任务),Adam 可能会导致学习率在训练后期衰减过快,从而减缓模型进一步优化的速度。
- 较差的泛化性能:有时 Adam 优化器训练出的模型在测试集上的表现不如 SGD 优化器,尤其是当数据量较大时。
6. Adam vs. SGD
- SGD:具有更好的泛化能力,但收敛速度较慢,尤其在梯度较小或不平稳的情况下需要更大的调整。
- Adam:收敛速度更快且更稳定,适合处理稀疏数据和高维度数据,但在某些情况下泛化能力不
如 SGD。
7. 总结
torch.optim.Adam
是一种自适应优化算法,它结合了动量法和 RMSProp 的优点,使得优化过程更加高效且稳定。它适用于各种深度学习任务,尤其在处理大规模数据和高维度问题时表现出色。然而,在某些特定任务中,Adam 的泛化性能可能不如 SGD,因此在选择优化器时应根据具体任务进行调试和比较。