torch.optim
是一个实现了各种优化算法的库。
1. 如何使用optimizer
我们需要构建一个optimizer对象。这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。
1.1 构建
为了构建一个Optimizer
,你需要给它一个包含了需要优化的参数(必须都是Variable
对象)的iterable。然后,你可以设置optimizer的参 数选项,比如学习率,权重衰减,
等等。
例子:
optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)
1.2 为每个参数单独设置选项
Optimizer
也支持为每个参数单独设置选项。此时,我们应该传入dict
的iterable。每一个dict都分别定义了一组参数,并且包含一个param
键,这个键对应参数的列表。
当你只想改动一个参数组的选项,但其他参数组的选项不变时,这是非常有用的。
例如,当我们想指定每一层的学习率时,
optim.SGD([
{'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 1e-3}
], lr=1e-2, momentum=0.9)
这意味着model.base
的参数将会使用1e-2
的学习率,model.classifier
的参数将会使用1e-3
的学习率,并且0.9
的momentum将会被用于所有的参数。
1.3 进行单次优化
所有的optimizer都实现了step()
方法,这个方法会更新所有的参数。它能按两种方式来使用:
1.optimizer.step()
这是大多数optimizer所支持的简化版本。一旦梯度被如backward()之类的函数计算好后,我们就可以调用这个函数。
例子:
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
2.optimizer.step(closure)
这个函数的用法没看懂,但用的也很少。
2. 优化器
class torch.optim.Optimizer(params, defaults)
这是所有优化器的基类。
参数:
- params (iterable) ——
Variable
或者dict
的iterable。指定了什么参数应当被优化。 - defaults —— (dict):包含了优化选项默认值的字典(一个参数组没有指定的参数选项将会使用默认值)。
(1)load_state_dict(state_dict)
加载optimizer状态。
参数:
state_dict (dict
) —— optimizer的状态。应当是一个调用state_dict()
所返回的对象。
(2)state_dict()
以dict
返回optimizer的状态。
它包含两项。
state
- 一个保存了当前优化状态的dict。optimizer的类别不同,state的内容也会不同。
param_groups
- 一个包含了全部参数组的dict。
(3)step(closure)
进行单次优化 (参数更新)。
closure参数是可选的。
(4)zero_grad()
清空所有被优化过的Variable的梯度。
下面给出几个最常用的优化器。
class torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)[source]
参数:
- params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
- lr (float, 可选) – 学习率(默认:1e-3)
- betas (Tuple[float, float], 可选) – 用于计算梯度以及梯度平方的运行平均值的系数(默认:0.9,0.999)
- eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)
- weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)
class torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)[source]
参数:
- params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
- lr (float, 可选) – 学习率(默认:1e-2)
- momentum (float, 可选) – 动量因子(默认:0)
- alpha (float, 可选) – 平滑常数(默认:0.99)
- eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)
- centered (bool, 可选) – 如果为True,计算中心化RMSProp,并且用它的方差预测值对梯度进行归一化
- weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)
class torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)[source]
参数:
- params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
- lr (float) – 学习率
- momentum (float, 可选) – 动量因子(默认:0)
- weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认:0)
- dampening (float, 可选) – 动量的抑制因子(默认:0)
- nesterov (bool, 可选) – 使用Nesterov动量(默认:False)
例子:
>>> optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
>>> optimizer.zero_grad()
>>> loss_fn(model(input), target).backward()
>>> optimizer.step()
3. 调整学习率
torch.optim.lr_scheduler
提供了几种方法来根据 epoch 的数量调整学习率。
学习率调整应该在优化器更新后应用,比如:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler = ExponentialLR(optimizer, gamma=0.9)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler.step()
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=- 1, verbose=False)
将每个参数组的学习率设置为初始 lr 乘以给定函数。当 last_epoch=-1
时,设置initial lr
为 lr。
l r e p o c h = l r i n i t i a l ∗ l r _ l a m b d a ( e p o c h ) lr_{epoch} =lr_{initial} * lr\_lambda(epoch) lrepoch=lrinitial∗lr_lambda(epoch)
# Assuming optimizer has two groups.
lambda1 = lambda epoch: epoch // 30
lambda2 = lambda epoch: 0.95 ** epoch
scheduler = LambdaLR(optimizer, lr_lambda=[lambda1, lambda2])
for epoch in range(100):
train(...)
validate(...)
scheduler.step()
torch.optim.lr_scheduler.MultiplicativeLR(optimizer, lr_lambda, last_epoch=- 1, verbose=False)
将每个参数组的学习率乘以指定函数中给出的因子。 当 last_epoch=-1 时,设置初始 lr 为 lr。
l r e p o c h = l r e p o c h − 1 ∗ l r _ l a m b d a ( e p o c h ) lr_{epoch} =lr_{epoch - 1} * lr\_lambda(epoch) lrepoch=lrepoch−1∗lr_lambda(epoch)
lmbda = lambda epoch: 0.95
scheduler = MultiplicativeLR(optimizer, lr_lambda=lmbda)
for epoch in range(100):
train(...)
validate(...)
scheduler.step()
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=- 1, verbose=False)
每 step_size epochs
衰减每个参数组的学习率。 请注意,这种衰减可能与此调度程序外部对学习率的其他更改同时发生。 当 last_epoch=-1 时,设置初始 lr 为 lr。
# Assuming optimizer uses lr = 0.05 for all groups
# lr = 0.05 if epoch < 30
# lr = 0.005 if 30 <= epoch < 60
# lr = 0.0005 if 60 <= epoch < 90
# ...
scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
for epoch in range(100):
train(...)
validate(...)
scheduler.step()
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=- 1, verbose=False)
一旦 epoch 的数量达到milestones
之一,通过 gamma 衰减每个参数组的学习率。 请注意,这种衰减可能与此调度程序外部对学习率的其他更改同时发生。 当 last_epoch=-1 时,设置初始 lr 为 lr。
# Assuming optimizer uses lr = 0.05 for all groups
# lr = 0.05 if epoch < 30
# lr = 0.005 if 30 <= epoch < 80
# lr = 0.0005 if epoch >= 80
scheduler = MultiStepLR(optimizer, milestones=[30,80], gamma=0.1)
for epoch in range(100):
train(...)
validate(...)
scheduler.step()
torch.optim.lr_scheduler.ConstantLR(optimizer, factor=0.3333333333333333, total_iters=5, last_epoch=- 1, verbose=False)
将每个参数组的学习率衰减一个小的常数因子,直到 epoch 的数量达到预定义的total_iters
。 请注意,这种衰减可能与此调度程序外部对学习率的其他更改同时发生。 当 last_epoch=-1 时,设置初始 lr 为 lr。
# Assuming optimizer uses lr = 0.05 for all groups
# lr = 0.025 if epoch == 0
# lr = 0.025 if epoch == 1
# lr = 0.025 if epoch == 2
# lr = 0.025 if epoch == 3
# lr = 0.05 if epoch >= 4
scheduler = ConstantLR(self.opt, factor=0.5, total_iters=4)
for epoch in range(100):
train(...)
validate(...)
scheduler.step()
torch.optim.lr_scheduler.LinearLR(optimizer, start_factor=0.3333333333333333, end_factor=1.0, total_iters=5, last_epoch=- 1, verbose=False)
通过线性改变小的乘法因子来衰减每个参数组的学习率,直到 epoch 的数量达到预定义的total_iters。 请注意,这种衰减可能与此调度程序外部对学习率的其他更改同时发生。 当 last_epoch=-1 时,设置初始 lr 为 lr。
# Assuming optimizer uses lr = 0.05 for all groups
# lr = 0.025 if epoch == 0
# lr = 0.03125 if epoch == 1
# lr = 0.0375 if epoch == 2
# lr = 0.04375 if epoch == 3
# lr = 0.05 if epoch >= 4
scheduler = LinearLR(self.opt, start_factor=0.5, total_iters=4)
for epoch in range(100):
train(...)
validate(...)
scheduler.step()