Pytorch入门(二)神经网络的搭建

torch.nn中的nn全称为neural network,意思是神经网络,是torch中构建神经网络的模块。

一、神经网络基本骨架

CNN卷积神经网络基本包含五个层

  • ①输入层
    • 主要做什么?数据的预处理
      • 去均值
      • 归一化
      • PCA/SVD降维等
    • 使用模块
      • transforms
  • ②卷积层
    一个图像占有很大的维数,但是图像的特征所在的维数远小于一个图像的维数
    在训练时冗余的维数会拖慢训练进度,我们要使用卷积降低维数,又保留特征(人识别不出特征计算机可以)
  • ③激活(激励)层
    • 主要做什么?
      • 对卷积层得出的结果做一次非线性映射
    • 主要使用函数
      • sigmoid
      • tanh
      • relu
      • leaky relu
      • elu
      • maxout
  • ④池化层(又称欠采样或下采样)
    • 主要作用:
      • 特征降维,压缩数据参数、数量,减小过拟合提高模型的容错性
    • 主要模块
      • 平均池化:MaxPooling
      • 最大池化:Average Pooling
  • ⑤全连接fc层
    • 经过多次卷积、激励、池化后没有出现过拟合可以认为模型训练完毕

二、认识卷积操作

  • 卷积相关概念
    • 卷积核:一定大小的矩阵,利用该矩阵与目标矩阵进行运算
    • 卷积操作:具体运算是对应项相乘再相加,计算结果放在新生成的位置
  • 卷积操作常用函数
    • conv1d(一维卷积)
    • conv2d(二维卷积)
    • conv3d(三维卷积)
  • 卷积时传进去的参数意义
    • input 需要进行操作的矩阵
    • weight 矩阵的权重
    • stride 每次卷积完下次卷积移动的步长
    • padding 目标矩阵在进行卷积操作的时候,是否进行外边界的填充

在这里插入图片描述

下面代码模拟了一下卷积操作:

# 模拟一下卷积操作
# 目标矩阵
objA=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]])
# 卷积核
coCore=torch.tensor([[1,2,1],
        [0,1,0],
        [2,1,0]])
input=torch.reshape(objA,(1,1,5,5))
coCore=torch.reshape(coCore,(1,1,3,3))
# 步长为1没有外边界填充
output1=F.conv2d(input,coCore,stride=1)
# 向外扩充一圈
output2=F.conv2d(input,coCore,stride=1,padding=1)
print(output1)
print(output2)

结果(可以自己计算测试一下):

tensor([[[[10, 12, 12],
          [18, 16, 16],
          [13,  9,  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]]]])

Process finished with exit code 0

将数据传入神经网络,进行多层卷积会得到具有明显特征的图片

测试一下神经网络中的卷积:

import os

import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
'''
将数据传入神经网络,进行多层卷积会得到具有明显特征的图片
'''
basepath=os.path.split(os.getcwd())[0]
# 获取需要使用的数据集
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor(),download=True)
# 加载数据集其中64个打包分成一块
dataloader=DataLoader(dataset,batch_size=64)
# 自定义一个神经网络类
class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        # 初始化一层卷积
        # channels          英文意思是频道
        # in_channels       向神经网络输送的数据频道数量
        # out_channels      神经网络输出的频道数量
        # kernel_size       卷积核的大小,输出的时候会将卷积核根据其大小正方形化
        # stride            每次卷积移动的步长,输出的时候也是一个元组,代表左右上下都是移动1
        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
# 创建日志文件,显示图像表示的效果
writer=SummaryWriter("logs_Conv")
# 生成神经网络模型
myModel=Model()
# print(myModel)
stept=0
# 迭代打包好的数据,将数据输送到神经网络进行卷积,最后得出卷积后的图片
for data in dataloader:
    # 获取数据与标签
    imgs,targets=data
    # 将数据输送到神经网络
    output=myModel(imgs)
    print(imgs.shape)
    print(output.shape)
    # 输出的数据是3,6,30,30   30为尺寸
    # tensorboard无法识别6维的图片,使用reshape修改图片形状
    output=torch.reshape(output,(-1,3,30,30))
    # 将图片加入到tensorBoard中
    writer.add_images("input",imgs,stept)
    writer.add_images("output",output,stept)
    stept=stept+1
    # 如果一个图片经过卷积尺寸没有改变并且维度变大,那么可能进行了卷积时的边界填充

三、认识最大池化操作

最大池化的作用:
通过卷积核大小将图片各个区域的最大值选出来
一般最大池化后会将数据的大小大大减小,以此提高训练速度
最大池化会将数据比较明显的特征提取出来
在日常神经网络训练过程中,通常将卷积,最大池化,激活函数交替使用

最大池化,Tensor变化,我记得还有平均池化之类的东西,感兴趣大家自己研究研究。
在这里插入图片描述

import os

import torch.nn as nn
import torch
import torchvision
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
basepath=os.path.split(os.getcwd())[0]
# 初始化数据集
writer=SummaryWriter(basepath+r"\logss\logs9_1")
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,64)
class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.pool1=MaxPool2d(kernel_size=2,ceil_mode=True)
    def forward(self,input):
        output=self.pool1(input)
        return output
# 创建神经网络模型
myModel=Model()
step=0
for data in dataloader:
    imgs,targes=data
    output=myModel(imgs)
    writer.add_images("pool_test",output,step)
    step=step+1
writer.close()

池化过后的图片:
在这里插入图片描述

四、非线性激活

当数据混乱冗杂时,不带激活函数的单层感知机是一个线性分类器,线性函数无法对各个类别进行分类
激活函数是用来加入非线性因素的,提高神经网络对模型的表达能力,解决线性模型无法解决的问题

