卷积神经网络的介绍

1. 卷积是什么

定义

卷积  是一种积分变换的数学方法。它是定义在两个函数上的数学运算。

数学定义:设 f(x) g(x) 是 两个可积函数,做积分:

                        \int_{-\infty }^{\infty } f(t)\ast g(x-t) dt

可以证明,关于几乎所有的实数 x,上述积分是存在的。随着x的不同取值,这个积分就定义了一个新函数   h(x)    称为函数  f 与  g   的卷积,记为 h(x) = (f*g)(x)

下面是采用蜡烛燃烧的概念来理解  卷积 这个概念:

参考的视频链接  B站 up 主  良叫我什么

https://www.bilibili.com/video/BV1JX4y1K7Dr/?spm_id_from=333.337.search-card.all.click&vd_source=ac2f909a3d37c98a835db4db3c041a29

 假设蜡烛 虽然质量不同,但是都以相同的速率进行燃烧,可得下方函数  G

 纵坐标 为 蜡烛 质量, 横坐标为时间。函数展示的是: 蜡烛的质量随时间的变化(初始蜡烛的质量可能为1,2.....10)。

下图为 某一时刻要做的事情   函数  F

0 分钟点燃 1 根蜡烛;

4 分钟点燃 4 根蜡烛;

5 分钟点燃 3 根蜡烛;

9 分钟点燃 2 根蜡烛;

...............................

 现在 有以下问题:

  假设每根蜡烛 的质量均为 10, 按照上述的方式去点燃蜡烛,则第 7 分钟时,剩余蜡烛的总质量为多少?

 因此 :

在  t  时刻,点燃了 f(t)  根蜡烛, f(t) 根蜡烛 燃烧了  (7-t) 分钟, 每根剩余质量  g(7-t)。

推论:

那么:

在 第 n 时刻( n > t)的时候,于 t  时刻点燃的这 f(t) 根蜡烛,燃烧了 (n - t) 分钟,每根剩余质量 g(n - t)。 则:这 f(t) 根蜡烛,剩余的总质量为  f(t) * g(n-t)   !!!!

如果  t 是离散的,则剩余总质量为:

        \sum_{t}^{} f(t)*g(n-t)

如果 t  是连续的,则:

        \int_{-\infty }^{\infty } f(t)\ast g(x-t) dt

意义

数学上的意义:如果 一个系统的 输入是不稳定的,但是 输出是稳定的;那么 就可以用 卷积 求系统存量

2. 图像的卷积

 把 卷积 当作 过去对现在的影响,周围像素点 对 当前像素点 的影响。 ----- 平滑卷积核

而 g 函数 规定了 如何影响的!

        除此之外 还有 其他的卷积核!!

卷积核:它是对周围像素点的主动的试探与选择,通过 它 把周围对自己有用的特征保留下来

 下图 摘自博客:
Pytorch:网络层介绍(卷积层、池化层、线性层、激活函数层)和多层感知机_pytorch卷积层-CSDN博客

1. 1d 卷积示意图

torch.nn.functional.conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) → Tensor 

This operator supports TensorFloat32.

应用:

Applies a 1D convolution over an input signal composed of several input planes.

对由多个输入平面组成的输入信号应用一维卷积。

 参数:

  • input:输入的张量,形状为 (batch_size, in_channels, length)。
  • weight:卷积核的权重张量,形状为 (out_channels, in_channels / groups, kernel_size)。
  • bias:可选参数,卷积层的偏置项张量,形状为 (out_channels,)。默认值为None,表示不使用偏置项。
  • stride:可选参数,卷积的步长。默认值为1。
  • padding:可选参数,输入的零填充的大小。默认值为0。
  • dilation:可选参数,卷积核元素之间的跳跃间隔。默认值为1。
  • groups:可选参数,将输入和输出通道分组的数量。默认值为1。

注意:

        1. batch_size是批量大小,in_channels是输入通道数,input_length是输入序列的长度

        2. out_channels是输出通道数,kernel_size是卷积核的大小。in_channels/groups是输入通道数除以分组数。

        3. padding 扩展的是 input 的 tensor,而不是卷积完成,输出后的 tensor。

