pytorch学习(7)——神经网络优化器torch.optim

1 optim 优化器

PyTorch神经网络优化器(optimizer)通过调整神经网络的参数(weight和bias)来最小化损失函数(Loss)。

学习链接:

https://pytorch.org/docs/stable/optim.html

1.1 优化器基类

使用时必须构造一个优化器对象,它将保存当前状态,并将根据计算的梯度(grad)更新参数。

调用优化器的step方法。

CLASS torch.optim.Optimizer(params, defaults)

  • Optimizer - 优化器的优化算法。
  • params (iterable) -- torch的迭代器。张量s或dict s,指定应该优化什么张量。
  • defaults -- (dict): 包含优化选项默认值的字典(在参数组没有指定优化选项时使用)。每个Optimizer算法都有其独特的设置字典。
算法(Optimizer) 说明
Adadelta 采用Adadelta算法。
Adagrad 采用Adagrad算法。
Adam 采用Adam算法。
AdamW 采用AdamW算法。
SparseAdam 采用适合稀疏张量的Adam算法的惰性版本。
Adamax 采用Adamax算法(Adam基于无穷范数的变种)。
ASGD 采用平均随机梯度下降。
LBFGS 采用L-BFGS算法,深受minFunc的启发。
NAdam 采用NAdam 算法。
RAdam 采用RAdam 算法。
RMSprop 采用RMSprop 算法。
Rprop 采用有弹性的反向传播算法。
SGD 采用随机梯度下降算法。

1.1.1 SGD 随机梯度下降算法

CLASS torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False, *, maximize=False, foreach=None, differentiable=False)

  • params (iterable) -- iterable参数优化或字典定义参数组。
  • lr (float) -- 学习率,需要用户输入。
  • momentum (float, optional) -- 动量系数(默认值为0)。
  • weight_decay (float, optional) -- 权重衰减(L2惩罚) (默认值为0)
  • dampening (float, optional) -- 动量阻尼(默认值为0)。
  • nesterov (bool, optional) -- 使能Nesterov动量(默认值为False)。
    【Nesterov动量(Nesterov Momentum)是一种基于动量法的优化算法,用于加速神经网络的训练过程。它在随机梯度下降(SGD)的基础上进行改进,通过考虑参数更新前的动量信息来调整参数更新的方向。】
  • maximize (bool, optional) -- 根据目标最大化参数,而不是最小化参数(默认值为False)。
  • foreach (bool, optional) -- 是否使用foreach优化器的实现。如果用户未指定(foreach为None),我们将尝试在CUDA上的for循环实现上使用foreach,因为CUDA通常性能更高(默认值:None)。
  • differentiable (bool, optional) -- 是否在训练中的优化器步骤中发生autograd。否则,step()函数在torch.no_grad()上下文中运行。设置为True会影响性能,所以如果你不打算通过这个实例运行autograd,请保留False(默认值为False)。

学习速率(lr)的取值,如果太大,则模型很不稳定;如果太小,学习速度非常缓慢。因此一般先设置较大的学习速率,然后降低学习速率。

python代码如下:

python 复制代码
import torchvision
import torch
from torch import nn, optim
from torch.nn import Linear, Conv2d, MaxPool2d, Flatten, Sequential,CrossEntropyLoss
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10(root="G:\\Anaconda\\pycharm_pytorch\\learning_project\\dataset_CIFAR10",
                                       train=False,
                                       transform=torchvision.transforms.ToTensor(),
                                       download=False)

dataloader = DataLoader(dataset, batch_size=1)

class MYNN(nn.Module):
    def __init__(self):
        super(MYNN, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2, stride=1),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2, stride=1),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2, stride=1),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

loss = CrossEntropyLoss()
mynn = MYNN()
opitm = optim.SGD(mynn.parameters(), lr=0.01)        # 优化器

