pytorch学习记录三 【Sequential / 损失函数 / 反向传播 / 优化器 / 模型修改及使用 / 模型保存与加载】

1.神经网络:搭建小实战和Sequential的使用

在这里插入图片描述
以CIFAR10 model为例
在这里插入图片描述

在这里插入图片描述

import torch
import torchvision
from tensorboardX import SummaryWriter
from torch import nn
from torch.nn import ReLU, Sigmoid, Linear, Conv2d, MaxPool2d, Flatten
from torch.utils.data import DataLoader


class test_cifar(nn.Module):
    def __init__(self) -> None:
        super(test_cifar, self).__init__()
        self.conv1 = Conv2d(3, 32, 5, padding=2)
        self.maxpool1 = MaxPool2d(2)
        self.conv2 = Conv2d(32, 32, 5, padding=2)
        self.maxpool2 = MaxPool2d(2)
        self.conv3 = Conv2d(32, 64, 5, 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

test = test_cifar()
print(test)
input = torch.ones((64, 3, 32, 32))  # 生成一个全是1的测试数据
output = test(input)
print(output.shape)  # torch.Size([64, 10]) 说明网络搭建应该没问题

如果网络中间有地方错误,可以通过这部分代码进行测试

test = test_cifar()
print(test)
input = torch.ones((64, 3, 32, 32))  # 生成一个全是1的测试数据
output = test(input)
print(output.shape)  # torch.Size([64, 10]) 说明网络搭建应该没问题

假如说,我把
self.linear1 = Linear(1024, 64)中的1024改成了10240
那么就会报错
在这里插入图片描述
改成Sequential代码就会变得非常简洁

import torch
import torchvision
from tensorboardX import SummaryWriter
from torch import nn
from torch.nn import ReLU, Sigmoid, Linear, Conv2d, MaxPool2d, Flatten, Sequential
from torch.utils.data import DataLoader


class test_cifar(nn.Module):
    def __init__(self) -> None:
        super(test_cifar, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 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.model1(x)
        return x

test = test_cifar()
print(test)
input = torch.ones((64, 3, 32, 32))  # 生成一个全是1的测试数据
output = test(input)
print(output.shape)  # torch.Size([64, 10]) 说明网络搭建应该没问题

用tensorboardX展示
(这里我报错!!!!!不知道为什么!!!看视频效果很牛逼,求解)
在这里插入图片描述

# 这个代码报错,没找到问题所在
import torch
import torchvision
from tensorboardX import SummaryWriter
from torch import nn
from torch.nn import ReLU, Sigmoid, Linear, Conv2d, MaxPool2d, Flatten, Sequential
from torch.utils.data import DataLoader


class test_cifar(nn.Module):
    def __init__(self) -> None:
        super(test_cifar, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 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):
        return x

test_model = test_cifar()
print(test_model)
input = torch.ones((64, 3, 32, 32))  # 生成一个全是1的测试数据
output = test_model(input)
print(output.shape)  # torch.Size([64, 10]) 说明网络搭建应该没问题

writer = SummaryWriter("../logs_seq")
writer.add_graph(test_model, input)
writer.close()

2.损失函数

在这里插入图片描述
以L1loss为例

import torch
from torch.nn import  L1Loss

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))

loss = L1Loss()
result = loss(inputs, targets)  # tensor(0.6667)

交叉熵
在这里插入图片描述

import torch
from torch.nn import  L1Loss
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))

# L1Loss
loss = L1Loss()
result = loss(inputs, targets)  # tensor(0.6667)

# MSELoss
loss_mse = nn.MSELoss()
result_mse = loss_mse(inputs, targets)  # tensor(1.3333)

# CrossEntropyLoss
x = torch.tensor([0.1, 0.2, 0.3])
y = torch.tensor([1])
x = torch.reshape(x, (1, 3))
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(x, y)
print(result_cross)  # tensor(1.1019)

3.反向传播

利用cifar10网络进行loss和反向传播的测试

import torch
import torchvision
from tensorboardX import SummaryWriter
from torch import nn
from torch.nn import ReLU, Sigmoid, Linear, Conv2d, MaxPool2d, Flatten, Sequential
from torch.utils.data import DataLoader


