优化器(optimizer)本质上是一种算法,用于优化深度学习模型的参数,通过不断更新模型的参数来最小化模型损失。在选择优化器时,需要考虑模型的结构、模型的数据量、模型的目标函数等因素。
BGD是梯度下降法最原始的形式,它的基本思想是在更新参数时使用所有样本来进行更新
公式如下,假设样本总数为N,
BGD得到的是一个全局最优解,但是每迭代一步,都要用到训练集的所有数据,如果样本数巨大大,那上述公式迭代起来则非常耗时,模型训练速度很慢;迭代次数少
# 数据
inputs = ...
# 标签
labels = ...
# 模型
model = ...
# 损失函数
criterion = ...
# 优化器
optimizer = torch.optim.SGD(model.parameters())
# 训练
for i in range(epochs):
# 计算损失
outputs = model(inputs)
loss = criterion(outputs, labels)
# 计算梯度
optimizer.zero_grad()
loss.backward()
# 更新参数
optimizer.step()
SGD的基本思想是,更新参数时使用随机选取的一个样本来进行更新
公式如下,
其中,:模型在第t次迭代时的参数值,:学习率, :损失函数关于模型参数的梯度。
SGD的优点是实现简单、效率高,缺点是收敛速度慢、容易陷入局部最小值;迭代次数多
# 数据
inputs = ...
# 标签
labels = ...
# 模型
model = ...
# 损失函数
criterion = ...
# 优化器
optimizer = torch.optim.SGD(model.parameters())
# 训练
for i in range(epochs):
for input, label in zip(inputs, labels)
# 计算损失
output = model(input)
loss = criterion(output, label)
# 计算梯度
optimizer.zero_grad()
loss.backward()
# 更新参数
optimizer.step()
由BGD和SGD可以看出,它们有各的优缺点,那么能不能在这两种方法的性能之间取得一个折中呢?即,算法的训练过程比较快,而且保证最终参数训练的准确率,而这正是MBGD的初衷。MBGD在每次更新参数时使用b个样本
训练过程较稳定;BGD可以找到局部最优解,不一定是全局最优解;若损失函数为凸函数,则BGD所求解一定为全局最优解
# 数据
inputs = ...
# 标签
labels = ...
# 模型
model = ...
# 损失函数
criterion = ...
# 优化器
optimizer = torch.optim.SGD(model.parameters())
# mini batch大小
b = ...
# 训练
optimizer.zero_grad()
for epoch in range(epochs):
for i, (input, label) in enumerate(zip(inputs, labels))
ni = i + len(inputs) * epoch
# 计算损失
output = model(input)
loss = criterion(output, label)
# 计算梯度
loss.backward()
if ni % b == 0:
# 更新参数
optimizer.step()
optimizer.zero_grad()
Adam是一种近似于随机梯度下降的优化器,它的基本思想是,通过计算模型参数的梯度以及梯度平方的加权平均值(一阶动量和二阶动量),来调整模型的参数
其中,
:模型参数在第t次迭代时的梯度,
和:模型参数在第t次迭代时的一阶动量和二阶动量,
和:超参数(默认是0.9和0.999),
和:和的t次方,
和 :偏差纠正后的一阶和二阶动量(由于m和v的初始值为0,在训练初期可能导致一阶动量和二阶动量偏向于0,因此需要对它们进行偏差修正;在训练初期,修正后的m、v会变大,在训练后期,修正前后的m、v差别不大),
"""
一阶动量及二阶动量初始化
"""
# Exponential moving average of gradient values
state['exp_avg'] = torch.zeros_like(p, memory_format=torch.preserve_format)
# Exponential moving average of squared gradient values
state['exp_avg_sq'] = torch.zeros_like(p, memory_format=torch.preserve_format)
:学习率,
:值为非常小的常数(默认是1e-8,防除0)
Adam计算效率高,收敛速度快;需要调整超参数;能够自适应地调整每个参数的学习率,从而提高模型的收敛速度和泛化能力;
# 数据
inputs = ...
# 标签
labels = ...
# 模型
model = ...
# 定义优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.1, betas=(0.9, 0.999))
# 损失函数
criterion = ...
# 训练模型
for i in range(epochs):
# 前向传播
outputs = model(inputs)
# 计算损失
loss = criterion(outputs, labels)
# 计算梯度
optimizer.zero_grad()
loss.backward()
# 更新参数
optimizer.step()
【参考文章】
Adam优化器(通俗理解)_Longer2048的博客-CSDN博客
http://bbs.xfyun.cn/thread/46940&wd=&eqid=f85ffc5f000f860300000006642b26be