Pytorch与深度学习自查手册5-损失函数、优化器

损失函数

可以直接使用官方自带的损失函数,也可以自定义损失函数。

自定义损失函数

包括两种形式:

  1. 直接以函数形式定义
  2. 当作模型的一层,通过继承nn.Module定义(推荐)

直接以函数形式定义

def my_loss(output, target):
loss = torch.mean((output - target)**2)
return loss

(推荐)当作模型的一层,通过继承nn.Module定义

import torch.nn as nn
class DiceLoss(nn.Module):
def __init__():
super(DiceLoss,self).__init__()

def forward():
inputs = F.sigmoid(inputs)
inputs = inputs.view(-1)
targets = targets.view(-1)
intersection = (inputs * targets).sum()
dice = (2.*intersection + smooth)/(inputs.sum() + targets.sum() + smooth)
return 1 - dice

# 使用方法
criterion = DiceLoss()
loss = criterion(input,targets)

Pytorch自带损失函数

可以参考官网的损失函数部分或者知乎上的这篇帖子

优化器

官方给出了很多优化器可以直接使用:pytorch优化器

优化器的使用

  1. 每个优化器都是一个类,一定要进行实例化才能使用,比如下方实现:

    class Net(nn.Moddule):
    ···
    net = Net()
    optim = torch.optim.SGD(net.parameters(),lr=lr)
    optim.step()
  2. optimizer在一个神经网络的epoch中需要实现下面两个步骤:

    1. 梯度置零

    2. 梯度更新

      optimizer = torch.optim.SGD(net.parameters(), lr=1e-5)
      for epoch in range(EPOCH):
      ...
      optimizer.zero_grad() #梯度置零
      loss = ... #计算loss
      loss.backward() #BP反向传播
      optimizer.step() #梯度更新

优化器的重要参数

Optimizer属性:

  1. defaults:存储的是优化器的超参数,例子如下:

    {'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}
  2. state:参数的缓存,例子如下:

    defaultdict(<class 'dict'>, {tensor([[ 0.3864, -0.0131], [-0.1911, -0.4511]], requires_grad=True): {'momentum_buffer': tensor([[0.0052, 0.0052],[0.0052, 0.0052]])}})
  3. param_groups:管理的参数组,是一个list,其中每个元素是一个字典,顺序是params,lr,momentum,dampening,weight_decay,nesterov,例子如下:

    [{'params': [tensor([[-0.1022, -1.6890],[-1.5116, -1.7846]], requires_grad=True)], 'lr': 1, 'momentum': 0, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}]

Optimizer方法

  1. zero_grad():清空所管理参数的梯度,PyTorch的特性是张量的梯度不自动清零,因此每次反向传播后都需要清空梯度。
  2. step():执行一步梯度更新,参数更新
  3. add_param_group():添加参数组
  4. load_state_dict() :加载状态参数字典,可以用来进行模型的断点续训练,继续上次的参数进行训练
  5. state_dict():获取优化器当前状态信息字典

学习率控制器scheduler

同样分为官方提供和自定义两种方式。

官方提供的学习率控制器scheduler

pytorch可以利用optim中的scheduler动态控制学习率,常用的如:

设置方法如下:

# 选择一种优化器
optimizer = torch.optim.Adam(...)
# 选择上面提到的一种或多种动态调整学习率的方法
scheduler1 = torch.optim.lr_scheduler....
scheduler2 = torch.optim.lr_scheduler....
...
schedulern = torch.optim.lr_scheduler....
# 进行训练
for epoch in range(100):
train(...)
validate(...)
optimizer.step()
# 需要在优化器参数更新之后再动态调整学习率
scheduler1.step()
...
schedulern.step()

在使用官方给出的torch.optim.lr_scheduler时,需要将scheduler.step()放在optimizer.step()后面进行使用。

自定义scheduler

通过自定义函数adjust_learning_rate来改变param_grouplr的值,从而实现自定义scheduler。

假设需要学习率每30轮下降为原来的1/10,已有的官方API中没有符合我们需求的,那就需要自定义函数来实现学习率的改变。

def adjust_learning_rate(optimizer, epoch):
lr = args.lr * (0.1 ** (epoch // 30))
for param_group in optimizer.param_groups:
param_group['lr'] = lr

在训练的过程就可以调用adjust_learning_rate函数来实现学习率的动态变化:

def adjust_learning_rate(optimizer,...):
...
optimizer = torch.optim.SGD(model.parameters(),lr = args.lr,momentum = 0.9)
for epoch in range(10):
train(...)
validate(...)
adjust_learning_rate(optimizer,epoch)

参考资料

第六章-Pytorch进阶训练技巧

优化器