Pytorch入门学习笔记(三)—— 神经网络

本文通过小土堆的教程,介绍了如何使用PyTorch构建基础深度学习模型,包括Module和Sequential类的使用、卷积层(Conv2d)、池化层(MaxPool2d)、非线性激活ReLU和Sigmoid,以及线性层(Linear)的应用,最后以CIFAR10数据集为例,展示了如何搭建一个简单的神经网络模型。
部署运行你感兴趣的模型镜像

本文结合小土堆的教学视频PyTorch深度学习快速入门教程进行学习

一、 基本骨架 Containers

1. torch.nn.Module

Module 类是所有神经网络模块的基类,还可以包含其他模块,允许他们嵌套在树状结构中。

当继承 Module 父类时,需要调用 __init__() 函数进行初始化处理,并且在该函数中必须调用父类的初始化函数。同时还可以调用 forward() 函数进行前向传播。

具体代码实现如下

import torch

# 继承Module模块,创建一个属于自己的类
class Model(torch.nn.Module):

    # 类的初始化
    def __init__(self):
        super().__init__()

    # 调用forward函数
    def forward(self, input):
        output = input + 1
        return output

model = Model()
x = torch.tensor(1.0)
output = model(x)
print(output)

程序运行结果输出  tensor(2.) 

2.torch.nn.Sequential

Sequential 类继承自Module 类,是一个有顺序的容器,将特定神经网络模块按照在传入容器的顺序依次执行

具体代码实现如下

from torch import nn

# 创建Sequential实例
model = nn.Sequential(
          nn.Conv2d(1,20,5),    # 第一次卷积操作
          nn.ReLU(),            # 第一次非线性激活
          nn.Conv2d(20,64,5),   # 第二次卷积操作
          nn.ReLU()             # 第二次非线性激活
        )
print(model)

程序运行结果如下

Sequential(
  (0): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
  (1): ReLU()
  (2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
  (3): ReLU()
)

二、 卷积层 Convolution Layers

功能实现:提取输入图像中的特征信息

Conv2d:对二维数据进行卷积层的处理

1. torch.nn.functional.conv2d

函数定义:

torch.nn.functional.conv2d(inputweightbias=Nonestride=1padding=0dilation=1groups=1

参数含义:input 表示传入要进行处理的图像数据; weight  表示权重,即卷积核;bias 表示形状的可选偏置张量,默认值为 None; stride  表示卷积的步幅,默认值为1; padding  表示图像边沿填充的数目,默认值为0

具体代码实现如下

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]])
# 卷积核
kernel = torch.tensor([[1,2,1],
                       [0,1,0],
                       [2,1,0]])
# 由于直接使用torch.tensor传入的数据只有2个尺寸形式,而conv2d的传参要求需要4个尺寸形式
# 对输入矩阵和卷积核的尺寸进行转变
input = torch.reshape(input,(1,1,5,5))
kernel = torch.reshape(kernel,(1,1,3,3))

# 输出卷积结果
output = F.conv2d(input,kernel,stride=1)            # 卷积核步长为1,边缘无填充
output2 = F.conv2d(input,kernel,stride=2)           # 卷积核步长为2,边缘无填充
output3 = F.conv2d(input,kernel,stride=1,padding=1) # 卷积核步长为1,边缘填充一圈
print(output)
print(output2)
print(output3)

程序运行结果如下

tensor([[[[10, 12, 12],
          [18, 16, 16],
          [13,  9,  3]]]])
tensor([[[[10, 12],
          [13,  3]]]])
tensor([[[[ 1,  3,  4, 10,  8],
          [ 5, 10, 12, 12,  6],
          [ 7, 18, 16, 16,  8],
          [11, 13,  9,  3,  4],
          [14, 13,  9,  7,  4]]]])

2. torch.nn.Conv2d

计算公式为  out(N_i,C_{outj})=bias(C_{outj})+\sum_{k=0}^{C_{in}-1}weight(C_{outj},k) \times input(N_i,k)

其中 是批量大小,表示多个通道,是输入平面的高度(以像素为单位),是宽度(以像素为单位)

