深度学习之卷积神经网络(一)

目录

1. 概述

1.1 使用场景

1.2 与传统网络的区别

1.3 全连接的局限性

1.3.1 参数量巨大

1.3.2 表达能力太有限

1.4 卷积思想

1.4.1 概念

1.4.2 局部连接

1.4.3 权重共享

2. 卷积层

2.1 卷积核

2.2 卷积计算

2.2.1 卷积计算过程

2.2.2 卷积计算底层实现

2.3 边缘填充

2.4 步长Stride

2.5 多通道卷积计算

2.5.1 数字图像的标识

2.5.2 具体计算实现

2.6 多卷积核卷积计算

2.7 特征图大小

2.8 只卷一次?

2.9 卷积参数共享

2.10 局部特征提取

2.11 PyTorch卷积层 API


视觉处理三大任务:图像分类、目标检测、图像分割

上游:提取特征,CNN

下游:分类、目标、分割等,具体的业务

1. 概述

卷积神经网络是深度学习在计算机视觉领域的突破性成果。在计算机视觉领域, 往往我们输入的图像都很大,使用全连接网络的话,计算的代价较高。另外图像也很难保留原有的特征,导致图像处理的准确率不高。

卷积神经网络(Convolutional Neural Network,CNN)是一种专门用于处理具有网格状结构数据的深度学习模型。最初,CNN主要应用于计算机视觉任务,但它的成功启发了在其他领域应用,如自然语言处理等。

卷积神经网络(Convolutional Neural Network)是含有卷积层的神经网络. 卷积层的作用就是用来自动学习、提取图像的特征。

CNN网络主要有三部分构成:卷积层、池化层和全连接层构成,其中卷积层负责提取图像中的局部特征;池化层用来大幅降低运算量并特征增强;全连接层类似神经网络的部分,用来输出想要的结果。

1.1 使用场景

1.2 与传统网络的区别

1.3 全连接的局限性

全连接神经网络并不太适合处理图像数据....

1.3.1 参数量巨大

$$
y = x \times W^T + b
$$

全连接结构计算量非常大,假设我们有1000×1000的输入,如果隐藏层也是1000×1000大小的神经元,由于神经元和图像每一个像素连接,则参数量会达到惊人的1000×1000×1000×1000,仅仅一层网络就已经有10^{12}个参数。

1.3.2 表达能力太有限

全连接神经网络的角色只是一个分类器,如果将整个图片直接输入网络,不仅参数量大,也没有利用好图片中像素的空间特性,增加了学习难度,降低了学习效果。

1.4 卷积思想

卷:从左往右,从上往下

积:乘积,求和

1.4.1 概念

Convolution,输入信息与卷积核(滤波器,Filter)的乘积。

1.4.2 局部连接
  • 局部连接可以更好地利用图像中的结构信息,空间距离越相近的像素其相互影响越大。

  • 根据局部特征完成目标的可辨识性。

1.4.3 权重共享
  • 图像从一个局部区域学习到的信息应用到其他区域。

  • 减少参数,降低学习难度。

2. 卷积层

接下来,我们开始学习卷积核的计算过程, 即: 卷积核是如何提取特征的。

2.1 卷积核

卷积核是卷积运算过程中必不可少的一个“工具”,在卷积神经网络中,卷积核是非常重要的,它们被用来提取图像中的特征。

卷积核其实是一个小矩阵,在定义时需要考虑以下几方面的内容:

  • 卷积核的个数:卷积核(过滤器)的个数决定了其输出特征矩阵的通道数

  • 卷积核的值:卷积核的值是初始化好的,后续进行更新。

  • 卷积核的大小:常见的卷积核有1×1、3×3、5×5等,一般都是奇数 × 奇数。

下图就是一个3×3的卷积核:

2.2 卷积计算

2.2.1 卷积计算过程

