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暂时不知道是什么原因。

相关推荐
DKPT2 小时前
Java桥接模式实现方式与测试方法
java·笔记·学习·设计模式·桥接模式
伍哥的传说4 小时前
React 各颜色转换方法、颜色值换算工具HEX、RGB/RGBA、HSL/HSLA、HSV、CMYK
深度学习·神经网络·react.js
好好研究4 小时前
学习栈和队列的插入和删除操作
数据结构·学习
新中地GIS开发老师5 小时前
新发布:26考研院校和专业大纲
学习·考研·arcgis·大学生·遥感·gis开发·地理信息科学
SH11HF6 小时前
小菜狗的云计算之旅,学习了解rsync+sersync实现数据实时同步(详细操作步骤)
学习·云计算
Frank学习路上6 小时前
【IOS】XCode创建firstapp并运行(成为IOS开发者)
开发语言·学习·ios·cocoa·xcode
Chef_Chen8 小时前
从0开始学习计算机视觉--Day07--神经网络
神经网络·学习·计算机视觉
X_StarX9 小时前
【Unity笔记02】订阅事件-自动开门
笔记·学习·unity·游戏引擎·游戏开发·大学生
MingYue_SSS10 小时前
开关电源抄板学习
经验分享·笔记·嵌入式硬件·学习
是Dream呀10 小时前
基于连接感知的实时困倦分类图神经网络
神经网络·分类·数据挖掘