PyTorch入门3

文章介绍了如何在PyTorch中使用Sequential简化神经网络结构,以及讲解了损失函数(L1Loss,MSELoss,CrossEntropyLoss)的用法和反向传播的概念。此外,还讨论了SGD优化器的使用,并展示了在CIFAR10数据集上的应用。文章最后提到了预训练模型VGG的使用和修改,以及模型的保存与加载方法。
摘要由CSDN通过智能技术生成

目录

搭建小实战和Sequential的使用

损失函数与反向传播

优化器

现有网络模型的使用及修改

网络模型的保存与读取


搭建小实战和Sequential的使用

以下面的神经网络为例,进行一个简单的搭建实战,并说明sequential的用法。

未使用sequential时神经网络的代码如下:

import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear


class Ceshi(nn.Module):
    def __init__(self):
        super(Ceshi, self).__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2)
        self.maxpool1 = MaxPool2d(2)
        self.conv2 = Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2)
        self.maxpool2 = MaxPool2d(2)
        self.conv3 = Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2)
        self.maxpool3 = MaxPool2d(2)
        self.flatten = Flatten()
        self.linear1 = Linear(1024, 64)
        self.linear2 = Linear(64, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)
        x = self.conv3(x)
        x = self.maxpool3(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.linear2(x)
        return x

ceshi = Ceshi()
# 在实际中,可以创建一个输入去检查网络正确性,比如下面创建一个input
# torch提供了一些比较简单的方法去创建数据。我们可以指定我们想要创建的数据的形状,其中的数可以指定为都是0、都是1或者是随机数
# 下面创造一个数据作为输入,其中的数都指定为1,通过这个输入去检查网络的正确性
input = torch.ones((64, 3, 32, 32))
output = ceshi(input)
print(output.shape)

使用sequential后神经网络的代码如下,相比未使用时代码简洁了很多:

import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential

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

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

ceshi = Ceshi()
# 在实际中,可以创建一个输入去检查网络正确性,比如下面创建一个input
# torch提供了一些比较简单的方法去创建数据。我们可以指定我们想要创建的数据的形状,其中的数可以指定为都是0、都是1或者是随机数
# 下面创造一个数据作为输入,其中的数都指定为1,通过这个输入去检查网络的正确性
input = torch.ones((64, 3, 32, 32))
output = ceshi(input)
print(output.shape)
# 输出结果:torch.Size([64, 10])

使用tensorboard工具对上面的ceshi网络进行显示:

writer = SummaryWriter("logs")
writer.add_graph(ceshi, input)
writer.close()

把ceshi的方框点开可以进一步查看网络架构:

进一步打开这些层:

损失函数与反向传播

Loss Functions:

    1. 计算实际输出和目标之间的差距
    2. 为我们更新输出提供一定的依据(反向传播)

下面介绍三个Loss Function:

① nn.L1Loss

——Creates a criterion that measures the mean absolute error (MAE) between each element in the input x and target y.

 ② nn.MSELoss

——Creates a criterion that measures the mean squared error (squared L2 norm) between each element in the input x and target y.

③ nn.CrossEntropyLoss

——This criterion computes the cross entropy loss between input logits and target.

代码实例如下:

import torch
from torch import nn

inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)

inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))

loss1 = nn.L1Loss()
loss_L1 = loss1(inputs, targets)
print("loss_L1 =", loss_L1)

loss2 = nn.MSELoss()
Loss_MSE = loss2(inputs, targets)
print("Loss_MSE =", Loss_MSE)

x = torch.tensor([0.1, 0.2, 0.3])
y = torch.tensor([1])
x = torch.reshape(x, (1, 3))
loss3 = nn.CrossEntropyLoss()
Loss_CrossEntropy = loss3(x, y)
print("Loss_CrossEntropy =", Loss_CrossEntropy)

 下面使用小实战搭建的网络结构+CIFAR10数据集进行CrossEntropyLoss的计算:

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

testset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(testset, batch_size=32)

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

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

ceshi = Ceshi()
loss = nn.CrossEntropyLoss()
for data in dataloader:
    imgs, targets = data
    outputs = ceshi(imgs)
    Loss_CrossEntropy = loss(outputs, targets)
    Loss_CrossEntropy.backward()
    print("Loss_CrossEntropy =", Loss_CrossEntropy)

断点打在33行,进行Debugger,可看到部分参数如下:

继续往下运行一步,用backward去做一个反向传播,计算出各个节点的参数,grad参数如下图,有关梯度和梯度下降法可参见李宏毅老师的课程:

优化器

各类优化器原理在李宏毅老师机器学习的课程中也有详细讲述,下面代码以SGD为例:

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

testset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(testset, batch_size=32)

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

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

ceshi = Ceshi()
loss = nn.CrossEntropyLoss()
optim = torch.optim.SGD(ceshi.parameters(), lr=0.001)
for epoch in range(20):
    running_loss = 0.0
    for data in dataloader:
        imgs, targets = data
        outputs = ceshi(imgs)
        Loss_CrossEntropy = loss(outputs, targets)
        optim.zero_grad()
        Loss_CrossEntropy.backward()
        optim.step()
        # print("Loss_CrossEntropy =", Loss_CrossEntropy)
        running_loss += Loss_CrossEntropy
    print("running_loss =", running_loss)

现有网络模型的使用及修改

以torchvision Classification中的VGG为例:

VGG有在ImageNet上预训练的版本和没有经过预训练的版本:

代码实例:

import torchvision

# 没有预训练
from torch import nn

vgg16_false = torchvision.models.vgg16(pretrained=False)
# 有预训练
vgg16_true = torchvision.models.vgg16(pretrained=True)
print(vgg16_true)

# vgg最后的out_features是1000,ImageNet数据集就有1000个类别
# 以CIFAR10为例,对vgg网络进行增加module和修改module的操作
# CIFAR10有10个类别,最后的out_features需要变成10
# 增加module操作如下:
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
# 不加.classifier就是把linear的module加在classifier的外面
# vgg16_true.add_module('add_linear', nn.linear(1000, 10))
print(vgg16_true)

# 修改module操作如下
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)

VGG网络原始的classifier如下图:

增加Linear module后的classifier如下图:

修改module后的classifier如下图:

网络模型的保存与读取

save模块代码实例:

import torch
import torchvision.models

vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1 模型结构+模型参数
torch.save(vgg16, "vgg_method1.pth")

# 保存方式2 模型参数(官方推荐)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")

 load模块代码实例:

import torch

# 加载通过方式1保存的模型
import torchvision

model = torch.load("vgg_method1.pth")
print(model)

# 加载通过方式2保存的模型
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
print(vgg16)

输出结果是两个vgg网络的模型。

注:如果保存的是自己写的网络模型,那么在加载模型的py文件中,需要import保存模型结构的那个文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值