class test_cifar(nn.Module):
    def __init__(self) -> None:
        super(test_cifar, self).__init__()

        self.model1 = Sequential(
            Conv2d(3, 32, 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.model1(x)
        return x


dataset = torchvision.datasets.CIFAR10("../datasets", train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=1)
test_model = test_cifar()
loss_cross = nn.CrossEntropyLoss()

for data in dataloader:
    imgs, targets = data
    outputs = test_model(imgs)
    # 看outputs和targets是什么样子,看需要选择什么损失函数
    print(outputs)  # tensor([[-0.0997, -0.1220, -0.1413,  0.0602, -0.1044,  0.1636, -0.0469, -0.1157, 0.0060, -0.1186]], grad_fn=<AddmmBackward0>)
    print(targets)  # tensor([3])

    result_loss = loss_cross(outputs, targets)  # tensor(2.3130, grad_fn=<NllLossBackward0>)
    result_loss.backward()
    print("ok")

打断点,进入网络中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意,如果没有result_loss.backward()这条语句的话,梯度是不会更新的。

4.优化器

优化器对梯度进行调整

import torch
import torchvision
from tensorboardX import SummaryWriter
from torch import nn
from torch.nn import ReLU, Sigmoid, Linear, Conv2d, MaxPool2d, Flatten, Sequential
from torch.utils.data import DataLoader


class test_cifar(nn.Module):
    def __init__(self) -> None:
        super(test_cifar, self).__init__()

        self.model1 = Sequential(
            Conv2d(3, 32, 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.model1(x)
        return x


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

loss_cross = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(test_model.parameters(), lr=0.01)  # lr:学习速率

for data in dataloader:
    imgs, targets = data
    outputs = test_model(imgs)
    result_loss = loss_cross(outputs, targets)  # tensor(2.3130, grad_fn=<NllLossBackward0>)

    optimizer.zero_grad()  # 优化器调节梯度为0
    result_loss.backward()  
    optimizer.step()  # 对每个参数进行调优

在这里插入图片描述
按那个绿色按钮进入下一步,即运行optimizer.zero_grad() # 优化器调节梯度为0,此时grad=None
再按一次绿色按钮,即运行result_loss.backward(),进行反向传播。此时梯度进行更新。
在这里插入图片描述
再按一次绿色按钮,此时运行optimizer.step() # 对每个参数进行调优,优化器会利用grad梯度对data进行更新。
在这里插入图片描述
加上轮数的代码

import torch
import torchvision
from tensorboardX import SummaryWriter
from torch import nn
from torch.nn import ReLU, Sigmoid, Linear, Conv2d, MaxPool2d, Flatten, Sequential
from torch.utils.data import DataLoader


class test_cifar(nn.Module):
    def __init__(self) -> None:
        super(test_cifar, self).__init__()

        self.model1 = Sequential(
            Conv2d(3, 32, 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.model1(x)
        return x


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

loss_cross = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(test_model.parameters(), lr=0.01)  # lr:学习速率

for epoch in range(20):
    running_loss = 0.0
    for data in dataloader:
        imgs, targets = data
        outputs = test_model(imgs)
        result_loss = loss_cross(outputs, targets)  # tensor(2.3130, grad_fn=<NllLossBackward0>)

        optimizer.zero_grad()  # 优化器调节梯度为0
        result_loss.backward()
        optimizer.step()  # 对每个参数进行调优
        running_loss = result_loss + result_loss
    print(running_loss)

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

用vgg做例子
在这里插入图片描述
需要ImageNet数据集
在这里插入图片描述
在这里插入图片描述
报错了。不管了
————————————————
vgg的模型 其中pretrained为是否预训练

import torchvision

vgg16_false = torchvision.models.vgg16(pretrained=False)  # 网络模型,没有参数 pretrained:是否预训练
vgg16_true = torchvision.models.vgg16(pretrained=True)  # 已经训练好的网络模型
print(vgg16_true)

打印出来:

VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace=True)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

从最后一个线性层可以看出来,输出 out_features=1000,分类1000种。我们想让vgg能够分类10个,在cifar10上用。
在后面加一层

import torchvision
from torch import nn

vgg16_false = torchvision.models.vgg16(pretrained=False)  # 网络模型,没有参数 pretrained:是否预训练
vgg16_true = torchvision.models.vgg16(pretrained=True)  # 已经训练好的网络模型
print(vgg16_true)

vgg16_true.add_module("add_linear", nn.Linear(1000, 10))
print(vgg16_true)

输出:

在这里插入图片描述
如果在classifier后面加一层的话,语句是:

vgg16_true.classifier.add_module("7 add_linear", nn.Linear(1000, 10))

在这里插入图片描述
如果想对某一层修改,例如把7 add_linear修改为输出5

vgg16_true.classifier[7] = nn.Linear(1000, 5)  # 7是下标,下标从0开始

则输出
在这里插入图片描述

6.模型的保存和加载

模型的保存
方法1:保存模型的结构和参数
方法2:把vgg16中的状态保存成字典形式
把两种方法在下面的代码中进行展示

import torchvision
from torch import nn
import torch

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

# 保存方式2  模型参数(官方推荐)  比较小
torch.save(vgg16.state_dict(), "vgg16_method2.pth")  # 把vgg16中的状态保存成字典形式

生成文件,保存模型的结构和参数
在这里插入图片描述

模型的加载
两种方式对应不同的加载方式

import torchvision
from torch import nn
import torch

# 保存方式1——>>加载
model1 = torch.load("vgg16_method1.pth")
print(model1)

# 保存方式2——>>加载
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
print(vgg16)

在pycharm中:在pth所在的文件夹右键点击open in Terminal
再在Terminal中输入dir,可以查看该文件夹下所有文件的信息
在这里插入图片描述
陷阱:
保存时:
在这里插入图片描述
加载时,直接加载会报错:在这里插入图片描述
要把网络结构定义一下才能正常运行在这里插入图片描述
也可以直接从py文件里import过来
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch是一种流行的Python深度学习库,具有强大的张量操作、自动微分以及与Python和NumPy之间的无缝集成等功能。而PyTorch中的Sequential是一种容类型,用于有效地将多个层连接在一起,以构建深度神经网络。在实现序列化神经网络中,我们可以使用PyTorch中的LSTM层来处理时序数据,LSTM作为长短时记忆网络,可以有效地捕捉时间依赖性。 LSTM是一种反向传播神经网络,主要用于序列化数据处理。 它使用RNN的网络结构,增了一个称为内存单元的子组件。 内存单元可以读取和写入身份验证值,以便让网络记住或取消记住之前所看到的数据。此外,LSTM还支持从前向后传递和后向传递,因此它可以处理时间或序列上的前向和后向依赖关系。 LSTM模型中,我们通常需要设置输入维度,隐藏单元数量和LSTM层数。接下来,我们可以在Sequential使用LSTM层来定义LSTM模型。在LSTM层中,定义为input_size,hidden_size,num_layers,batch_first的四个参数。 其中,input_size表示输入序列的维数,hidden_size表示隐藏状态维度,num_layers表示LSTM层数,batch_first表示数据的维度排列顺序,若为True则是batch_size x seq_len x embed_size,否则seq_len x batch_size x embed_size。 在PyTorch中,LSTM层的常见使用方式如下所示: ``` import torch.nn as nn # LSTMModel model class LSTMModel(nn.Module): def __init__(self, input_size, hidden_size, num_layers): super(LSTMModel, self).__init__() self.hidden_size = hidden_size self.num_layers = num_layers # Define LSTM Layer self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) def forward(self, x): # Set initial hidden and cell states h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device) c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device) # Forward propagate LSTM out, _ = self.lstm(x, (h0, c0)) # Decode hidden state of last time step out = out[:, -1, :] return out ``` 在这个模型中,我们首先定义了LSTM层,并在forward函数中实现前向传播,设置了初始状态,并调用LSTM层对输入进行处理。最终,输出最后一个时间戳处的隐藏状态。我们可以按照需要定义其他层,以构建完整的深度神经网络。 综上所述,PyTorch中的Sequential使用LSTM可以被用来构建序列化神经网络,利用LSTM层容参数设置来定义输入序列的维数、隐藏状态维度、LSTM层数、数据的维度排列顺序等诸多参数来方便地进行时间依赖性序列化数据处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值