PyTorch框架学习十三——优化器

  • 一、优化器
  • 二、Optimizer类
  • 1.基本属性
  • 2.基本方法
  • 三、学习率与动量
  • 1.学习率learning rate
  • 2.动量、冲量Momentum
  • 四、十种常见的优化器(简单罗列)


上次笔记简单介绍了一下损失函数的概念以及18种常用的损失函数,这次笔记介绍优化器的相关知识以及PyTorch中的使用。

一、优化器

PyTorch中的优化器:管理并更新模型中可学习参数的值,使得模型输出更接近真实标签。

导数:函数在指定坐标轴上的变化率。
方向导数:指定方向上的变化率。
梯度:一个向量,方向为方向导数取得最大值的方向。

二、Optimizer类

1.基本属性

  1. defaults:优化器超参数,包含优化选项的默认值的dict(当参数组没有指定这些值时使用)。
  2. state:参数的缓存,如momentum的缓存。
  3. param_groups:管理的参数组,形式上是列表,每个元素都是一个字典。

2.基本方法

(1)zero_grad():清空所管理的参数的梯度。因为PyTorch中张量梯度不会自动清零。

weight = torch.randn((2, 2), requires_grad=True)
weight.grad = torch.ones((2, 2))

optimizer = optim.SGD([weight], lr=0.1)

print("weight before step:{}".format(weight.data))
optimizer.step()        # 修改lr=1 0.1观察结果
print("weight after step:{}".format(weight.data))

print("weight in optimizer:{}\nweight in weight:{}\n".format(id(optimizer.param_groups[0]['params'][0]), id(weight)))

print("weight.grad is {}\n".format(weight.grad))
optimizer.zero_grad()
print("after optimizer.zero_grad(), weight.grad is\n{}".format(weight.grad))

结果如下:

weight before step:tensor([[0.6614, 0.2669],
        [0.0617, 0.6213]])
weight after step:tensor([[ 0.5614,  0.1669],
        [-0.0383,  0.5213]])
weight in optimizer:1314236528344
weight in weight:1314236528344

weight.grad is tensor([[1., 1.],
        [1., 1.]])

after optimizer.zero_grad(), weight.grad is
tensor([[0., 0.],
        [0., 0.]])

(2) step():执行一步优化更新。

weight = torch.randn((2, 2), requires_grad=True)
weight.grad = torch.ones((2, 2))

optimizer = optim.SGD([weight], lr=0.1)

print("weight before step:{}".format(weight.data))
optimizer.step()        # 修改lr=1 0.1观察结果
print("weight after step:{}".format(weight.data))

结果如下:

weight before step:tensor([[0.6614, 0.2669],
        [0.0617, 0.6213]])
weight after step:tensor([[ 0.5614,  0.1669],
        [-0.0383,  0.5213]])

(3) add_param_group():添加参数组。

weight = torch.randn((2, 2), requires_grad=True)
weight.grad = torch.ones((2, 2))

optimizer = optim.SGD([weight], lr=0.1)

print("optimizer.param_groups is\n{}".format(optimizer.param_groups))

w2 = torch.randn((3, 3), requires_grad=True)

optimizer.add_param_group({"params": w2, 'lr': 0.0001})

print("optimizer.param_groups is\n{}".format(optimizer.param_groups))

结果如下:

optimizer.param_groups is
[{'params': [tensor([[0.6614, 0.2669],
        [0.0617, 0.6213]], requires_grad=True)], 'lr': 0.1, 'momentum': 0, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}]
optimizer.param_groups is
[{'params': [tensor([[0.6614, 0.2669],
        [0.0617, 0.6213]], requires_grad=True)], 'lr': 0.1, 'momentum': 0, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}, {'params': [tensor([[-0.4519, -0.1661, -1.5228],
        [ 0.3817, -1.0276, -0.5631],
        [-0.8923, -0.0583, -0.1955]], requires_grad=True)], 'lr': 0.0001, 'momentum': 0, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}]