卷积的过程是将卷积核在图像上进行滑动计算,每次滑动到一个新的位置时,卷积核和图像进行点对点的计算,并将其求和得到一个新的值,然后将这个新的值加入到特征图中,最终得到一个新的特征图。

  1. input 表示输入的图像

  2. filter 表示卷积核, 也叫做滤波器

  3. input 经过 filter 的得到输出为最右侧的图像,该图叫做特征图

那么, 它是如何进行计算的呢?卷积运算本质上就是在滤波器和输入数据的局部区域间做点积。

左上角的点计算方法:

按照上面的计算方法可以得到最终的特征图为:

卷积的重要性在于它可以将图像中的特征与卷积核进行卷积操作,从而提取出图像中的特征

可以通过不断调整卷积核的大小、卷积核的值和卷积操作的步长,可以提取出不同尺度和位置的特征。

 # 面向对象的模块化编程
 from matplotlib import pyplot as plt
 import os
 import torch
 import torch.nn as nn
 ​
 ​
 def test001():
     current_path = os.path.dirname(__file__)
     img_path = os.path.join(current_path, "data", "彩色.png")
     # 转换为相对路径
     img_path = os.path.relpath(img_path)
 ​
     # 使用plt读取图片
     img = plt.imread(img_path)
     print(img.shape)
     # 转换为张量:HWC  ---> CHW  ---> NCHW  链式调用
     img = torch.tensor(img).permute(2, 0, 1).unsqueeze(0)
     # 创建卷积核  (501, 500, 4)
     conv = nn.Conv2d(
         in_channels=4,  # 输入通道
         out_channels=32,  # 输出通道
         kernel_size=(5, 3),  # 卷积核大小
         stride=1,  # 步长
         padding=0,  # 填充
         bias=True
     )
     # 使用卷积核对图像进行卷积操作  [9999]  [[[[]]]]
     out = conv(img)
     
     # 输出128个特征图
     conv2 = nn.Conv2d(
         in_channels=32,  # 输入通道
         out_channels=128,  # 输出通道
         kernel_size=(5, 5),  # 卷积核大小
         stride=1,  # 步长
         padding=0,  # 填充
         bias=True
     )
     out = conv2(out)
     print(out)
     # 把图像显示出来
     print(out.shape)
     plt.imshow(out[0][10].detach().numpy(), cmap='gray')
     plt.show()
 ​
 ​
 # 作为主模块执行
 if __name__ == "__main__":
     test001()
2.2.2 卷积计算底层实现

并不是水平和垂直方向的循环。

下图是卷积的基本运算方式:

卷积真正的计算过程如下图:

2.3 边缘填充

Padding

通过上面的卷积计算,我们发现最终的特征图比原始图像要小,如果想要保持图像大小不变, 可在原图周围添加padding来实现。

更重要的,边缘填充还更好的保护了图像边缘数据的特征。

2.4 步长Stride

按照步长为1来移动卷积核,计算特征图如下所示:

如果我们把 Stride 增大为2,也是可以提取特征图的,如下图所示:

stride太小:重复计算较多,计算量大,训练效率降低; stride太大:会造成信息遗漏,无法有效提炼数据背后的特征;

2.5 多通道卷积计算

首先我们需要认识下通道,做到颗粒度对齐~

2.5.1 数字图像的标识

我们知道图像在计算机眼中是一个矩阵

通道越多,可以表达的特征就越丰富~

2.5.2 具体计算实现

实际中的图像都是多个通道组成的,我们怎么计算卷积呢?

计算方法如下:

  1. 当输入有多个通道(Channel), 例如RGB三通道, 此时要求卷积核需要有相同的通道数。

  2. 卷积核通道与对应的输入图像通道进行卷积。

  3. 将每个通道的卷积结果按位相加得到最终的特征图。

如下图所示:

2.6 多卷积核卷积计算

实际对图像进行特征提取时, 我们需要使用多个卷积核进行特征提取。这个多个卷积核可以理解为从不同到的视角、不同的角度对图像特征进行提取。

那么, 当使用多个卷积核时, 应该怎么进行特征提取呢?

2.7 特征图大小