函数定义:

torch.nn.Conv2d(in_channelsout_channelskernel_sizestride=1padding=0dilation=1groups=1bias=Truepadding_mode='zeros'device=Nonedtype=None

参数含义: in_channels  表示输入图像中的通道数(通常为 RGB 3通道); out_channels  表示经过卷积后输出图像的通道数; kernel_size  表示卷积核的大小,输入整数 size 表示大小为 size × size,输入序列 (h,w) 表示大小为 h × w; stride  表示卷积的步幅,默认值为1; padding  表示图像边沿填充的数目,默认值为0;padding_mode 表示边沿填充模式

具体代码实现如下

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

# 准备并加载测试数据集
dataset = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloder = DataLoader(dataset,batch_size=64)

# 创建model类(继承Module)
class Model(nn.Module):
    # 类的初始化
    def __init__(self):
        super().__init__()    # 父类的初始化
        self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)  # 定义卷积层
    # forward函数
    def forward(self,x):
        x = self.conv1(x)    # 对输入进来的x进行卷积操作
        return x

model = Model() # 创建类的实例
step = 0
writer = SummaryWriter("logs")
# 通过for循环遍历数据集中的每个子集
for data in dataloder:
    imgs,targets = data
    output = model(imgs)    # 传入图片进行卷积操作
    writer.add_images("input",imgs,step)    # 显示输入图片
    output = torch.reshape(output,(-1,3,30,30)) # 转变输出图片尺寸(经过卷积之后图片变成30×30)
    # -1表示不清楚该值要设置为多少,系统会自动根据后面的值进行计算;3表示将图片转化为三通道
    writer.add_images("output",output,step) # 显示输出图片
    step += 1
writer.close()

将程序运行后,在终端输入  tensorboard --logdir=logs --port=6007  ,结果显示如下

三、 池化层 Pooling Layers

功能实现:提取窗口的特征数据,保留输入的特征,减小需要计算的数据量

MaxPool2d:直接计算池化窗口内的原始数据,选择池化核覆盖的范围中的最大值

函数定义:

torch.nn.MaxPool2d(kernel_sizestride=Nonepadding=0dilation=1return_indices=Falseceil_mode=False)

参数含义: kernel_size  表示池化核的窗口大小; stride  表示池化核窗口的步长(默认值为kernel_size); padding  表示图像边沿填充的数目; ceil_mode  当值为 True 时,表示将使用 ceil 而不是 floor 来计算输出形状,即保存大小不足为kernel_size的数据,自动补足NAN至kernel_size大小,值为 False表示直接舍弃大小不足为 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]],dtype=torch.float32) # 转为浮点数的tensor类型
# 对输入矩阵的尺寸进行转变,因为MaxPool2d的传参要求需要4个尺寸形式
input = torch.reshape(input,(1,1,5,5))

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        # 池化核大小为3×3,并保存大小不足为kernel_size的数据
        self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=True)

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

model = Model()
output = model(input)
print(output)

程序运行结果如下

tensor([[[[2., 3.],
          [5., 1.]]]])

若将 ceil_mode 的值赋为 False,则程序运行结果为  tensor([[[[2.]]]]) 

在调试过程中出现了  RuntimeError: "max_pool2d" not implemented for 'Long'  的报错,是由于我们传入数据的类型不符合 long 型,故需要在传入数据后添加  dtype=torch.float32 

具体代码实现如下(图像数据)

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

# 准备并加载测试数据集
dataset = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloder = DataLoader(dataset,batch_size=64)

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        # 池化核大小为3×3,并保存大小不足为kernel_size的数据
        self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=True)

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

model = Model()
step = 0
writer = SummaryWriter("logs")
# 通过for循环遍历数据集中的每个子集
for data in dataloder:
    imgs,targets = data
    output = model(imgs)    # 传入图片进行池化操作
    writer.add_images("input",imgs,step)    # 显示输入图片
    writer.add_images("output",output,step) # 显示输出图片
    step += 1
writer.close()

将程序运行后,在终端输入  tensorboard --logdir=logs --port=6007  ,结果显示如下

