Pytorch实战: 常见优化器optimizer- Pytorch实现系列第8部分
常用十种优化器
-
torch.optim.SGD 随机梯度下降算法(动量momentum可选)
-
torch.optim.ASGD 平均随机梯度下降算法
-
torch.optim.Rprop 弹性反向传播 ---适用于full-batch,不适用于mini-batch
-
<推荐> torch.optim.Adagrad 自适应优化方法 ---自适应的为各个参数分配不同的学习率,学习率的变化,会受到梯度的大小和迭代次数的影响。梯度越大,学习率越小;梯度越小,学习率越大。缺点是训练后期,学习率过小
-
<推荐> torch.optim.Adadelta ---Adadelta是Adagrad的改进,避免在训练后期,学习率过小
-
<推荐> torch.optim.RMSprop
-
torch.optim.Adam(AMSGrad) ---Adam是一种自适应学习率的优化方法,Adam利用梯度的一阶矩估计和二阶矩估计动态的调整学习率通过添加额外的约束,使学习率始终为正值
-
torch.optim.Adamax ---Adamax是对Adam增加了一个学习率上限的概念
-
torch.optim.SparseAdam
-
torch.optim.LBFGS
简介
torch.optim
是一个实现了各种优化算法的库。
为了使用 torch.optim,你需要构建一个optimizer对象。这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。
optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)
为每个参数单独设置选项
model.base
的参数将会使用1e-2的学习率,model.classifier
的参数将会使用1e-3的学习率,并且0.9的momentum将会被用于所有的参数。
optim.SGD([ {'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 1e-3} ],
lr=1e-2, momentum=0.9)
优化函数
Adagrad(Adaptive Gradient)<推荐>
将每一个参数的每一次迭代的梯度取平方累加再开方,用基础学习率除以这个数,来做学习率的动态更新。
RMSprop<推荐>
为了缓解Adgrad学习率衰减过快,RMSprop对累计的信息进行衰减
Adadelta<推荐>
Adadelta是对Adagrad的扩展,Adagrad不需要设置初始学习速率,而是利用之前的步长估计下一步的步长。
Momentum冲量法
模拟物理动量的概念,积累之前的动量来替代真正的梯度。增加了同向的更新,减少了异向的更新。
Nesterov accelerated gradient(NAG)
再之前加速的梯度方向进行一个大的跳跃(棕色向量),计算梯度然后进行校正(绿色梯向量)
训练代码
分类问题训练代码
#----------------data------------------
data_num = 100
x = torch.unsqueeze(torch.linspace(-1,1,data_num), dim=1)
y0 = torch.zeros(50)
y1 = torch.ones(50)
y = torch.cat((y0, y1), ).type(torch.LongTensor) #数据
#----------------train------------------
optimizer = torch.optim.SGD(mynet.parameters(),lr=0.1) #优化器
loss_func = torch.nn.CrossEntropyLoss() #损失函数
for epoch in range(1000):
optimizer.zero_grad()
#forward + backward + optimize
pred = mynet(x)
loss = loss_func(pred,y)
loss.backward()
optimizer.step()
#----------------prediction---------------
test_data = torch.tensor([-1.0])
pred = mynet(test_data)
print(test_data, pred.data)
回归问题训练代码
#--------------data--------------------
x = torch.unsqueeze(torch.linspace(-1,1,100),dim=1)
y = x.pow(2)
#--------------train-------------------
optimizer = torch.optim.SGD(mynet.parameters(),lr=0.1) #优化器
loss_func = torch.nn.MSELoss() #损失函数
for epoch in range(1000):
optimizer.zero_grad()
#forward + backward + optimize
pred = mynet(x)
loss = loss_func(pred,y)
loss.backward()
optimizer.step()
#----------------prediction---------------
test_data = torch.tensor([-1.0])
pred = mynet(test_data)
print(test_data, pred.data)
tips: optimizer.zero_grad() 每次做反向传播之前都要归零梯度,不然梯度会累加在一起,造成结果不收敛。