- checkpoint要存的东西如下:但为啥TransENet中还存了loss,查看所有.pt文件
- optimizer中存的参数是啥
选择优化器和设置学习率调整策略的直接实现
那为什么要重写optimizer和scheduler呢,如下所示:
def make_optimizer(args, my_model):
trainable = filter(lambda x: x.requires_grad, my_model.parameters())
if args.optimizer == 'SGD':
optimizer_function = optim.SGD
kwargs = {'momentum': args.momentum}
elif args.optimizer == 'ADAM':
optimizer_function = optim.Adam
kwargs = {
'betas': (args.beta1, args.beta2),
'eps': args.epsilon
}
elif args.optimizer == 'RMSprop':
optimizer_function = optim.RMSprop
kwargs = {'eps': args.epsilon}
kwargs['lr'] = args.lr
kwargs['weight_decay'] = args.weight_decay
return optimizer_function(trainable, **kwargs)
def make_scheduler(args, my_optimizer):
if args.decay_type == 'step':
scheduler = lrs.StepLR(
my_optimizer,
step_size=args.lr_decay,
gamma=args.gamma
)
elif args.decay_type.find('step') >= 0:
milestones = args.decay_type.split('_')
milestones.pop(0)
milestones = list(map(lambda x: int(x), milestones))
scheduler = lrs.MultiStepLR(
my_optimizer,
milestones=milestones,
gamma=args.gamma
)
return scheduler
然后在训练的时候调用
self.optimizer = utils.make_optimizer(args, self.model) # 选择优化器
self.scheduler = utils.make_scheduler(args, self.optimizer) # 设置学习率调整策略
当然是因为想要实现更多的功能,比如:
1.在迁移学习时需要冻结部分网络层的参数,
trainable = filter(lambda x: x.requires_grad, my_model.parameters())
这一句就可以选择只给requires_grad=TRUE的参数设置优化器
2.很多参数希望用更方便的argparse传入,那就需要把可选的优化器、对应的初始化参数、学习策略相关参数等等,用args.*的形式设置为选项。自然需要重新一个函数进行包装。
Pytorch的优化器:
管理并更新模型中可学习参数的值, 使得模型输出更接近真实标签。
Pytorch里面优化器的基本属性:
defaults: 优化器超参数,里面会存储一些学习了, momentum的值,衰减系数等
state: 参数的缓存, 如momentum的缓存(使用前几次梯度进行平均)
param_groups: 管理的参数组, 这是个列表,每一个元素是一个字典,在字典中有key,key里面的值才是我们真正
的参数(这个很重要, 进行参数管理)
_step_count: 记录更新次数, 学习率调整中使用, 比如迭代100次之后更新学习率的时候,就得记录这里的100.
优化器里面的基本方法:
zero_grad(): 清空所管理参数的梯度, 这里注意Pytorch有一个特性就是张量梯度不自动清零
step(): 执行一步更新
add_param_group(): 添加参数组, 我们知道优化器管理很多参数,这些参数是可以分组的,我们对不同组的参数
可以设置不同的超参数, 比如模型finetune中,我们希望前面特征提取的那些层学习率小一些,
而后面我们新加的层学习率大一些更新快一点,就可以用这个方法。
state_dict(): 获取优化器当前状态信息字典
load_state_dict(): 加载状态信息字典,这两个方法用于模型断点的一个续训练, 所以我们在模型训练的时候,
一般多少个epoch之后就要保存当前的状态信息。
Pytorch的学习率调整策略:
在学习学习率调整策略之前,得先学习一个基类_LRScheduler, 因为后面的六种学习率调整策略都是继承于这个类的,所以得先明白这个类的原理:
主要属性:
optimizer: 关联的优化器, 得需要先关联一个优化器,然后再去改动学习率
last_epoch: 记录epoch数, 学习率调整以epoch为周期
base_lrs: 记录初始学习率
主要方法:
step(): 更新下一个epoch的学习率, 这个是和用户对接
get_lr(): 虚函数, 计算下一个epoch的学习率, 这是更新过程中的一个步骤
pytorch的六种学习率调整策略小结一下:
有序调整:Step、MultiStep、 Exponential和CosineAnnealing, 这些得事先知道学习率大体需要在多少个epoch之后调整的时候用
自适应调整: ReduceLROnPleateau, 这个非常实用,可以监控某个参数,根据参数的变化情况自适应调整
自定义调整:Lambda, 这个在模型的迁移中或者多个参数组不同学习策略的时候实用
总结
我们需要先知道一个复杂函数中的核心语句,其次是对它进行重写包装的目的。
小tip
断点续存可以把所有要存的放进一个字典(eg:pytorch学习笔记中的示例)也可以分别存多个.pt文件(eg:TransENet参考代码)