四、 非线性激活 Non-linear Activations

功能实现:向神经网络引入一些非线性的特质

1. torch.nn.ReLU

函数定义: torch.nn.ReLU(inplace=False

参数含义: inplace  若设置为 True ,则函数会把输出结果覆盖到输入变量中(默认值为 False)

计算公式: ReLU(x)=(x)^{+}=max(0,x)

具体代码实现如下

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

# 输入数据矩阵
input = torch.tensor([[1,-0.5],
                      [-1,3]])
input = torch.reshape(input,(-1,1,2,2))   # 转化数据尺寸

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.relu1 = ReLU() # 定义非线性激活函数

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

程序运行结果如下

tensor([[[[1., 0.],
          [0., 3.]]]])

2. torch.nn.Sigmoid

函数定义: torch.nn.Sigmoid(*args**kwargs

计算公式: Sigmoid(x)=\sigma(x)=\frac{1}{1+exp(-x)}

具体代码实现如下

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

# 准备并加载测试数据集
dataset = torchvision.datasets.CIFAR10("./dataset",train=False,download=False,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset,batch_size=64)

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.sigmoid1 = Sigmoid() # 定义非线性激活函数

    def forward(self,input):
        output = self.sigmoid1(input)
        return output
    
model = Model()
step = 0
writer = SummaryWriter("logs")
for data in dataloader:
    imgs,targets = data
    writer.add_images("input",imgs,step)
    output = model(imgs)
    writer.add_images("output",output,step)
    step += 1
writer.close()

将程序运行后,在终端输入  tensorboard --logdir=logs --port=6007  ,结果显示如下

五、 线性层 Linear Layers

功能实现:将前面计算得到的特征向量进行线性变换,转化成一维向量

函数定义: torch.nn.Linear(in_featuresout_featuresbias=Truedevice=Nonedtype=None

参数含义: in_features  表示每次输入样本的大小; out_features  表示每次输出样本的大小;bias 表示偏置量

具体代码实现如下

import torch
from torch import nn
from torch.nn import Linear
import torchvision
from torch.utils.data import DataLoader

# 准备并加载测试数据集
dataset = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloder = DataLoader(dataset,batch_size=64,drop_last=True)

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear1 = Linear(196608,10)    # 将输入图片的大小196608转化为10
    def forward(self,x):
        x = self.linear1(x)
        return x

model = Model()
for data in dataloder:
    imgs,targets = data
    # output = torch.reshape(imgs,(1,1,1,-1))   # 将图片数据扁平化
    output = torch.flatten(imgs)    # 可以替代上面的reshape函数的功能
    print(output.shape)
    output = model(output)
    print(output.shape)

六、 搭建神经网络模型小实战(结合 CIFAR10 模型)

CIFAR10 模型结构如下

具体实战代码实现如下

import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class Model(nn.Module):
    def __init__(self) -> None:
        super(Model,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

model = Model()
print(model)
input = torch.ones((64,3,32,32))    # 构建一个值全为1的矩阵
output = model(input)
print(output.shape)

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

程序运行结果如下

Model(
  (conv1): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
  (maxpool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (conv2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
  (maxpool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (conv3): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
  (maxpool3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear1): Linear(in_features=1024, out_features=64, bias=True)
  (linear2): Linear(in_features=64, out_features=10, bias=True)
)
torch.Size([64, 10])

具体代码实现如下(结合 Sequential 类)

import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class Model(nn.Module):
    def __init__(self) -> None:
        super(Model,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

model = Model()
print(model)
input = torch.ones((64,3,32,32))
output = model(input)
print(output.shape)

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

程序运行结果如下

Model(
  (model1): Sequential(
    (0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (6): Flatten(start_dim=1, end_dim=-1)
    (7): Linear(in_features=1024, out_features=64, bias=True)
    (8): Linear(in_features=64, out_features=10, bias=True)
  )
)
torch.Size([64, 10])

将程序运行后,在终端输入  tensorboard --logdir=logs --port=6007  ,结果显示如下

 

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值