Pytorch模型训练--Optimizer(5)

版权声明:未经博主允许,不得转载! https://blog.csdn.net/u011681952/article/details/86630870

  本文总结Pytorch中的Optimizer
  Optimizer是深度学习模型训练中非常重要的一个模块,它决定参数参数更新的方向,快慢和大小,好的Optimizer算法和合适的参数使得模型收敛又快又准
  但本文不会讨论什么任务用什么Optimizer,及其参数设置,只是总结下Pytorch中的Optimizer

torch.optim

  Pytorch的torch.optim是包含各种优化器算法的包,支持通用优化器方法,接口通用性好,也方便集成更加复杂的算法

  怎样使用一个Optimizer ???
  要使用Optimizer,我们首先要创建一个Optimizer对象,该对象会保持当前状态,并根据计算梯度来更新参数

  1)创建Optimizer
  创建Optimizer时,需要为其提供一些需要迭代的参数进行迭代,还可以指定一些可选的,特定的,用于优化的参数,如学习率,权重衰减等参数
  Example:

optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)

  注意1:如果需要将模型移到GPU,可以通过".cuda"来实现

optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9).cuda()
optimizer = optim.Adam([var1, var2], lr = 0.0001).cuda()

  注意2:在训练中,最好保持模型和优化在相同位置,即要在GPU,都在GPU

  2)Optimizer参数
  Optimizer支持特殊参数指定选项,这样需要用一个字典(dict)类型的可迭代参数代替变量(Variable)可迭代参数;它们有各自的参数组,用"params"关键字将他们独立开(包含属于它的参数列表)
  在需要不同层不同参数时,非常有用,如:

optim.SGD([
                {'params': model.base.parameters()},
                {'params': model.classifier.parameters(), 'lr': 1e-3}
            ], lr=1e-2, momentum=0.9)

  也就是,classifier.parameters的学习率为1e-3,base.parameters的学习率为le-2,动量0.9适用所有参数

  3)Optimizer迭代
  迭代,更新参数,一般有下面2中方式:
  方式1:

optimizer.step()

  该方式能满足大多需求,一般只要进行梯度需要,如backward(),这个step()函数就需要被召唤
  Example:

for input, target in dataset:
    optimizer.zero_grad()
    output = model(input)
    loss = loss_fn(output, target)
    loss.backward()
    optimizer.step()

  方式2:

optimizer.step(closure)

  一些特殊算法,如共轭梯度(Conjugate Gradient) 和 LBFGS 需要多次重新评估函数,所以需要传入一个允许重新计算模型的闭包(closure),来清理梯度,计算loss并返回
  Example:

for input, target in dataset:
    def closure():
        optimizer.zero_grad()
        output = model(input)
        loss = loss_fn(output, target)
        loss.backward()
        return loss
    optimizer.step(closure)

Algorithms

Optimizer基类

torch.optim.Optimizer(params, defaults)

  所有Optimizer的基类

  参数:
  1)params:可迭代对象,需要被优化的参数对象,一般为张量(torch.Tensor)或字典(dict)
  2)defaults:字典类型,一些优化选项,基本都有默认值

  方法:
  1)add_param_group(param_group)
    增加需要优化的参数到param_groups,如在使用预训练模型进行微调时,很有用,可以将冻结层参数添加到训练中
  2)load_state_dict(state_dict)
    加载优化器参数
  3)state_dict()
    返回优化器状态,字典类型,包括优化器状态和参数组
  4)step(closure)
    单步更新
  5)zero_grad()
    清空优化器参数的梯度

Optimizer

torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)


torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)


torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)


torch.optim.SparseAdam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08)

torch.optim.Adamax(params, lr=0.002, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)


torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)


torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)


torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)


torch.optim.Rprop(params, lr=0.01, etas=(0.5, 1.2), step_sizes=(1e-06, 50))


torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)

  这些Optimizer部分,我罗列的比较简单,因为在应用层,无非是他们的参数,而这些参数就关乎算法原理,不是本文重点,有兴趣可以参见梯度下降算法原理的博客

学习率调节

  这些优化器中往往需要多个参数,共同控制才能达到优化目的,但大多数参数都有默认参考值,这些值都是大牛们经过多方验证得出的,所以我们在训练模型时,需要手动设置的参数并不多
  其中最需要我们手动调节的就是学习率,关于学习率衰减理论部分可参见个人博客;而Pytorch中怎么调用呢?

torch.optim.lr_scheduler

  提供了基于epochs调节学习率的方法;主要有以下几种:

torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)

torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)

torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)

torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)

torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)

torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)

  Example:

optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = ReduceLROnPlateau(optimizer, 'min')
for epoch in range(10):
train(...)
val_loss = validate(...)
# Note that step should be called after validate()
 scheduler.step(val_loss)

CPN Optimizer

  1)实例化Adam优化器

optimizer = torch.optim.Adam(model.parameters(),
                            lr = cfg.lr,
                            weight_decay=cfg.weight_decay)

  2)若resume,加载优化器状态

if args.resume:
    if isfile(args.resume):
        print("=> loading checkpoint '{}'".format(args.resume))
        checkpoint = torch.load(args.resume)
        pretrained_dict = checkpoint['state_dict']
        model.load_state_dict(pretrained_dict)
        args.start_epoch = checkpoint['epoch']
        
        optimizer.load_state_dict(checkpoint['optimizer'])
        
        print("=> loaded checkpoint '{}' (epoch {})"
              .format(args.resume, checkpoint['epoch']))
        logger = Logger(join(args.checkpoint, 'log.txt'), resume=True)
    else:
        print("=> no checkpoint found at '{}'".format(args.resume))
else:        
    logger = Logger(join(args.checkpoint, 'log.txt'))
    logger.set_names(['Epoch', 'LR', 'Train Loss'])

  3)训练时(学习率调节,train,优化器迭代,模型保存)

    for epoch in range(args.start_epoch, args.epochs):
    
    	#调节学习率
        lr = adjust_learning_rate(optimizer, epoch, cfg.lr_dec_epoch, cfg.lr_gamma)
        print('\nEpoch: %d | LR: %.8f' % (epoch + 1, lr)) 

        # train for one epoch
        #将优化器给train函数
        train_loss = train(train_loader, model, [criterion1, criterion2], optimizer)
        print('train_loss: ',train_loss)

        # append logger file
        logger.append([epoch + 1, lr, train_loss])

		#保存模型,也保存优化器状态
        save_model({
            'epoch': epoch + 1,
            'state_dict': model.state_dict(),
            'optimizer' : optimizer.state_dict(),
        }, checkpoint=args.checkpoint)

  细节1:学习率调节函数adjust_learning_rate

def adjust_learning_rate(optimizer, epoch, schedule, gamma):
    """Sets the learning rate to the initial LR decayed by schedule"""
    if epoch in schedule:
        for param_group in optimizer.param_groups:
            param_group['lr'] *= gamma
    return optimizer.state_dict()['param_groups'][0]['lr']

  细节2:train函数,优化器迭代

    # compute gradient and do Optimization step
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

猜你喜欢

转载自blog.csdn.net/u011681952/article/details/86630870