momentum(动量,惯性)
动量使用的原理:
梯度下降,原本是使用当前 k 的参数 - 当前 k 的梯度乘以学习率,得到下一组更新的 k+1 参数。
使用动量之后,与学习率相乘的不仅是当前 k 的梯度,也有 k 之前的梯度的整合,学习率乘以 k 之前的梯度,还有一部分当前 k 的梯度。换句话说,就是参数不仅沿着当前梯度的方向衰减,之前梯度的方向也会有衰减。
momentum的优缺点:
有惯性后,可能不会在局部极小值休息。想象成滑雪的过程,如果没有惯性,在局部最低点就会停下来了,而有惯性,他会继续滑行,会滑到山底而不是山腰。但是有momentum会更新更慢。
操作中,Adam直接包含momentum,SGD需要自己设置eg0.78,历史方向0.78的权重
learning rate decay(学习率衰退)
学习率过小,时间损耗很多(第一个图),过大,可能略过最小值的位置(第三个图),然后在两个较大值上横跳
学习率最好能做到,先大后小,前期下降的快,之后慢慢下降
以上是一个真实的优化例子,横坐标是迭代次数,这里loss有一个剧变,可能是因为,之前 lr 比较大,更新后得到的loss总是在不段横跳,到达不了最低点,剧变这里,突然 lr 变小,参数变化的小,loss变化的也小,能到达最低点了
两种常见的learning rate decay方案
1 如果loss到达了一个很平坦的地方,好几次的更新参数,loss都不变化,怀疑需要减小lr
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, momentum=0.78, weight_decay=1e-5)
scheduler = ReduceLROnPlateau(optimizer,'min',factor=0.1,patience=5,threshold=0.001)
# loss要最小化,lr下降为原来的0.1,5次loss不变化就改lr,loss变化小于0.001就算是不变化
for epoch in xrange(start_epoch, epochs):
train(train_loader,model, criterion, optimizer,epoch)
result, loss = validate(val_loader, model, criterion, epoch)
scheduler.step(loss_val)
# 权重衰减通过向损失函数添加一个正则化项来限制模型参数的大小,从而防止过拟合
# 在每个 epoch 中,首先进行训练(使用 train 函数)
# 然后进行验证(使用 validate 函数),并获取验证集上的损失值。
# 最后,调用 scheduler.step(loss_val) 来根据验证集上的损失值来调整学习率。
2 规定每30个epoch,把lr衰减为原来的0.1
scheduler = stepLR(optimizer,step_size=30, gamma=0.1)
for epoch in range(100):
scheduler.step()
train()
validate()
# 每 30 个 epoch 进行一次学习率的调整。每次调整时学习率都会乘以 0.1。