import torch
import torch.nn as nn

# 定义输入数据
batch_size = 1
in_channels = 3
input_length = 10
input_data = torch.rand(batch_size, in_channels, input_length)
print(input_data)

# 定义卷积层参数
out_channels = 2
kernel_size = 3
stride = 2
padding = 1

# 创建一维卷积层
conv1d = nn.Conv1d(in_channels, out_channels, kernel_size, stride, padding)

# 进行一维卷积操作
output = conv1d(input_data)
print(output.shape)  
# 输出形状为(batch_size, out_channels, output_length)  torch.Size([1, 2, 5])

2. 2d 卷积示意图

     多通道 类型:

          如果是多个通道的卷积核,首先按照单个通道进行操作,然后将得到的多个通道的特征图进行相加得到最后的结果。

        如下图:输入特征是3个通道的,那么单个卷积核也是三个通道的,首先进行卷积然后将多个通道的卷积进行相加。

torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) → Tensor

应用:

Applies a 2D convolution over an input image composed of several input planes.

对由多个输入平面组成的输入图像应用二维卷积。

用于从输入数据中提取特征。它主要应用于图像处理和计算机视觉任务中。

卷积核的大小和数量是可以自定义的,不同大小和数量的卷积核可以提取不同的特征。

输出:

输出特征图的形状为(Batch_size, out_channels, H_out, W_out),其中H_out和W_out分别是输出特征图的高度和宽度。

实际上这4 个值的含义是:图片数、图层数、高、宽

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

# 定义输入张量
batch_size = 1
channels = 1
height = 5
width = 5

input_tensor = torch.randn(batch_size, channels, height, width)

# 定义卷积核
kernel_size = 3
stride = 1
padding = 0

# 使用conv2d函数进行单层卷积
output_tensor = F.conv2d(input_tensor, nn.Parameter(torch.randn(1, 1, kernel_size, kernel_size)), stride=stride, padding=padding)

# 打印输入张量和输出张量的形状
print("Input tensor shape:", input_tensor.shape)
print("Output tensor shape:", output_tensor.shape)


"""
Input tensor shape: torch.Size([1, 1, 5, 5])
Output tensor shape: torch.Size([1, 1, 3, 3])
"""

import torch
import torch.nn.functional as F
input = torch.tensor([[1,2,3],
                      [4,5,6],
                      [7,8,9]],dtype=torch.float32)
kernel = torch.tensor([[1/4,1/4],
                       [1/4,1/4]])
# 由于 cov2d 需要的输入的 tensor 的 shape 为:Batch_size, in_channels, H_out, W_out)
print(input.shape)  # torch.Size([3, 3])
# 需要改变 tensor 的形状
input  = input.reshape(1,1,3,3)
print(input.shape)  # torch.Size([1, 1, 3, 3])

kernel = kernel.reshape(1,1,2,2)

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

output1 = F.conv2d(input,kernel,stride=1,padding=1)
print(output1)

3. 3d 卷积示意图

3.  卷积 使用示例

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


#1. 准备数据
dataset = torchvision.datasets.CIFAR10(root="../TorchVersion/dataset",train=True,
                                       transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64)

#2. 创建自己的模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)

# forward 是为了对输入 x 进行定义在 __init__ 上的网络进行计算
    def forward(self,x):
        x = self.conv1(x)
        return x

mymodel = MyModel()
print(mymodel)
"""
输出的模型:
#MyModel(
  (conv1): Conv2d(3, 6, kernel_size=(3, 3), stride=(1, 1))
)
"""

write = SummaryWriter("logs")
step = 0

# 3. 读入模型数据,并进行卷积,最后通过 tensorboard 展现出来
for data in dataloader:
    imgs, targets = data
    output = mymodel(imgs)
    print(imgs.shape)       #  torch.Size([64, 3, 32, 32])
    print(output.shape)     #  torch.Size([64, 6, 30, 30]) 可见实现了卷积
    write.add_image("input",imgs,step,dataformats="NCHW")

    # 由于生成后的 channel 是 6 ,需要转为 3通道
    output = torch.reshape(output,(-1,3,30,30))
    write.add_image("output",output,step,dataformats="NCHW")
    step = step + 1

