深度学习-Optimizer优化器的比较

深度学习中常用的优化器一般有如下几种:

BGD(批量梯度下降法,Batch Gradient Descent):是最原始的形式,它是指在每一次迭代时使用所有样本来进行梯度的更新。

   优点:由全数据集确定的方向能够更好地代表样本总体,从而更准确地朝向极值所在的方向。当目标函数为凸函数时,BGD一定能够得到全局最优。

  缺点:当样本数目 mm 很大时,每迭代一步都需要对所有样本计算,训练过程会很慢。

SGD(随机梯度下降法,Stochastic Gradient Descent):原理和BGD类似,只不过每个迭代不是对全部的数据,而是随机抽取数据进行更新损失值。

   优点:由于不是在全部训练数据上的损失函数,而是在每轮迭代中,随机优化某一条训练数据上的损失函数,这样每一轮参数的更新速度大大加快。

   缺点:(1)准确度下降。由于即使在目标函数为强凸函数的情况下,SGD仍旧无法做到线性收敛。(2)可能会收敛到局部最优,由于单个样本并不能代表全体样本的趋势。

Momentum(动量优化法):动量优化方法是在梯度下降法的基础上进行的改变,具有加速梯度下降的作用。简单理解,就是为了防止波动,取前几次波动的平均值当做这次的权值W(记录之前几次更新的方向)。

   优点:前后梯度方向一致时,能够加速学习,前后梯度方向不一致时,能够抑制震荡。

   缺点:比较难学习一个较好的学习率。

AdaGrad算法:随着算法不断迭代,梯度累计变量会越来越大,整体的学习率会越来越小。所以,一般来说AdaGrad算法一开始是激励收敛,到了后面就慢慢变成惩罚收敛,速度越来越慢。

   优点:不需要人为的调节学习率,它可以自动调节。

   缺点:随着迭代次数增多,学习率会越来越小,最终会趋近于0。

RMSProp算法(root mean square prop):修改了AdaGrad的梯度积累为指数加权的移动平均,使纵轴方向上摆动较小,而横轴方向继续推进。

   优点:由于取了个加权平均,避免了学习率越来越低的的问题,而且能自适应地调节学习率。

   缺点:依然依赖于全局学习速率

Adam算法:简单来讲 Adam 算法就是综合了 Momentum 和 RMSProp 的一种算法,其既记录了历史梯度均值作为动量,又考虑了历史梯度平方和实现各个参数的学习率自适应调整,解决了 更新方向不稳定和学习率的问题。

 

这里比较四个优化器的损失情况:

import torch
import torch.utils.data as Data
import matplotlib.pyplot as plt

"""超参数"""
LR = 0.01
BATCH_SIZE = 32
EPOCH = 12
"""生成随机数据"""
x = torch.unsqueeze(torch.linspace(-1, 1, 1000), dim=1)  # 生成1000个-1到1之间的数据点,按照维度1(列)排列
y = x.pow(2) + 0.1 * torch.normal(torch.zeros(*x.size()))  # normal为
torch_dataset = Data.TensorDataset(x, y)
loader = Data.DataLoader(dataset=torch_dataset, batch_size=BATCH_SIZE, shuffle=True)  # 数据加载器
"""创建四个不同的神经网络"""
net_SGD = torch.nn.Sequential(torch.nn.Linear(1, 20), torch.nn.ReLU(), torch.nn.Linear(20, 1))
net_Momentun = torch.nn.Sequential(torch.nn.Linear(1, 20), torch.nn.ReLU(), torch.nn.Linear(20, 1))
net_RMSprop = torch.nn.Sequential(torch.nn.Linear(1, 20), torch.nn.ReLU(), torch.nn.Linear(20, 1))
net_Adam = torch.nn.Sequential(torch.nn.Linear(1, 20), torch.nn.ReLU(), torch.nn.Linear(20, 1))
nets = [net_SGD, net_Momentun, net_RMSprop, net_Adam]  # 将四个神经网络放入列表中
"""设置不同的优化方法"""
opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR)
opt_Momentun = torch.optim.SGD(net_Momentun.parameters(), lr=LR, momentum=0.8)  # Momentun也是用的SGD,只是加了一个属性
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_Momentun, opt_RMSprop, opt_Adam]  # 将四个标签放入列表中
"""计算误差"""
loss_func = torch.nn.MSELoss()
losses_his = [[], [], [], []]  # 记录误差
for epoch in range(EPOCH):  # 训练12次
    for step, (b_x, b_y) in enumerate(loader):  # 批数据训练
        for net, opt, l_his in zip(nets, optimizers, losses_his):  # 遍历不同的神经网络
            output = net(b_y)
            loss = loss_func(output, b_y)  # 计算误差
            opt.zero_grad()  # 清空梯度
            loss.backward()  # 反向传播
            opt.step()
            l_his.append(loss.data.numpy())  # 误差放入记录里面
"""绘制"""
labels = ['SGD', 'Momentum', 'RMSprop', 'Adam']
for i, l_his in enumerate(losses_his):
    plt.plot(l_his, label=labels[i])  # 取出每一种的损失值来显示,共四种,并取出相应的标签,标签和数据绑定
plt.legend(loc='best')  # 显示图例,best代表自动分配最佳位置来显示
plt.xlabel('Steps')
plt.ylabel('Loss')
plt.ylim(0, 0.2)
plt.show()

深度学习-Optimizer优化器的比较_第1张图片

 

 

 

 

你可能感兴趣的:(深度学习)