pytorch优化器:管理并更新模型中可学习参数的值,使模型输出更接近标签。
梯度下降策略
导数:导数在指定坐标轴上的变化率
方向导数:指定方向上的变化率
梯度:方向导数取得最大的方向,一个向量,模长为方向导数的长度
优化器
def __init__(self, params, defaults):
torch._C._log_api_usage_once("python.optimizer")
self.defaults = defaults
#: {'lr': 0.01, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}
if isinstance(params, torch.Tensor):
raise TypeError("params argument given to the optimizer should be "
"an iterable of Tensors or dicts, but got " +
torch.typename(params))
self.state = defaultdict(dict)
self.param_groups = [] #list
param_groups = list(params)
if len(param_groups) == 0:
raise ValueError("optimizer got an empty parameter list")
if not isinstance(param_groups[0], dict):
param_groups = [{'params': param_groups}]
for param_group in param_groups:
self.add_param_group(param_group) #添加参数![]
基本属性
default:优化器的超参数
state:参数的缓存
params_groups:管理的参数组,list类型,每一个元素是一个字典,‘params’:'values'
_step_count:记录更新的次数
'''
1.优化器的作用是管理并更新参数组,请构建一个SGD优化器,通过add_param_group方法添加三组参数,
三组参数的学习率分别为 0.01, 0.02, 0.03, momentum分别为0.9, 0.8, 0.7,构建好之后,
并打印优化器中的param_groups属性中的每一个元素的key和value(提示:param_groups是list,其每一个元素是一个字典)
'''
flag = 0
# flag = 1
if flag:
lr_list = [0.01, 0.02, 0.03]
momentum_list = [0.9, 0.8, 0.7]
x = torch.tensor([2.], requires_grad=True)
optimizer = optim.SGD([x],lr=0.01,momentum=0.9)
#构造一个SGD优化器
for i,lr in enumerate(lr_list):
w2 = torch.randn((1), requires_grad=True)
para_dic = {'params':w2, 'lr':lr, 'momentum':momentum_list[i]}
optimizer.add_param_group(para_dic)
for i,para in enumerate(optimizer.param_groups):
print("optimizer.param_groups {} is\n{}".format(i,para))
基本方法
1.zero_grad():清空所有管理参数的梯度,pytorch不会自动清零梯度,在进行求梯度之前就要清零
2.step():执行一步更新,有很多方法,动量法什么的
3.add_param_group():添加参数组到优化器中,参数可以分组,对不同的参数组,可以有不同的权值、学习率
4.state_dict():获取优化器当前状态信息字典,也保存
5.load_state_dict():加载状态信息字典
state_dict before step:
{'state': {}, 'param_groups': [{'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'params': [2187292089544]}]}
state_dict after step:
{'state': {2187292089544: {'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': [2187292089544]}]}
#2187292089544 就是参数的地址,这样保存了可以用于下次训练
学习率
梯度下降:
学习率控制更新的步伐
Momentum动量
结合当前梯度与上次更新信息,用于当前更新(沿着正确的方向,更新速度越来越快)
指数加权平均:
每一步将两个梯度方向做一个合并(历史梯度和当前梯度),距离当前时刻越远,对当前值的影响越小,权重越小。
值越大,记忆时间越长,就是距离当前越远的点的影响也能保持下来:
一般选择为0.9,就是关注10个点的数据,
梯度下降:
pytorch中的动量算法:
可见,在的作用下,距离当前点越远的梯度信息对当前作用越小
带有动量的出现震荡现象是因为梯度大,在取得最小值的情况下收到之前动量信息的影响出现反弹的情况。
optim.SGD 随机梯度下降
批量梯度下降,每一次计算都要将样本中的所有信息进行批量计算;
随机梯度下降,每次迭代随机选取一个样本来对参数进行更新,方向具有不确定性,避免了陷入局部最优
import torch.optim as optim
optimizer = optim.SGD([x], lr=lr, momentum=momentum)
'''
参数:momentum:动量大小一般选择0.9,
weight_decay:L2正则化系数
nesterov:是否采用NAG,默认false
对于90%的模型都能使用
'''
for iter in range(iteration)
y = func(x)
y.backward()
optimizer.step() #参数优化
optimizer.zero_grad()
# 每次迭代完,梯度清零
optim.Adagrad 自适应梯度下降
class torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)
实现Adagrad优化方法(Adaptive Gradient),Adagrad是一种自适应优化方法,是自适应的为各个参数分配不同的学习率。这个学习率的变化,会受到梯度的大小和迭代次数的影响。梯度越大,学习率越小;梯度越小,学习率越大。缺点是训练后期,学习率过小,因为Adagrad累加之前所有的梯度平方作为分母。
optim.RMSprop 均方根(root meam square)
class torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)
RMSprop优化方法(Hinton提出),RMS是均方根(root meam square)的意思。RMSprop是对Adagrad的一种改进。RMSprop采用均方根作为分母,可缓解Adagrad学习率下降较快的问题。并且引入均方根,可以减少摆动(原理同自适应,抑制大的,增长小的)。
optim.Adam(AMSGrad)
class torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
使用梯度一阶矩(均值)和二阶矩(方差)
实现Adam(Adaptive Moment Estimation))优化方法。Adam是一种自适应学习率的优化方法,Adam利用梯度的一阶矩估计和二阶矩估计动态的调整学习率。Adam结合了Momentum和RMSprop,并进行了偏差修正。