write.close()

注意:

        1.  # 由于生成后的 channel 是 6 ,需要转为 3通道, tensorboard 显示出 3 通道 图片。
                    output = torch.reshape(output,(-1,3,30,30))
                    write.add_image("output",output,step,dataformats="NCHW")

4.  torch.nn.Conv2d  与  torch.nn.functional.conv2d  的区别与联系

1.  torch.nn.Conv2d

torch.nn.Conv2d‌ 是一个类,它属于PyTorch中定义的一个卷积层,是torch.nn.Module的一部分。这意味着它是一个可以实例化的类,通常用于构建自定义的神经网络层。当创建一个torch.nn.Module的子类时,可以在其中创建torch.nn.Conv2d实例,这个实例在模型的前向传播过程中被调用,以执行卷积操作。 

class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)

  • in_channels: 输入通道数,例如RGB图像的通道数为3。
  • out_channels: 输出通道数,即卷积核的数量,控制卷积层输出的特征图的深度。
  • kernel_size: 卷积核的大小,可以是一个整数或一个元组,例如(3, 3)。
  • stride: 卷积核的步长,可以是一个整数或一个元组,例如(2, 2)。
  • padding: 输入边界的填充数量,可以是一个整数或一个元组,例如(1, 1)。
  • dilation: 卷积核元素之间的间距,可以是一个整数或一个元组,用于控制卷积核的可感受野大小。
  • groups: 输入通道被分组的数量,可以用来实现分组卷积操作。
  • bias: 是否在卷积中使用偏置项,默认为True。

 注意:

        nn.Conv2d的卷积核是通过随机初始化的。每个卷积核都是一个二维矩阵,其大小取决于参数设置。默认情况下,卷积核的形状为(kernel_size, kernel_size),其中kernel_size是由用户指定的卷积核大小。

        具体地说,每个卷积核的参数是在训练过程中通过反向传播和梯度下降等优化算法进行学习的,以使得网络能够更好地进行特征提取和模式识别。因此,在初始化时无法确定卷积核的确切形状和数值。

 

 输出形状(Output Shape)表示卷积层的输出特征映射的尺寸,可以用(N,Cout,Hout,Wout) 或 (Cout,Hout,Wout) 表示,其中Cout是输出通道数,Hout是输出特征映射的高度,Wout是输出特征映射的宽度。

通过这些公式,可以根据输入的形状和卷积层的参数计算出输出的形状,从而对CNN的网络结构和尺寸进行设计和调整。

# 创建自己的模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)

# forward 是为了对输入 x 进行定义在 __init__ 上的网络进行计算
    def forward(self,x):
        x = self.conv1(x)
        return x

2.  torch.nn.functional.conv2d

torch.nn.functional.conv2d‌ 是一个函数,属于PyTorch的功能性API,它提供了许多独立的函数来实现各种操作,包括卷积操作。这个函数不依赖于类的实例化,可以直接调用以执行卷积操作。它的优点是使用简单,不需要创建类的实例,适用于快速原型设计和灵活应用。

 torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) → Tensor


import torch
import torch.nn.functional as F
input = torch.tensor([[1,2,3],
                      [4,5,6],
                      [7,8,9]],dtype=torch.float32)
kernel = torch.tensor([[1/4,1/4],
                       [1/4,1/4]])
# 由于 cov2d 需要的输入的 tensor 的 shape 为:Batch_size, in_channels, H_out, W_out)
print(input.shape)  # torch.Size([3, 3])
# 需要改变 tensor 的形状
input  = input.reshape(1,1,3,3)
print(input.shape)  # torch.Size([1, 1, 3, 3])

kernel = kernel.reshape(1,1,2,2)

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

output1 = F.conv2d(input,kernel,stride=1,padding=1)
print(output1)



3. 使用场景

如果构建一个复杂的神经网络模型,可则使用torch.nn.Conv2d,因为它与模型的其余部分集成得更好。

如果你只是想快速尝试一个新的卷积操作,或者在不构建完整模型的情况下进行实验,那么使用torch.nn.functional.conv2d可能会更方便‌。

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值