参考资料:
一、优化器PyTorch常用的优化方法都封装在torch. optim里面,其设计很灵活,可以扩展为自定义的优化方法。所有的优化方法都是继承了基类optim.Optimizer,并实现了自己的优化步骤。最常用的优化算法就是梯度下降法及其各种变种,后续章节我们将介绍各种算法的原理,这类优化算法通过使用参数的梯度值更新参数。
说明使用优化器的一-般步骤为:
(1) 建立优化器实例
导入optim模块,实例化SGD优化器,这里使用动量参数momentum (该值一般在(0,1) 之间),是SGD的改进版,效果一般比不使用动量规则的要好.
import torch.optim as optim optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)
以下步骤在训练模型的for循环中
(2)向前传播
把输入数据传入神经网络Net实例化对象model中,自动执行forward函数,得到out输出值,然后用out与标记label计算损失值loss.
out=model(img) loss=criterion(out,label)
(3)清空梯度
缺省情况梯度是累加的,在梯反向传播前,先需要把梯度清零.
optimizer.zero_grad()
(4)反向传播
基于损失值,把梯度进行反向传播.
loss.backward()
(5)更新参数
基于当前梯度(存储在参数的.grad属性中)更新参数
optimizer.step()二、动态修改学习率参数
修改参数的方式可以通过修改参数optimizer. params_ groups或新建optimizer。 新建optimizer比较简单,optimizer十分轻量级, 所以开销很小。但是新的优化器会初始化动量等状态信息,这对于使用动量的优化器(momentum参数的sgd)可能会造成收敛中的震荡。所以,这里直接采用修改参数optimizer.params_ groups。
optimizer.param_ groups: 长度1的list,
optimizer.param_ groups[0]: 长度为6的字典,包括权重参数、Ir、 momentum等参数。
len(optimizer.param_groups[0])#结果为6
动态修改学习率参数
for epoch in range(num_epoches): # 动态修改参数学习率 if epoch%5 == 0: optimizer.param_groups[0][lr] *= 0.1 print(optimizer.param_groups[O]['lr']) for img, label in train_loader:####三、优化器比较
PyTorch中的优化器很多,各种优化器一-般都有 其适应的场景,不过,像自适应优化器在深度学习中比较受欢迎,除了性能较好,鲁棒性、泛化能力也更强。这里通过一个简单实例进行说明。
1)导入需要的模块。
import torch import torch.utils.data as Data import torch.nn.functional as F import matplotlib. pyplot as plt %matplotlib inline #超参数 LR = 0.01 BATCH_SIZE = 32 EPOCH= 12
2)生成数据。
#生成训练数据 # torch.unsqueeze()的作用是将一维变二 维,torch只能处理二 维的数据 x = torch.unsqueeze(torch.linspace(-1, 1, 1000), dim=1) # 0.1 * torch.normal(x.size()增加噪点 y = x.pow(2) + 0.1 * torch.normal(torch.zeros(*x.size())) torch_dataset = Data.TensorDataset(x,y) #得 到一个代批量的生成器 loader = Data.DataLoader(dataset=torch_dataset,batch_size=BATCH_SIZE, shuffle=True)
3)构建神经网络。
class Net(torch.nn.Module): # 初始化 def __init__(self): super(Net, self).__init__() self.hidden = torch.nn.Linear(1, 20) self.predict = torch.nn.Linear(20, 1) # 前向传递 def forward(self, x): x = F.relu(self.hidden(x)) x = self.predict(x) return x
4)使用多种优化器。
net_SGD = Net() net_Momentum = Net() net_RMSProp = Net() net_Adam = Net() nets = [net_SGD, net_Momentum, net_RMSProp, net_Adam] opt_SGD =torch.optim.SGD(net_SGD.parameters(), lr=LR) opt_Momentum = torch.optim.SGD(net_Momentum.parameters(),lr=LR, momentum=0.9) opt_RMSProp =torch.optim.RMSprop(net_RMSProp.parameters(), lr=LR, alpha=0.9) opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99)) optimizers = [opt_SGD, opt_Momentum, opt_RMSProp, opt_Adam]
5)训练模型。
loss_func = torch.nn.MSELoss() loss_his= [[],[],[], []] #记录损失 for epoch in range(EPOCH): for step, (batch_x, batch_y) in enumerate(loader): for net, opt,l_his in zip(nets,optimizers, loss_his): output = net(batch_x) # get output for every net loss = loss_func(output, batch_y) # compute loss for every net opt.zero_grad() # clear gradients for next train loss.backward() # backpropagation, compute gradients opt.step() # apply gradients l_his.append(loss.data.numpy()) # loss recoder labels= ['SGD', 'Momentum', 'RMSprop', 'Adam']
- 可视化结果。
for i,l_loss in enumerate(loss_his): plt.plot(l_his,label=labels[i]) plt.legend(loc="best") plt.xlabel("Steps") plt.ylabel("Loss") plt.ylim((0,0.2)) plt.show()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)