(自用)学习进度(二)

一、神经网络的基本骨架-nn.Module

(1)、概念

torcn.nn是专门为神经网络设计的模块化接口. nn构建于autograd之上,可以用来定义和运行神经网络。
    nn.Module是nn中十分重要的类,包含网络各层的定义及forward方法,在用户自定义神经网络时,需要继承自nn.Module类。

(2)、基本结构

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):  # Model类继承自nn.Module
    def __init__(self):   # 构造函数
        super(Model, self).__init__()  # 在构造函数中要调用Module的构造函数
        self.conv1 = nn.Conv2d(1, 20, 5)  # 卷积操作
        self.conv2 = nn.Conv2d(20, 20, 5) # 卷积操作

    def forward(self, x): # 前向传播函数
        x = F.relu(self.conv1(x))  # 先卷积操作conv1,后非线性操作relu
        return F.relu(self.conv2(x))

forward函数具体解析

(3)、实例

import torch
from torch import nn

class Nntest(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, input): # 经过forward,加一
        output = input + 1
        return output

nntest = Nntest()
x = torch.tensor(1.0)
output = nntest(x)
print(output)

输出结果如下:

二、卷积层

(1)、概念

 卷积层CNN(Convolutional Neural Networks)中的基本网络层,主要用于对图像进行特征提取操作,其卷积核权重是共享权值的,对应的相关概念还包括步长,填充。

Conv2d二维卷积为例,其参数主要为:

  • in_channels: – 输入图像中的通道数

  • out_channels: - 卷积产生的通道数,即卷积核的数量

  • stride:步长,卷积核在输入图像上滑动的步长,通常为 1 或 2。

  • kernel_size:卷积核的大小,可用元组(H,W)表示,H为高度,W为宽度

  • padding在输入数据的边界周围填充的层数,默认为0,控制卷积操作的输出大小。

  • padding_mode 填充模式,默认为:’zeros’

  • dilation:内核元素之间的间距。默认值:1,控制卷积操作中元素之间的距离

  • groups输入通道分组数,默认值:1,实现分组卷积

  • bias:是否使用偏置项,默认为True,表示卷积层是否包含可学习的偏置

计算公式:

过程如下图:

 具体可见https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md

(2)、矩阵实例

实现上图的卷积操作

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

#通过reshape修改尺寸
input = torch.reshape(input, (1, 1, 5, 5))
kernel = torch.reshape(kernel, (1, 1, 3, 3))

#输出结果
output = F.conv2d(input, kernel, stride=1)
print(output)

(3)、图像实例

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("../data", train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=64)


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


nntest = Nntest()

writer = SummaryWriter("logs")

step = 0
# print(nntest)
for data in dataloader:
    imgs, targets = data
    output = nntest(imgs)
    # torch.Size([64, 3, 32, 32])
    writer.add_images("input", imgs, step)
    # torch.Size([64, 6, 30, 30]) -> [xxx, 3, 30, 30]

    output = torch.reshape(output,(-1, 3, 30, 30))
    writer.add_images("output", output, step)

    step = step + 1

writer.close()

三、池化层

(一)、概念

池化层通常跟在卷积层之后,其主要目的是减少卷积层输出的特征图(Feature Maps)的空间大小,同时保留最重要的信息。这一过程不仅有助于减少计算量,还能提高模型的泛化能力,减少过拟合的风险。

以torch.nn.MaxPool2d二维最大池化为例,其参数主要为:

  • kernel_size:池化窗口的大小
  • stride:池化窗口的步长,默认值与kernel_size相同

  • padding:在输入数据的边界周围填充的层数

  • dilation:控制窗口中元素步幅的参数

  • return_indices:如果为True,将返回每个最大值的索引

  • ceil_mode:如果为True,会使用ceil而不是floor来计算输出形状(ceil向上取整,floor向下取整)

(2)、实例

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)
input = torch.reshape(input, (-1, 1, 5, 5))
print(input.shape)

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

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


nntest = Nntest()
output = nntest(input)
print(output)

ceil_mode为True时

