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)
结果:
