一、CNN
视觉处理三大任务:分类、目标检测、图像分割
1. 概述
卷积神经网络是深度学习在计算机视觉领域的突破性成果。在计算机视觉领域, 往往我们输入的图像都很大,使用全连接网络的话,计算的代价较高。另外图像也很难保留原有的特征,导致图像处理的准确率不高。
卷积神经网络(Convolutional Neural Network,CNN)是一种专门用于处理具有网格状结构数据的深度学习模型。最初,CNN主要应用于计算机视觉任务,但它的成功启发了在其他领域应用,如自然语言处理等。
卷积神经网络(Convolutional Neural Network)是含有卷积层的神经网络. 卷积层的作用就是用来自动学习、提取图像的特征。
CNN网络主要有三部分构成:卷积层、池化层和全连接层构成,其中卷积层负责提取图像中的局部特征;池化层用来大幅降低运算量并特征增强;全连接层类似神经网络的部分,用来输出想要的结果。
1.1 使用场景
1.2 与传统网络的区别
1.3 全连接的局限性
全连接神经网络并不太适合处理图像数据...
1.3.1 参数量巨大
y = W T × x + b y = W^T \times x + b y=WT×x+b
全连接结构计算量非常大,假设我们有1000×1000的输入,如果隐藏层也是1000×1000大小的神经元,由于神经元和图像每一个像素连接,则参数量会达到惊人的1000×1000×1000×1000,仅仅一层网络就已经有 1 0 12 10^{12} 1012个参数。
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 卷积计算过程
卷积的过程是将卷积核在图像上进行滑动计算,每次滑动到一个新的位置时,卷积核和图像进行点对点的计算,并将其求和得到一个新的值,然后将这个新的值加入到特征图中,最终得到一个新的特征图。
- input 表示输入的图像
- filter 表示卷积核, 也叫做滤波器
- input 经过 filter 的得到输出为最右侧的图像,该图叫做特征图
那么, 它是如何进行计算的呢?卷积运算本质上就是在滤波器和输入数据的局部区域间做点积。
左上角的点计算方法:
按照上面的计算方法可以得到最终的特征图为:
卷积的重要性在于它可以将图像中的特征与卷积核进行卷积操作,从而提取出图像中的特征。
可以通过不断调整卷积核的大小、卷积核的值和卷积操作的步长,可以提取出不同尺度和位置的特征。
python
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 -> NCHW
newimg = img.unsqueeze(0)
print(newimg.shape)
# 送入卷积核运算一下
newimg = conv(newimg)
print(newimg.shape)
# 蒋BCHW->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()
2.2.2 卷积计算底层实现
并不是水平和垂直方向的循环。
下图是卷积的基本运算方式:
卷积真正的计算过程如下图:
2.3 边缘填充
Padding
通过上面的卷积计算,我们发现最终的特征图比原始图像要小,如果想要保持图像大小不变, 可在原图周围添加padding来实现。
更重要的,边缘填充还更好的保护了图像边缘数据的特征。
2.4 步长Stride
按照步长为1来移动卷积核,计算特征图如下所示:
如果我们把 Stride 增大为2,也是可以提取特征图的,如下图所示:
stride太小:重复计算较多,计算量大,训练效率降低;
stride太大:会造成信息遗漏,无法有效提炼数据背后的特征;
2.5 多通道卷积计算
首先我们需要认识下通道,做到颗粒度对齐~
2.5.1 数字图像的标识
我们知道图像在计算机眼中是一个矩阵
通道越多,可以表达的特征就越丰富~
2.5.2 具体计算实现
实际中的图像都是多个通道组成的,我们怎么计算卷积呢?
计算方法如下:
- 当输入有多个通道(Channel), 例如RGB三通道, 此时要求卷积核需要有相同的通道数。
- 卷积核通道与对应的输入图像通道进行卷积。
- 将每个通道的卷积结果按位相加得到最终的特征图。
如下图所示:
2.6 多卷积核卷积计算
实际对图像进行特征提取时, 我们需要使用多个卷积核进行特征提取。这个多个卷积核可以理解为从不同到的视角、不同的角度对图像特征进行提取。
那么, 当使用多个卷积核时, 应该怎么进行特征提取呢?
2.7 特征图大小
输出特征图的大小与以下参数息息相关:
- size: 卷积核/过滤器大小,一般会选择为奇数,比如有 1×1, 3×3, 5×5
- Padding: 零填充的方式
- Stride: 步长
那计算方法如下图所示:
-
输入图像大小: W x W
-
卷积核大小: F x F
-
Stride: S
-
Padding: P
-
输出图像大小: N x N
以下图为例:
- 图像大小: 5 x 5
- 卷积核大小: 3 x 3
- Stride: 1
- Padding: 1
- (5 - 3 + 2) / 1 + 1 = 5, 即得到的特征图大小为: 5 x 5
2.8 只卷一次?
2.9 卷积参数共享
数据是 32 × 32 × 3 32×32×3 32×32×3 的图像,用 10 10 10 个 5 × 5 × 3 5×5×3 5×5×3 的filter来进行卷积操作,所需的权重参数有多少个呢?
- 5 × 5 × 3 = 75 5×5×3 = 75 5×5×3=75,表示每个卷积核只需要 75 75 75个参数。
- 10个不同的卷积核,就需要 10 ∗ 75 = 750 10*75 = 750 10∗75=750个卷积核参数。
- 如果还考虑偏置参数 b b b,最终需要 750 + 10 = 760 750+10=760 750+10=760 个参数。
2.10 局部特征提取
通过卷积操作,CNN具有局部感知性,能够捕捉输入数据的局部特征,这在处理图像等具有空间结构的数据时非常有用。
2.11 PyTorch卷积层 API
test01 函数使用一个多通道卷积核进行特征提取, test02 函数使用 3 个多通道卷积核进行特征提取:
python
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)
# 蒋BCHW->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()
效果:
2.12 卷积层实验
2.12.1 基本原理
在前面的章节中我们了解了卷积的过程,明白了卷积过程就是使用一个小的卷积核与输入特征矩阵进行滑动卷积的过程。
前面的章节中为了能更好的说清楚卷积的过程,其输入特征矩阵都是单通道的,根据"计算机眼中的图像"章节,知道单通道是灰度图或者二值化图,但是实际上识别图像大部分都是彩色图,也就意味着不是一个通道的特征输入。
所以,卷积的过程中大部分都是多通道的卷积,并且在卷积完之后还会加上偏置项。
2.12.1.1 特征输入
在"特征输入"组件中,提供了一个3x3的三通道输入特征矩阵,并将其三个通道的内容都展示了出来。
也就意味着这个输入矩阵是一个3x3大小的,并且有三个通道。可以看成是三张3x3的A4纸"啪"一下,粘在一块了。
2.12.1.2 卷积核
有了输入特征矩阵后,就需要定义卷积核了。
在"卷积核"组件中,为了简化计算,定义了卷积核的大小为2x2(实际上几乎不会有2x2的卷积核), 通过拖动滑动条可以修改卷积核的个数。
并且为了能够对一个三通道的输入特征矩阵进行卷积,这里的每一个卷积核也是三通道的卷积核。
|
|
|
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| 卷积核个数为1 | 卷积核个数为2 |
2.12.1.3 卷积过程显示
在"卷积过程显示"组件中,固定了Padding方式为VALID和步长为1。
在多通道卷积过程中,输出特征矩阵是由每个通道的卷积核与对应通道的输入特征矩阵在对应位置进行卷积,然后将多个通道的卷积结果相加的结果。
以输出特征矩阵的左上角"1"为例,其值是由第一个通道的卷积核与第一个通道的输入特征矩阵的左上角进行卷积加上第二个通道的卷积核与第二个通道的输入特征矩阵的左上角进行卷积加上第三个通道的卷积核与第三个通道的输入特征矩阵的左上角进行卷积,最后得到的卷积结果相加得到输出特征矩阵的左上角值为"1",其他的以此类推。
在得到输出特征矩阵后,偏置矩阵就会与输出特征矩阵相加,得到本次多通道卷积的最终结果。
由此我们得到两个结论:
- 输入特征的通道数决定了卷积核的通道数(卷积核通道个数=输入特征通道个数)。
- 卷积核的个数决定了输出特征矩阵的通道数与偏置矩阵的通道数(卷积核个数=输出特征通道数=偏置矩阵通道数)。
2.12.1.2 步骤
需要默认打开"人工智能虚拟仿真"和"人工智能虚拟仿真本地服务管理平台"。
(可选)使用人工智能虚拟仿真本地服务管理平台启动服务。
服务启动一次之后就不需要再次启动了。
单击多通道卷积与偏置实验进入
如果之前进入了某个实验,可以在实验面板的右上角点击"返回"回到主页即可。
拖出组件并连线
根据实验原理,将我们的逻辑抽象成组件之后,连线如下图所示。
验证
点击验证,如显示校验成功,即代表逻辑无误,验证按钮与校验成功界面如下图所示。
运行
点击运行,可以实现功能运行,并显示结果输出,如下图所示。
代码生成
点击界面左下角的生成代码按钮,可生成本实验的Python代码,生成代码按钮如下图所示。
点击后可以查看该实验代码,代码会根据界面所选参数进行适配,点击复制可以将其复制,并粘贴在其它地方。
这里我们可以粘贴到软件的Jupyter中运行,"人工智能虚拟仿真本地服务管理平台"打开Jupyter,第一次打开Jupyter需要点击"打开CMD命令",打开Jupyter后无需再次打开CMD,如下图所示。
在弹出的CMD命令行中,输入python -m jupyterlab --notebook-dir .\\learn,点击回车,浏览器会自动跳转打开Jupyter,如下图所示。
如果没有自动跳转和打开浏览器,请输入下图中圈出的内容,每个人的该内容不一致,请复制自己的 弹出的。
将代码输入到Jupyter中,点击运行可以查看结果。
2.12.1.3 实验现象
实验结果为:
2.13 卷积作业
- 基本概念理解题 :
- 什么是多通道卷积?在处理RGB图像时,如何体现多通道卷积的特性?
- 计算过程描述题 :
- 假设你有一个3通道(如RGB)的输入图像,其尺寸为64x64,应用一个大小为3x3、深度也为3的卷积核进行卷积操作,请描述这个过程。
- 参数数量计算题 :
- 请计算一个大小为5x5、深度为3的卷积核应用于具有10个通道的输入时,需要多少个可学习参数。如果有偏置项,总参数量是多少?
- 偏置项含义题 :
- 解释卷积层中的偏置项是什么,并讨论在神经网络中引入偏置项的好处。
- 设计选择题 :
- 在实际应用中,为什么有些卷积层会选择不包含偏置项?列举并解释可能的情况。
2.14 知识点扩展
-
深度理解题:
- 在多通道卷积过程中,权重共享如何在不同通道间实现特征学习的协同作用?请结合实际应用案例进行说明。
-
优化策略设计题:
- 当处理高维输入数据时(例如视频帧序列或高光谱图像),针对多个通道上的卷积操作,你可能会采取哪些优化策略以减少计算复杂度并提高模型性能?
-
数学表达与梯度传播分析题:
- 请推导一个多通道卷积层(包括多个滤波器和每个滤波器对应的偏置项)前向传播过程中的矩阵运算表达式,并解释反向传播时这些参数(权重和偏置)的梯度是如何计算的。
-
架构创新思考题:
- 现代深度学习框架中存在将通道注意力机制融入到卷积层的设计,例如SENet中的Squeeze-and-Excitation模块。请描述这一机制如何影响卷积层对多通道信息的处理,并讨论其优势。
-
跨通道交互研究题:
- 举例说明一种或多通道特征融合的方法,比如深度可分离卷积中的点wise卷积或者跨通道卷积,并阐述它们如何促进不同通道间的特征交互。
-
实践问题解决题:
- 假设你在训练一个用于图像分类的深度卷积神经网络时,发现由于输入图像的多通道特性导致模型过拟合,请提出至少两种通过调整卷积层结构或配置来缓解过拟合的技术方案,并讨论其原理。
-
偏置项作用与权衡题:
- 讨论卷积层中偏置项的作用以及它可能引入的问题(如模型的平移不变性)。在某些场景下为何会选择去除偏置项?如果有,会采用什么替代策略来补偿去除偏置带来的潜在损失?
-
技术对比与选择题:
- 比较全局平均池化、全局最大池化以及具有偏置项的1x1卷积在获取通道级统计特征方面的异同,并根据特定任务需求阐述何时选择哪种方法更为合适。