ceil_mode为False时

继续以CIFAR10数据集为例与TensorBoard联动

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("../data", train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=64)


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

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


nntest = Nntest()

writer = SummaryWriter("logs_maxpool")
step = 0

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

writer.close()

四、非线性激活

(1)、概念

如果神经元的输出是输入的线性函数,而线性函数之间的嵌套任然会得到线性函数。如果不加非线性函数处理,那么最终得到的仍然是线性函数。所以需要在神经网络中引入非线性激活函数。

非线性变化的目的就是给我们的网络当中引入一些非线性特征

以ReLU函数为例,有一个参数inplace,该参数作用在于是否将输入数据进行替换,inplace的取值是True或者False,当inplace=True时,将输入数据进行替换,当inplace=False时,输入数据不进行替换。如下图所示:

(2)、实例

ReLU处理矩阵

import torch

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


class Nntest(nn.Module):
    def __init__(self):
        super(Nntest, self).__init__()
        self.relu = torch.nn.ReLU()

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


nntest = Nntest()
output = nntest(input)
print(output)

 

Sigmoid处理图片 

仍以二维最大池化CIFAR10数据集为例

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


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

class Nntest(nn.Module):
    def __init__(self):
        super(Nntest, self).__init__()
        self.relu1 = ReLU()
        self.sigmoid1 = Sigmoid()

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

nntest = Nntest()

writer = SummaryWriter("logs_relu")
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input", imgs, global_step=step)
    output = nntest(imgs)
    writer.add_images("output", output, step)
    step += 1

writer.close()

五、线性层

(1)、概念

线性层nn.Linear()是用于设置网络中的全连接层的,需要注意在二维图像处理的任务中,全连接层的输入与输出一般都设置为二维张量,形状通常为[batch_size, size],不同于卷积层要求输入输出是四维张量。其用法与形参说明如下:

使用nn.Linear()可以方便地创建全连接层,指定输入特征的维度和输出特征的维度,例如:

import torch as t
from torch import nn

# in_features由输入张量的形状决定,out_features则决定了输出张量的形状 
connected_layer = nn.Linear(in_features = 64*64*3, out_features = 1)

# 假定输入的图像形状为[64,64,3]
input = t.randn(1,64,64,3)

# 将四维张量转换为二维张量之后,才能作为全连接层的输入
input = input.view(1,64*64*3)
print(input.shape)
output = connected_layer(input) # 调用全连接层
print(output.shape)

运行结果为

(2)、实例

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

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

dataloader = DataLoader(dataset, batch_size=64, drop_last=True)

class Line(torch.nn.Module):
    def __init__(self):
        super(Line, self).__init__()
        self.linear = Linear(196608, 10)

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


testline = Line()

for data in dataloader:
    imgs, targets = data
    print(imgs.shape)
    output = torch.reshape(imgs, (1, 1, 1, -1))
    print(output.shape)
    output = testline(output)
    print(output.shape)

也可使用torch.flatten()将输入的张量展平为一维张量

效果如下

六、Sequential实战

(1)、概念

Sequential是一个有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行,同时以神经网络模块为元素的有序字典也可以作为传入参数。

(2)、实例

以下图为例搭建模型

代码与运行结果如下

import torch
from torch import nn

# 搭建网络
class TEST(nn.Module):
    def __init__(self):
        super(TEST, self).__init__()

        self.conv1 = nn.Conv2d(3, 32, 5, padding=2)
        self.maxpool1 = nn.MaxPool2d(kernel_size=2)
        self.conv2 = nn.Conv2d(32, 32, 5, padding=2)
        self.maxpool2 = nn.MaxPool2d(kernel_size=2)
        self.conv3 = nn.Conv2d(32, 64, 5, padding=2)
        self.maxpool3 = nn.MaxPool2d(kernel_size=2)
        self.flatten = nn.Flatten()
        self.linear1 = nn.Linear(1024, 64)
        self.linear2 = nn.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()
print(test)

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

使用Sequential简化代码

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


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

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

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

在TensorBoard可视化网络

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值