Pytorch总结十五之优化算法:AdaGrad、RMSProp、AdaDelta、Adam算法详解
Pytorch总结十五之优化算法:AdaGrad、RMSProp、AdaDelta、Adam算法详解
简介:
- 继续解析优化算法!
1. AdaFrad算法
1.1 算法
1.2 特点
#Adagrad算法
import math
import torch
import sys
sys.path.append("..")
import d2lzh_pytorch as d2ldef adagrad_2d(x1,x2,s1,s2):g1,g2,eps=0.2*x1,4*x2,1e-6 #前两项为自变量梯度s1+=g1**2s2+=g2**2x1-=eta/math.sqrt(s1+eps)*g1x2-=eta/math.sqrt(s2+eps)*g2return x1,x2,s1,s2def f_2d(x1,x2):return 0.1*x1**2+2*x2**2eta=0.4
d2l.show_trace_2d(f_2d,d2l.train_2d(adagrad_2d))
output:
epoch 20, x1 -2.382563, x2 -0.158591
下⾯将学习率增⼤到2。可以看到⾃变量更为迅速地逼近了最优解。
eta=2
d2l.show_trace_2d(f_2d,d2l.train_2d(adagrad_2d))
output:
epoch 20, x1 -0.002295, x2 -0.000000
1.3 从零开始实现
同动量法⼀样,AdaGrad算法需要对每个⾃变量维护同它⼀样形状的状态变量。我们根据AdaGrad算
法中的公式实现该算法。
##从零实现adagrad算法
def get_data_ch7(): data = np.genfromtxt('data/airfoil_self_noise.dat', delimiter='\t')data = (data - data.mean(axis=0)) / data.std(axis=0)return torch.tensor(data[:1500, :-1], dtype=torch.float32), \torch.tensor(data[:1500, -1], dtype=torch.float32) # 前1500个样本(每个样本5个特征)def init_adagrad_states():s_w=torch.zeros((features.shape[1],1),dtype=torch.float32)s_b=torch.zeros(1,dtype=torch.float32)return (s_w,s_b)def adagrad(params,states,hyperparams):eps=1e-6for p,s in zip(params,states):s.data+=(p.grad.data**2)p.data-=hyperparams['lr']*p.grad.data/torch.sqrt(s+eps)def train_ch7(optimizer_fn, states, hyperparams, features, labels,batch_size=10, num_epochs=2):# 初始化模型net, loss = linreg, squared_lossw = torch.nn.Parameter(torch.tensor(np.random.normal(0, 0.01, size=(features.shape[1], 1)), dtype=torch.float32),requires_grad=True)b = torch.nn.Parameter(torch.zeros(1, dtype=torch.float32), requires_grad=True)def eval_loss():return loss(net(features, w, b), labels).mean().item()ls = [eval_loss()]data_iter = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(features, labels), batch_size, shuffle=True)for _ in range(num_epochs):start = time.time()for batch_i, (X, y) in enumerate(data_iter):l = loss(net(X, w, b), y).mean() # 使用平均损失# 梯度清零if w.grad is not None:w.grad.data.zero_()b.grad.data.zero_()l.backward()optimizer_fn([w, b], states, hyperparams) # 迭代模型参数if (batch_i + 1) * batch_size % 100 == 0:ls.append(eval_loss()) # 每100个样本记录下当前训练误差# 打印结果和作图print('loss: %f, %f sec per epoch' % (ls[-1], time.time() - start))set_figsize()plt.plot(np.linspace(0, num_epochs, len(ls)), ls)plt.xlabel('epoch')plt.ylabel('loss')plt.show()features,labels=d2l.get_data_ch7()
#使用更大的学习率来训练模型
d2l.train_ch7(adagrad,init_adagrad_states(),{'lr':0.1},features,labels)
output:
loss: 0.243252, 0.052886 sec per epoch
1.4 简洁实现
通过名称为 Adagrad
的优化器⽅法,我们便可使⽤PyTorch
提供的AdaGrad
算法来训练模型。
# 本函数与原书不同的是这里第一个参数优化器函数而不是优化器的名字
# 例如: optimizer_fn=torch.optim.SGD, optimizer_hyperparams={"lr": 0.05}
def train_pytorch_ch7(optimizer_fn, optimizer_hyperparams, features, labels,batch_size=10, num_epochs=2):# 初始化模型net = nn.Sequential(nn.Linear(features.shape[-1], 1))loss = nn.MSELoss()optimizer = optimizer_fn(net.parameters(), **optimizer_hyperparams)def eval_loss():return loss(net(features).view(-1), labels).item() / 2ls = [eval_loss()]data_iter = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(features, labels), batch_size, shuffle=True)for _ in range(num_epochs):start = time.time()for batch_i, (X, y) in enumerate(data_iter):# 除以2是为了和train_ch7保持一致, 因为squared_loss中除了2l = loss(net(X).view(-1), y) / 2 optimizer.zero_grad()l.backward()optimizer.step()if (batch_i + 1) * batch_size % 100 == 0:ls.append(eval_loss())# 打印结果和作图print('loss: %f, %f sec per epoch' % (ls[-1], time.time() - start))set_figsize()plt.plot(np.linspace(0, num_epochs, len(ls)), ls)plt.xlabel('epoch')plt.ylabel('loss')plt.show()d2l.train_pytorch_ch7(torch.optim.Adagrad, {'lr': 0.1}, features,labels)
output:
loss: 0.243147, 0.040675 sec per epoch 1
1.4 小结
AdaGrad
算法在迭代过程中不断调整学习率,并让⽬标函数⾃变量中每个元素都分别拥有⾃⼰
的学习率。- 使⽤
AdaGrad
算法时,⾃变量中每个元素的学习率在迭代过程中⼀直在降低(或不变)
2.Rmsprop算法
AdaGrad
算法中提到,因为调整学习率时分⺟上的变量 ⼀直在累加按元素平⽅的⼩批量随机梯度,所以⽬标函数⾃变量每个元素的学习率在迭代过程中⼀直在降低(或不变)。因此,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad
算法在迭代后期由于学习率过⼩,可能较难找到⼀个有⽤的解。为了解决这⼀问题,RMSProp
算法对AdaGrad
算法做了⼀点⼩⼩的修改。
2.1 算法
#Rmsprop算法
import math
import torch
import sys
sys.path.append("..")
import d2lzh_pytorch as d2l
def rmsprop_2d(x1, x2, s1, s2):g1, g2, eps = 0.2 * x1, 4 * x2, 1e-6s1 = gamma * s1 + (1 - gamma) * g1 ** 2s2 = gamma * s2 + (1 - gamma) * g2 ** 2x1 -= eta / math.sqrt(s1 + eps) * g1x2 -= eta / math.sqrt(s2 + eps) * g2return x1, x2, s1, s2
def f_2d(x1, x2):return 0.1 * x1 ** 2 + 2 * x2 ** 2eta, gamma = 0.4, 0.9
d2l.show_trace_2d(f_2d, d2l.train_2d(rmsprop_2d))
输出:
epoch 20, x1 -0.010599, x2 0.000000
2.2 从零开始实现
接下来按照RMSProp
算法中的公式实现该算法。
features, labels = d2l.get_data_ch7()
def init_rmsprop_states():s_w = torch.zeros((features.shape[1], 1), dtype=torch.float32)s_b = torch.zeros(1, dtype=torch.float32)return (s_w, s_b)
def rmsprop(params, states, hyperparams):gamma, eps = hyperparams['gamma'], 1e-6for p, s in zip(params, states):s.data = gamma * s.data + (1 - gamma) * (p.grad.data)**2p.data -= hyperparams['lr'] * p.grad.data / torch.sqrt(s + eps)
d2l.train_ch7(rmsprop, init_rmsprop_states(), {'lr': 0.01, 'gamma':0.9},features, labels)
output:
loss: 0.243452, 0.049984 sec per epoch 1
2.3 简洁实现
通过名称为 RMSprop
的优化器⽅法,我们便可使⽤PyTorch
提供的RMSProp
算法来训练模型。注意,超参数 通过 alpha
指定。
#简洁实现:
d2l.train_pytorch_ch7(torch.optim.RMSprop, {'lr': 0.01, 'alpha':0.9},features, labels)
output:
loss: 0.244027, 0.057885 sec per epoch
2.4 小结
RMSProp
算法和AdaGrad
算法的不同在于,RMSProp
算法使⽤了⼩批量随机梯度按元素平⽅的指数加权移动平均来调整学习率。
3.AdaDelta算法
除了RMSProp
算法以外,另⼀个常⽤优化算法AdaDelta
算法也针对AdaGrad
算法在迭代后期可能较难找到有⽤解的问题做了改进。有意思的是,AdaDelta
算法没有学习率这⼀超参数。
3.1 算法
3.2 从零开始实现
##AdaDelta算法
import torch
import sys
sys.path.append("..")
import d2lzh_pytorch as d2lfeatures,labels=d2l.get_data_ch7()def init_adadelta_states():s_w,s_b=torch.zeros((features.shape[1],1),dtype=torch.float32),torch.zeros(1,dtype=torch.float32)delta_w,delta_b=torch.zeros((features.shape[1],1),dtype=torch.float32),torch.zeros(1,dtype=torch.float32)return ((s_w,delta_w),(s_b,delta_b))def adadelta(params,states,hyperparams):rho,eps=hyperparams['rho'],1e-5for p,(s,delta) in zip(params,states):s[:]=rho*s+(1-rho)*(p.grad.data**2)g=p.grad.data*torch.sqrt((delta+eps)/(s+eps))p.data-=gdelta[:]=rho*delta+(1-rho)*g*g#使用超参数p=0.9来训练模型
d2l.train_ch7(adadelta,init_adadelta_states(),{'rho':0.9},features,labels)
output:
loss: 0.242700, 0.066821 sec per epoch
3.3 简洁实现
通过名称为 Adadelta
的优化器⽅法,我们便可使⽤PyTorch
提供的AdaDelta
算法。它的超参数可以通过 rho
来指定。
#简洁实现
d2l.train_pytorch_ch7(torch.optim.Adadelta,{'rho':0.9},features,labels)
输出:
loss: 0.273120, 0.062369 sec per epoch
3.4 小结
AdaDelta
算法没有学习率超参数,它通过使⽤有关⾃变量更新量平⽅的指数加权移动平均的项来替代RMSProp
算法中的学习率。
4.Adam算法
Adam
算法在RMSProp
算法基础上对⼩批量随机梯度也做了指数加权移动平均。下⾯我们来介绍这个算法。- 所以
Adam
算法可以看作是RMSProp
算法与动量法的组合
4.1 算法
4.2 从零开始实现
按照Adam
算法中的公式实现该算法,其中时间步t通过hyperparams
参数传入adam
函数。
#Adam算法从零开始实现
import torch
import sys
sys.path.append("..")
import d2lzh_pytorch as d2lfeatures,labels=d2l.get_data_ch7()def init_adam_states():v_w,v_b=torch.zeros((features.shape[1],1),dtype=torch.float32),torch.zeros(1,dtype=torch.float32)s_w,s_b=torch.zeros((features.shape[1],1),dtype=torch.float32),torch.zeros(1,dtype=torch.float32)return ((v_w,s_w),(v_b,s_b))
def adam(params,states,hyperparams):beta1,beta2,eps=0.9,0.999,1e-6for p,(v,s) in zip(params,states):v[:]=beta1*v+(1-beta1)*p.grad.datas[:]=beta2*s+(1-beta2)*p.grad.data**2v_bias_corr=v/(1-beta1**hyperparams['t'])s_bias_corr=s/(1-beta2**hyperparams['t'])p.data-=hyperparams['lr']*v_bias_corr/(torch.sqrt(s_bias_corr)+eps)hyperparams['t']+=1#使用学习率为0.01的Adam算法来训练模型
d2l.train_ch7(adam,init_adam_states(),{'lr':0.01,'t':1},features,labels)
output:
loss: 0.244865, 0.069813 sec per epoch
4.3 简洁实现
通过名称为“adam”的 Trainer
实例,我们便可使⽤Gluon提供的Adam算法。
#简洁实现:
d2l.train_pytorch_ch7(torch.optim.Adam,{'lr':0.01},features,labels)
output:
loss: 0.242826, 0.065362 sec per epoch
4.4 小结
- Adam算法在RMSProp算法的基础上对⼩批量随机梯度也做了指数加权移动平均。
- Adam算法使⽤了偏差修正。
Pytorch总结十五之优化算法:AdaGrad、RMSProp、AdaDelta、Adam算法详解相关推荐
- [Python人工智能] 十五.无监督学习Autoencoder原理及聚类可视化案例详解
从本专栏开始,作者正式研究Python深度学习.神经网络及人工智能相关知识.前一篇文章详细讲解了循环神经网络LSTM RNN如何实现回归预测,通过sin曲线拟合实现如下图所示效果.本篇文章将分享无监督 ...
- PostgreSQL:十五. 性能优化
十五. 性能优化 优化简介: PostgreSQL优化一方面是找出系统的瓶颈,提高PostgreSQL数据库整体的性能: 另一方面,需要合理的结构设计和参数调整,以提高用户操作响应的速度: 同时还要尽 ...
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/28261997 作者:毛星云(浅墨) ...
- 【OpenCV新手教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/28261997 作者:毛星云(浅墨) ...
- [Python图像识别] 五十.Keras构建AlexNet和CNN实现自定义数据集分类详解
该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...
- [Python从零到壹] 三十六.图像处理基础篇之图像算术与逻辑运算详解
欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...
- 即时通讯音视频开发(十):实时语音通讯的回音消除技术详解
前言 即时通讯应用中的实时音视频技术,几乎是IM开发中的最后一道高墙.原因在于:实时音视频技术 = 音视频处理技术 + 网络传输技术 的横向技术应用集合体,而公共互联网不是为了实时通信设计的.有关实时 ...
- EM算法(Expectation Maximization Algorithm)详解
EM算法(Expectation Maximization Algorithm)详解 主要内容 EM算法简介 预备知识 极大似然估计 Jensen不等式 EM算法详解 问题描述 EM算法推导 EM ...
- SAP UI5 初学者教程之二十六 - OData 服务配合 Mock 服务器的使用步骤详解试读版
一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 初学者教程之一:Hello World SAP UI5 初学者教程之二:SAP UI5 ...
- 蓝桥杯 试题 算法训练 无聊的逗 C++ 详解
题目: 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的 ...
最新文章
- HashMap和LinkedHashMap的区别
- 数据库视图的概念和相关操作合集
- 域名系统DNS、文件传送协议FTP、动态主机配置协议DHCP、远程登录协议TELNET、电子邮件协议(SMTP/POP3/IMAP)、常用端口
- c++中 结构体和类的区别
- Linux底层开发之四书五经
- pat 乙级 1030 完美数列(C++)
- nmap入门之主机发现
- python -pymysql的操作
- 吞吐性能翻倍!搭载了第三代Tensor Core的A100是怎么做到的?
- 随机过程中的功率谱密度
- linux系统安装本地r包,linux环境下安装R包DESeq2的报错以及解决方法
- 360手机卫士大数据驱动犯罪打击 配合警方破案成果显著
- TreeMap、HashMap、LinkedHashMap的区别
- Python基础-序列化(json/pickle)
- C++ 10进制字符串转10进制 10进制字符串转换
- 【预测模型】基于蝙蝠算法改进SVM实现预测matlab源码
- FZU 2037 Maximum Value Problem【递推】
- 【应用统计学】总体均值的假设检验
- 移动终端开发详解总结(二)(kotlin版)| CSDN创作打卡
- 解除操作系统宽带限制