for data in dataloader:
    imgs, targets = data
    outputs = mynn(imgs)
    result_loss = loss(outputs, targets)
    # print(outputs)          # 神经网络输出
    # print(targets)          # 目标
    # print(result_loss)      # 损失函数-交叉熵计算结果

    opitm.zero_grad()       # 梯度清零,设置断点
    result_loss.backward()  # 反向传播,求出每个节点的梯度,设置断点
    opitm.step()            # 对神经网络模型的参数进行调优,设置断点

设置断点,进入程序Debug:

(1)不断运行程序,能够观察到卷积层0的bias梯度变化:mynn -> Protected Attributes -> _modules -> 'model1' -> Protected Attributes -> _modules -> '0' -> bias-> grad

(2)能观察到卷积层0的weight梯度变化:mynn -> Protected Attributes -> _modules -> 'model1' -> Protected Attributes -> _modules -> '0' -> weight -> grad

(3)能观察到bias的变化:mynn -> Protected Attributes -> _modules -> 'model1' -> Protected Attributes -> _modules -> '0' -> bias-> data

(4)能观察到weight的变化:mynn -> Protected Attributes -> _modules -> 'model1' -> Protected Attributes -> _modules -> '0' -> weight-> data

(5)结论:运行opitm.zero_grad()后,清空weight和bias的梯度grad;运行result_loss.backward()后,计算得到新的weight和bias的梯度grad;运行opitm.step()后,调整weight和bias的值。

1.1.2 优化器多次循环

修改以上python代码,增加多次循环,观察总体损失值改变。

python 复制代码
import torchvision
import torch
from torch import nn, optim
from torch.nn import Linear, Conv2d, MaxPool2d, Flatten, Sequential,CrossEntropyLoss
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10(root="G:\\Anaconda\\pycharm_pytorch\\learning_project\\dataset_CIFAR10",
                                       train=False,
                                       transform=torchvision.transforms.ToTensor(),
                                       download=False)

dataloader = DataLoader(dataset, batch_size=1)

class MYNN(nn.Module):
    def __init__(self):
        super(MYNN, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2, stride=1),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2, stride=1),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2, stride=1),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

loss = CrossEntropyLoss()
mynn = MYNN()
opitm = optim.SGD(mynn.parameters(), lr=0.01)        # 优化器

for epoch in range(20):
    running_loss = 0.0
    for data in dataloader:
        imgs, targets = data
        outputs = mynn(imgs)
        result_loss = loss(outputs, targets)
        # print(outputs)          # 神经网络输出
        # print(targets)          # 目标
        # print(result_loss)      # 损失函数-交叉熵计算结果
        opitm.zero_grad()       # 梯度清零
        result_loss.backward()  # 反向传播,求出每个节点的梯度
        opitm.step()            # 对神经网络模型的参数进行调优

        running_loss = running_loss + result_loss#.data

    print(running_loss)

运行结果:

c 复制代码
tensor(18746.2012, grad_fn=<AddBackward0>)
tensor(16136.0107, grad_fn=<AddBackward0>)
tensor(15499.3203, grad_fn=<AddBackward0>)
tensor(nan, grad_fn=<AddBackward0>)
tensor(nan, grad_fn=<AddBackward0>)
tensor(nan, grad_fn=<AddBackward0>)

可以发现running_loss在一开始不断降低,但是以下的nan暂时不知道是什么原因。

相关推荐
Red Red4 小时前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全
Natural_yz6 小时前
大数据学习17之Spark-Core
大数据·学习·spark
qq_172805596 小时前
RUST学习教程-安装教程
开发语言·学习·rust·安装
一只小小汤圆6 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
虾球xz6 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
LateBloomer7777 小时前
FreeRTOS——信号量
笔记·stm32·学习·freertos
legend_jz7 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
Komorebi.py7 小时前
【Linux】-学习笔记04
linux·笔记·学习
weiabc7 小时前
学习electron
javascript·学习·electron
YRr YRr8 小时前
深度学习:神经网络中的损失函数的使用
人工智能·深度学习·神经网络