我想在CIFAR-10上训练,假设训练200个时期。这是我的优化器:optimizer = optim.Adam([x for x in model.parameters() if x.requires_grad], lr=0.001)
我想使用OneCycleLR作为调度程序。现在,根据文件,这些是OneCycleLR:的参数
torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr, total_steps=None, epochs=None, steps_per_epoch=None, pct_start=0.3, anneal_strategy='cos', cycle_momentum=True, base_momentum=0.85, max_momentum=0.95, div_factor=25.0, final_div_factor=10000.0, three_phase=False, last_epoch=- 1, verbose=False)
我看到使用最多的是max_lr
、epochs
和steps_per_epoch
。文件上写着:
- max_lr(浮点或列表(–每个参数组在循环中的学习率上限
- 历元(int(–要训练的历元数。这与steps_per_epoch一起使用,以便在没有提供total_steps的值的情况下推断循环中的总步数。默认值:无
- steps_per_epoch(int(–每个epoch要训练的步数。如果没有提供total_steps的值,则将其与历元一起使用,以推断循环中的总步数。默认值:无
关于steps_per_epoch
,我在许多github repo中看到它使用的是steps_per_epoch=len(data_loader)
,所以如果我的批量大小为128,那么这个参数等于128。然而,我不明白其他两个参数是什么。如果我想训练200个时代,那么epochs=200
?或者这是一个仅为epoch
运行调度程序然后重新启动的参数?例如,如果我在调度器中写了10个历元,但我总共训练了200个,这就像调度器的20个完整步骤?然后max_lr
我看到人们使用的值大于优化器的lr,而其他人使用的值较小。我认为max_lr
必须大于lr(否则为什么它被称为max:smiley:?(然而,如果我逐时代打印学习率,它会呈现出奇怪的值。例如,在此设置中:
optimizer = optim.Adam([x for x in model.parameters() if x.requires_grad], lr=0.001)
scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr = 0.01, epochs=200, steps_per_epoch=128)
这就是学习率:
Epoch 1: TrL=1.7557, TrA=0.3846, VL=1.4136, VA=0.4917, TeL=1.4266, TeA=0.4852, LR=0.0004,
Epoch 2: TrL=1.3414, TrA=0.5123, VL=1.2347, VA=0.5615, TeL=1.2231, TeA=0.5614, LR=0.0004,
...
Epoch 118: TrL=0.0972, TrA=0.9655, VL=0.8445, VA=0.8161, TeL=0.8764, TeA=0.8081, LR=0.0005,
Epoch 119: TrL=0.0939, TrA=0.9677, VL=0.8443, VA=0.8166, TeL=0.9094, TeA=0.8128, LR=0.0005,
所以lr正在增加
文档中说,应该将total_steps
或两个epochs & steps_per_epoch
都作为参数。它们之间的简单关系是CCD_ 13。
total_steps
是循环中的总步数。名称中的OneCycle
表示训练只有一个周期。
CCD_ 16是CCD_ 17的最大学习率。确切地说,在第一个pct_start * total_steps
步骤中,学习率将从max_lr / div_factor
增加到max_lr
,然后平滑地降低到max_lr / final_div_factor
。
编辑:对于那些不熟悉lr_scheduler
的人,您可以绘制学习率曲线,例如
EPOCHS = 10
BATCHES = 10
steps = []
lrs = []
model = ... # Your model instance
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9) # Wrapped optimizer
scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer,max_lr=0.9,total_steps=EPOCHS * BATCHES)
for epoch in range(EPOCHS):
for batch in range(BATCHES):
scheduler.step()
lrs.append(scheduler.get_last_lr()[0])
steps.append(epoch * BATCHES + batch)
plt.figure()
plt.legend()
plt.plot(steps, lrs, label='OneCycle')
plt.show()