(4)state_dict():获取优化器当前状态信息字典。

weight = torch.randn((2, 2), requires_grad=True)
weight.grad = torch.ones((2, 2))

optimizer = optim.SGD([weight], lr=0.1, momentum=0.9)
opt_state_dict = optimizer.state_dict()

print("state_dict before step:\n", opt_state_dict)

for i in range(10):
    optimizer.step()

print("state_dict after step:\n", optimizer.state_dict())

torch.save(optimizer.state_dict(), os.path.join(BASE_DIR, "optimizer_state_dict.pkl"))

结果如下:

state_dict before step:
 {'state': {}, 'param_groups': [{'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'params': [2872948098296]}]}
state_dict after step:
 {'state': {2872948098296: {'momentum_buffer': tensor([[6.5132, 6.5132],
        [6.5132, 6.5132]])}}, 'param_groups': [{'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'params': [2872948098296]}]}

获取到了优化器当前状态的信息字典,其中那个2872948098296是存放权重的地址,并将这些参数信息保存为一个pkl文件:

pytorch adam优化器自带正则化 pytorch adam优化器参数_pytorch

(5)load_state_dict():加载状态信息字典。

optimizer = optim.SGD([weight], lr=0.1, momentum=0.9)
state_dict = torch.load(os.path.join(BASE_DIR, "optimizer_state_dict.pkl"))

print("state_dict before load state:\n", optimizer.state_dict())
optimizer.load_state_dict(state_dict)
print("state_dict after load state:\n", optimizer.state_dict())

从刚刚保存参数的pkl文件中读取参数赋给一个新的空的优化器,结果为:

state_dict before load state:
 {'state': {}, 'param_groups': [{'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'params': [1838346925624]}]}
state_dict after load state:
 {'state': {1838346925624: {'momentum_buffer': tensor([[6.5132, 6.5132],
        [6.5132, 6.5132]])}}, 'param_groups': [{'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'params': [1838346925624]}]}

注:state_dict()与load_state_dict()一般经常用于模型训练中的保存和读取模型参数,防止断电等突发情况导致模型训练强行中断而前功尽弃。

三、学习率与动量

1.学习率learning rate

梯度下降:

pytorch adam优化器自带正则化 pytorch adam优化器参数_数组_02


其中LR就是学习率,作用是控制更新的步伐,如果太大可能导致模型无法收敛或者是梯度爆炸,如果太小可能使得训练时间过长,需要调节。

2.动量、冲量Momentum

结合当前梯度与上一次更新信息,用于当前更新。

PyTorch中梯度下降的更新公式为:

pytorch adam优化器自带正则化 pytorch adam优化器参数_机器学习_03


其中:

pytorch adam优化器自带正则化 pytorch adam优化器参数_pytorch_04

  • Wi:第i次更新的参数。
  • lr:学习率。
  • Vi:更新量。
  • m:momentum系数。
  • g(Wi):Wi的梯度。

举个例子:

pytorch adam优化器自带正则化 pytorch adam优化器参数_深度学习_05


100这个时刻的更新量不仅与当前梯度有关,还与之前的梯度有关,只是越以前的对当前时刻的影响就越小。

momentum的作用主要是可以加速收敛。

四、十种常见的优化器(简单罗列)

目前对优化器的了解还不多,以后会继续跟进,这里就简单罗列一下:

  1. optim.SGD:随机梯度下降法
  2. optim.Adagrad:自适应学习率梯度下降法
  3. optim.RMSprop:Adagrad的改进
  4. optim.Adadelta:Adagrad的改进
  5. optim.Adam:RMSprop结合Momentum
  6. optim.Adamax:Adam增加学习率上限
  7. optim.SparseAdam:稀疏版的Adam
  8. optim.ASGD:随机平均梯度下降法
  9. optim.Rprop:弹性反向传播
  10. optim.LBFGS :BFGS的改进