← 返回文章列表

PyTorch模型构建与训练全解析

1.torch.nn nn.Module的使用 2.卷积操作 无padding填充 pading=1 扩充会使卷积输出跟输入举证s …

1.torch.nn

nn.Module的使用

import torch
from torch import nn

class Ziggy(nn.Module):
    def __init__(self):
        super().__init__()  # 等价于 super(Ziggy, self).__init__()

    def forward(self, input):
        # 注意:input 应为 Tensor;这里支持标量或任意形状张量
        output = input + 1
        return output

# 实例化模型
ziggy = Ziggy()

# 输入一个标量张量(float32)
x = torch.tensor(1.0)
output = ziggy(x)

print("Input:", x)
print("Output:", output)  # → tensor(2.)

2.卷积操作

无padding填充

import torch
import torch.nn.functional as F

input = torch.tensor([[[1, 2, 0, 3, 1],
                       [0, 1, 2, 3, 1],
                       [1, 2, 1, 0, 0],
                       [5, 2, 3, 1, 1],
                       [2, 1, 0, 1, 1]]], dtype=torch.float32)
input = input.reshape(1, 1, 5, 5)

kernel = torch.tensor([[[1, 2, 1],
                        [0, 1, 0],
                        [2, 1, 0]]], dtype=torch.float32)
kernel = kernel.reshape(1, 1, 3, 3)

output = F.conv2d(input, kernel, stride=1)
output2 = F.conv2d(input, kernel, stride=2)

print(output)
print(output2)

pading=1

扩充会使卷积输出跟输入举证shape一样

3.神经网路—卷积层

1)对图片进行卷积操作

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10(root='./dataset', train=False,
                                        transform=torchvision.transforms.ToTensor(),
                                        download=True)
dataloader = DataLoader(dataset, batch_size=64)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

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

tudui = Tudui()
writer = SummaryWriter('p1')
step = 0

for data in dataloader:
    imgs, targets = data
    output = tudui(imgs)
    print(imgs.shape)
    print(output.shape)
    writer.add_images("input", imgs, step)
    writer.add_images("output", output, step)
    step += 1

writer.close()

3.神经网络—最大池化的使用

stride = kernel_size

import torch
from torch import nn
from torch.nn import MaxPool2d

input = torch.tensor([[[1, 2, 0, 3, 1],
                       [0, 1, 2, 3, 1],
                       [1, 2, 1, 0, 0],
                       [5, 2, 3, 1, 1],
                       [2, 1, 0, 1, 1]]])
input = torch.reshape(input, shape=(-1, 1, 5, 5))

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.maxpool = MaxPool2d(kernel_size=3, ceil_mode=True)

    def forward(self, input):
        output = self.maxpool(input)
        return output

tudui = Tudui()
output = tudui(input)
print(output)

1)ceil_mode = True

2)ceil_mode = False

最大池化的操作,池化就是保存图片原本信息的情况下,减少数据量

import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10(root='./dataset', train=False,
                                        transform=torchvision.transforms.ToTensor(),
                                        download=True)
dataloader = DataLoader(dataset, batch_size=64)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.maxpool = MaxPool2d(kernel_size=3, ceil_mode=False)

    def forward(self, input):
        output = self.maxpool(input)
        return output

tudui = Tudui()
writer = SummaryWriter('./maxpool')
step = 0

for data in dataloader:
    imgs, targets = data
    writer.add_images("input", imgs, step)
    output = tudui(imgs)
    writer.add_images("output", output, step)
    step += 1

writer.close()

4神经网络—非线性激活

1)ReLu:也就是0截断函数

import torch
from torch import nn
from torch.nn import ReLU

input = torch.tensor([[1.1, -0.5],
                      [-1, 3]])
input = torch.reshape(input, shape=(-1, 1, 2, 2))
print(input.shape)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.relu1 = ReLU()

    def forward(self, input):
        output = self.relu1(input)
        return output

tudui = Tudui()
output = tudui(input)
print(output)

输出:

可以看见,<小于0的数被截断了

2)Sigmoid函数 -看起来像加滤镜

import torch
import torchvision
from torch import nn
from torch.nn import Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
input = torch.tensor([[1.1,-0.5],
                      [-1,3]])
