神经网络——torch.optim优化器的使用

optimizer.step()是大多数优化器支持的简化版本。 一旦使用例如计算梯度,就可以调用该函数。 backward()反向传播。



一、 官方文档

1. 什么是torch.optim?

torch.optim 是一个实现各种优化算法的包。 最常用的方法都已经支持了,接口也足够通用,以后也可以轻松集成更复杂的方法。

2. How to use an optimizer(如何使用优化器)

要使用 torch.optim,必须构造一个优化器对象,该对象将保持当前状态并根据计算的梯度更新参数。

2.1 Constructing it(构建它)

要构造一个优化器,你必须给它一个包含要优化的参数(都应该是变量)的迭代。 然后,您可以指定优化器特定的选项,例如学习率、权重衰减等。

Note:
如果您需要通过 .cuda() 将模型移动到 GPU,请在为其构建优化器之前执行此操作。 .cuda() 之后的模型参数将与调用之前的对象不同。
通常,在构建和使用优化器时,应该确保优化的参数位于一致的位置。

2.2 Per-parameter options(每个参数选项)    

不会,后面补充。

2.3 Taking an optimization step(采取优化步骤)

所有优化器都实现了一个更新参数的 step() 方法。 它可以通过两种方式使用:

第一种是optimizer.step()
这是大多数优化器支持的简化版本。 一旦使用例如计算梯度,就可以调用该函数。 backward()反向传播。

for input, target in dataset:
    optimizer.zero_grad()        #这是将上一步求得每个参数对应的梯度进行清0,以防上一步的梯度造成影响
    output = model(input)      #数据经过神经网络得到一个输出
    loss = loss_fn(output, target)    #计算出losss,得到输出与目标之间的误差
    loss.backward()                  #反向传播,得到每一个要更新的参数的梯度
    optimizer.step()                 #调用optimizer.step,每一个参数都会根据反向传播得到的梯度进行优化


第二种是optimizer.step(closure)
一些优化算法,如 Conjugate Gradient 和 LBFGS 需要多次重新评估函数,因此您必须传入一个允许它们重新计算模型的闭包。 闭包应该清除梯度,计算损失并返回它。

for input, target in dataset:
    def closure():
        optimizer.zero_grad()
        output = model(input)
        loss = loss_fn(output, target)
        loss.backward()
        return loss
    optimizer.step(closure)

二、torch.optim的算法

2.1 torch.optim.Optimizer(params, defaults)

这是优化器的基本结构,每个优化器类都有着两个参数。
 

参数:
params (iterable) – an iterable of torch.Tensor s or dict s. Specifies what Tensors should be optimized.
( 可迭代的 torch.Tensor 或 dict 。 指定应该优化哪些张量。)
defaults – (dict): a dict containing default values of optimization options (used when a parameter group doesn’t specify them).
(包含优化选项默认值的字典(在参数组未指定它们时使用)。)

2.2 Adadelta

torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)

params:参数,需要将模型的参数输入
lr:学习速率,即learning rate

不同的优化器,只有params和lr前面两个参数是一样的,其他的参数是不一样的。

2.3 使用torch.optim.SGD进行学习

代码如下:

import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

#调用CIFAR10数据集
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
#使用dataloader数据迭代器
dataloader = DataLoader(dataset, batch_size=1)

#搭建神经网络,这个Test网络就是CIFAR10数据集的网络
class Test(nn.Module):
    def __init__(self):    #初始化
        super(Test, self).__init__()
        self.seq = Sequential(
            Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self,x):
        x = self.seq(x)
        return x

#创建网络
test = Test()

#使用nn.CrossEntropyLoss
loss_cross = nn.CrossEntropyLoss()
optim = torch.optim.SGD(test.parameters(), lr=0.01)
for data in dataloader:
    imgs, targets = data
    optim.zero_grad()    #上一步求得的参数归零
    output = test(imgs)
    result_loss = loss_cross(output, targets)
    result_loss.backward()
    optim.step()
    print(result_loss)

结点运行一下,一开始grad梯度是没有值的none


运行一次backward,grad梯度值就计算出来了


运行optim.step().会发现grad梯度改变了


运行optim.zero_grad(),grad梯度又清零了


如此往复。让我们的Loss变小。

输入print(result_loss),来查看一下代码运行的结果


在每一个节点上,loss值好像并没有减小,那是因为dataloder的数据在这个神经网络中都只看了一遍,
一般情况下,我们需要对数据进行很多轮的学习,这里才学习了一次
故,可以使用for循环,来进行多轮学习

代码如下:

loss_cross = nn.CrossEntropyLoss()
optim = torch.optim.SGD(test.parameters(), lr=0.01)
for epoch in range(20):                  #epoch就是一轮一轮的意思
    running_loss = 0.0       #为了方便观察,用这个查看每一轮中loss值为多少
    for data in dataloader:
        imgs, targets = data
        optim.zero_grad()     #上一步求得的参数归零
        output = test(imgs)
        result_loss = loss_cross(output, targets)
        result_loss.backward()
        optim.step()
        running_loss = running_loss + result_loss
    print(running_loss)

输出结果:

可以看见,Loss值在变小。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
torch.optim.Adam 和 torch.optim.SGD 是 PyTorch 中两种不同的优化器,它们在优化算法和使用方式上存在一些区别。 1. 优化算法: - Adam(Adaptive Moment Estimation)是一种基于梯度的优化算法,它结合了 AdaGrad 和 RMSProp 的优点。它使用动量和自适应学习率来更新参数,能够更快地收敛,并且对于稀疏梯度和噪声较大的问题有较好的表现。 - SGD(Stochastic Gradient Descent)是一种基本的随机梯度下降算法,每次更新参数时仅使用一个样本或一小批样本的梯度。它通过迭代地更新参数来最小化损失函数,适用于大规模数据集和较简单的模型。 2. 学习率调整: - Adam 使用自适应学习率,每个参数都有自己的学习率,根据梯度的历史信息来自动调整学习率。 - SGD 需要手动设置全局学习率,并且可以通过学习率衰减策略进行调整,如按照固定时间表衰减或根据验证集的性能进行衰减。 3. 参数更新方式: - Adam 通过存储每个参数的历史梯度平方的指数衰减平均来计算自适应学习率,使用动量项来加速参数更新。 - SGD 使用每个参数的梯度和学习率来更新参数,可以选择添加动量项来加速收敛。 选择 Adam 还是 SGD 取决于问题的性质和数据集的规模。在大多数情况下,Adam 通常能够更快地收敛,特别是对于复杂的模型和大规模数据集。然而,在某些情况下,SGD 可能会更好地适应局部最优解,并且具有更低的内存使用量。 需要根据具体问题和实验结果来选择合适的优化器。可以尝试不同的优化器并根据模型性能和训练速度进行比较,以确定最佳选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓亮.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值