单层感知机是最基础的神经网络,感知机网络与卷积网络都属于前馈型网络
单层感知机网络是二分类的线性分类模型,输入是被感知数据集的特征向量,输出是数据集的类别

在这里插入图片描述

五、线性层及其它层介绍

  • Linear Layers线性层

  • Dropout Layers 随机将一些数据置为0
    Dropout函数参数
    第一个参数p是被置为0的概率,第二个参数inplace 是否在本次样本进行操作默认为false

  • Normalization正则化层

  • Recurrent Layers

  • Transformer Layers

  • Sparse Layers 一般用于自然语言处理

import os

import torch.nn as nn
import torch
import torchvision.datasets
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

basepath=os.path.split(os.getcwd())[0]
# 预处理数据集
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,64)
writer=SummaryWriter(basepath+r"\logss\log_6")
class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        '''
        Linear()
        第一个参数是输入的样本大小,第二个是输出的样本大小,第三个是是否偏执,默认为true
        '''
        self.line1=nn.Linear(196608,10)
    def forward(self,input):
        output=self.line1(input)
        return output
myModel=Model()
step=0
for data in dataloader:
    imgs,targets=data
    print(imgs.shape)
    # 该函数直接将多维数组直接转换成一维数组
    output=torch.flatten(imgs)
    print(output.shape)
    output=myModel(output)
    print(output.shape)
    # writer.add_images("test",output,step)
    step=step+1

六、简单的神经网络搭建

普通方式

import os

import torch
import torch.nn as nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
basepath=os.path.split(os.getcwd())[0]

class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.con1=Conv2d(3, 32, 5, padding=2)
        self.maxp1=MaxPool2d(2)
        self.con2=Conv2d(32, 32, 5, padding=2)
        self.maxp2=MaxPool2d(2)
        self.con3=Conv2d(32, 64, 5, padding=2)
        self.maxp3=MaxPool2d(2)
        self.fla=Flatten()
        self.lin1=Linear(1024, 64)
        self.lin2=Linear(64, 10)
    def forward(self,x):
        x=self.con1(x)
        x=self.maxp1(x)
        x=self.con2(x)
        x=self.maxp2(x)
        x=self.con3(x)
        x=self.maxp3(x)
        x=self.fla(x)
        x=self.lin1(x)
        x=self.lin2(x)
        return x

Sequential方式
构建神经网络的另一个方法,也可以说是快速构建方法,就是通过torch.nn.Sequential,直接完成对神经网络的建立。

import os

import torch
import torch.nn as nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
basepath=os.path.split(os.getcwd())[0]

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

直接打印创建的对象可以看到网络结构,也可以通过之前介绍到的tensorboard查看网络结构:

myModel=Model()
writer=SummaryWriter(basepath+r"\logss\log_7")
print(myModel)
input=torch.ones((64,3,32,32))
output=myModel(input)
print(output.shape)
# 将搭建的神经网络结构绘制到tensorboard中
writer.add_graph(myModel,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])

Process finished with exit code 0

在这里插入图片描述

七、简单的认识神经网络中的数值计算

import torch
from torch.nn import L1Loss
import torch.nn as nn
input=torch.tensor([1,2,3],dtype=torch.float32)
target=torch.tensor([1,2,5])
input=torch.reshape(input,(1,1,1,3))
target=torch.reshape(target,(1,1,1,3))
# 获取损失函数计算器(计算差值)
# reduction可以进行修改
loss=L1Loss(reduction="sum")
result_loss=loss(input,target)
print(result_loss)
# 计算平方差
loss_mse=nn.MSELoss()
result_loss_mse=loss_mse(input,target)
print(result_loss_mse)
# 交叉熵
x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
# 这里(1,3)代表有三个类别一个进行选择
x=torch.reshape(x,(1,3))
loss_cross=nn.CrossEntropyLoss()
result_loss=loss_cross(x,y)
print(result_loss)

八、损失函数与反向传播的应用

  • 损失函数
    损失函数用于检测最后的数据结果与最开始的数据存在的差值(默认计算的是平均损失值,可以对reduction参数进行修改,改为自己想进行的运算方式)计算实际得到的结果与预测结果的差值
  • 反向传播
    损失函数进行完损失值的计算,使用反向传播会给数据下一次进入神经网络提供一些参数进行参考,以减小损失值结合优化器一块使用,反向传播告诉神经网络,模型的好坏,哪里需要调整
  • 优化器
    损失函数进行误差估计,反向传播将数据参数给优化器,然后优化器根据梯度对训练方式进行优化
    优化器没进行完一次优化,就需要将数据清理一次
import os

import torchvision.datasets
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
import torch
import torch.nn as nn
from torch.utils.data import  DataLoader
basepath=os.path.split(os.getcwd())[0]
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,1)
class Model(nn.Module):
    def __init__(self):
        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
myModel=Model()
# 创建损失函数
loss=nn.CrossEntropyLoss()
# 获取优化器
optim=torch.optim.SGD(myModel.parameters(),lr=0.01)#lr指的是训练速率,这个速率不可以过高,也不可以太低,过高会使模型不稳定
for x in range(20):#过低训练速度太慢
    runing_loss=0.0
    for data in dataloader:
        imgs,targets=data
        output=myModel(imgs)
        # print(output)
        # print(targets)
        result_loss=loss(output,targets)
        optim.zero_grad()
        result_loss.backward()
        optim.step()
        runing_loss=runing_loss+result_loss
    print(runing_loss)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/apple_51931783/article/details/130970868