input = torch.reshape(input,(-1,1,2,2,))
print(input.shape)
dataset = torchvision.datasets.CIFAR10('../dataset',train=False,
                                       transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.sigmoid1 = Sigmoid()
    def forward(self,input):
        output =self.sigmoid1(input)
        return output
tudui = Tudui()
writer = SummaryWriter('../relu')
step =0
for data in dataloader:
    imgs,targets = data
    writer.add_images('input',imgs,step)
    output = tudui(imgs)
    writer.add_images('output',output,step)
    step+=1
writer.close()

输出:

5.线性层及其他层介绍

主要是学会输入和输出的关系,参考官方文档,nn_linear的使用in_features和

out_features,还有torch.flatten和reshape的区别,flatten相当于二向箔

import torchvision
import torch
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10('../dataset',train=False,
                                       transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.linear1 = Linear(196608,10)
    def forward(self,input):
        output = self.linear1(input)
        return output
tudui = Tudui()
for data in dataloader:
    imgs,targets = data
    print(imgs.shape)
    # output = torch.reshape(imgs,(1,1,1,-1))
    output = torch.flatten(imgs)
    print(output.shape)
    output = tudui(output)
    print(output.shape)

flatten的输出

reshape的输出

6.搭建小实战和sequantial的使用

完成以下图片的操作

import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,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)
        self.sequential = 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.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)
        x = self.sequential(x)
        return x
tudui = Tudui()
print(tudui)
input = torch.ones((64,3,32,32))
output = tudui(input)
print(output.shape)
writer = SummaryWriter('../seq')
writer.add_graph(tudui,input)
writer.close()

利用tensorboard显示

7.损失函数和反向传播

LOSS 1:计算实际输出和目标之间的差距

2.为我们更新输出提供了一定的依据(反向传播)

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

lose_mse = nn.MSELoss()
result_mse = lose_mse(inputs,targets)
print(result)
print(result_mse)


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)

输出

在神经网络中使用

1)计算实际输出和目标之间的差距

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

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


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.sequential = 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.sequential(x)
        return x


loss = nn.CrossEntropyLoss()
tudui =Tudui()

for data in dataloader:
    imgs,targets = data
    outputs = tudui(imgs)
    result_loss = loss(imgs,targets)
    print(result_loss)

输出:

2)优化器—更新参数

先找到grad(梯度)

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

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


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.module1 = 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.module1(x)
        return x


loss = nn.CrossEntropyLoss()
tudui =Tudui()
optim = torch.optim.SGD(tudui.parameters(),lr=0.01)
for epoch in range(20):
    running_loss=0.0
    for data in dataloader:
        imgs,targets = data
        outputs = tudui(imgs)
        result_loss = loss(outputs,targets)
        optim.zero_grad()
        result_loss.backward()
        optim.step()
        running_loss+=result_loss
    print(running_loss)

输出:

8.现有的网络模型的使用和修改

vgg16_false = torchvision.models.vgg16(weights = None)
vgg16_true = torchvision.models.vgg16(weights='DEFAULT')
print(vgg16_true)

vgg16有1000个输出集,我们想用自己的模型,就得在vgg16的模型后加一个线性层,将输出集改为10

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

9.网络模型的保存与读取

1)保存

import torch
import torchvision

vgg16 = torchvision.models.vgg16(weights = None)
#保存方式1,保存的是模型结构+模型参数
torch.save(vgg16,'vgg16_method1.pth')
#保存方式2,保存的是模型参数(官方推荐)
torch.save(vgg16.state_dict(),'vgg16_method2.pth')

2)读取

import torch

#加载方式1:
model1 = torch.load('vgg16_method1.pth',weights_only=False)
# print(model1)
#加载方式2:
model2 = torch.load("vgg16_method2.pth")
print(model2)

方式二保存的是字典形式

import torch

#加载方式1:
model1 = torch.load('vgg16_method1.pth',weights_only=False)
# print(model1)
#加载方式2:
model2 = torch.load("vgg16_method2.pth")
print(model2)

但是调用方式1有陷阱,不能调用类->tudui=Tudui()

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

#加载方式1:
model1 = torch.load('vgg16_method1.pth',weights_only=False)
# print(model1)
#加载方式2:
model2 = torch.load("vgg16_method2.pth")
# print(model2)
#陷阱
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.sequential = 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.sequential(x)
        return x


#陷阱
model3 = torch.load('tudui_method1.pth',weights_only=False)
print(model3)

结果:

去掉tudui=Tudui()后,发现能正常运行