输出特征图的大小与以下参数息息相关:

  1. size: 卷积核/过滤器大小,一般会选择为奇数,比如有 1×1, 3×3, 5×5

  2. Padding: 零填充的方式

  3. Stride: 步长

那计算方法如下图所示:

  1. 输入图像大小: W x W

  2. 卷积核大小: F x F

  3. Stride: S

  4. Padding: P

  5. 输出图像大小: N x N

以下图为例:

  1. 图像大小: 5 x 5

  2. 卷积核大小: 3 x 3

  3. Stride: 1

  4. Padding: 1

  5. (5 - 3 + 2) / 1 + 1 = 5, 即得到的特征图大小为: 5 x 5

2.8 只卷一次?

2.9 卷积参数共享

数据是 32×32×3 的图像,用 10 个 5×5 的filter来进行卷积操作,所需的权重参数有多少个呢?

  • 5×5×3 = 75,表示每个卷积核只需要75个参数。

  • 10个不同的卷积核,就需要10*75 = 750个卷积核参数。

  • 如果还考虑偏置参数b,最终需要 750+10=760 个参数。

$$
全连接参数量: 10 * 28 * 28 *(32 * 32 * 3 + 1)
$$

2.10 局部特征提取

通过卷积操作,CNN具有局部感知性,能够捕捉输入数据的局部特征,这在处理图像等具有空间结构的数据时非常有用。

2.11 PyTorch卷积层 API

test01 函数使用一个多通道卷积核进行特征提取, test02 函数使用 3 个多通道卷积核进行特征提取:

 import torch
 import torch.nn as nn
 import matplotlib.pyplot as plt
 import os
 ​
 ​
 def showimg(img):
     plt.imshow(img)
     # 隐藏刻度
     plt.axis("off")
     plt.show()
 ​
 ​
 def test001():
     dir = os.path.dirname(__file__)
     img = plt.imread(os.path.join(dir, "彩色.png"))
     # 创建卷积核
     # in_channels:输入数据的通道数
     # out_channels:输出特征图数,和filter数一直
     conv = nn.Conv2d(in_channels=4, out_channels=1, kernel_size=3, stride=1, padding=1)
     # 注意:卷积层对输入的数据有形状要求 [batch, channel, height, width]
     # 需要进行形状转换  H, W, C -> C, H, W
     img = torch.tensor(img, dtype=torch.float).permute(2, 0, 1)
     print(img.shape)
     # 接着变形:CHW -> BCHW
     newimg = img.unsqueeze(0)
     print(newimg.shape)
     # 送入卷积核运算一下
     newimg = conv(newimg)
     print(newimg.shape)
 ​
     # 蒋NCHW->HWC
     newimg = newimg.squeeze(0).permute(1, 2, 0)
     showimg(newimg.detach().numpy())
 ​
 ​
 # 多卷积核
 def test002():
     dir = os.path.dirname(__file__)
     img = plt.imread(os.path.join(dir, "彩色.png"))
     # 定义一个多特征图输出的卷积核
     conv = nn.Conv2d(in_channels=4, out_channels=3, kernel_size=3, stride=1, padding=1)
 ​
     # 图形要进行变形处理
     img = torch.tensor(img).permute(2, 0, 1).unsqueeze(0)
     
     # 使用卷积核对图片进行卷积计算
     outimg = conv(img)
     print(outimg.shape)
     # 把图形形状转换回来以方便显示
     outimg = outimg.squeeze(0).permute(1, 2, 0)
     print(outimg.shape)
     # showimg(outimg)
     # 显示这些特征图
     for idx in range(outimg.shape[2]):
         showimg(outimg[:, :, idx].squeeze(-1).detach())
 ​
 ​
 if __name__ == "__main__":
     test002()
 ​

效果:


技术分享是一个相互学习的过程。关于本文的主题,如果你有不同的见解、发现了文中的错误,或者有任何不清楚的地方,都请毫不犹豫地在评论区留言。我很期待能和大家一起讨论,共同补充更多细节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值