云计算百科
云计算领域专业知识百科平台

卷积神经网络CNN

1 图像基础知识

1.1 图像基本概念

        图像是人类视觉的基础,是自然景物的客观反映,是人类认识世界和人类本身的重要源泉。“图”是物体反射或透射光的分布,“像“是人的视觉系统所接受的图在人脑中所形成的印象或认识,照片、绘画、剪贴画、地图、书法作品、手写汉字、传真、卫星云图、影视画面、X光片、脑电图、心电图等都是图像。

1.2 图像类型

图像类型通道数像素值范围主要特点常见用途
二值图像 1通道 0 或 1 每个像素只有黑与白两种值 形态学操作、二值化、轮廓检测
灰度图像 1通道 0 到 255 每个像素表示灰度(亮度) 图像预处理、物体检测、人脸识别
索引图像 1通道 0 到 255(索引) 像素值为颜色表的索引,颜色表决定实际颜色 存储压缩、较少颜色的图像表示
RGB图像 3通道(R、G、B) 0 到 255 每个像素由红、绿、蓝三个通道组成 普通彩色图像显示、图像处理与分析

简单的讲:图像是由像素点组成的,每个像素点的取值范围为: [0, 255] 。像素值越接近于0,颜色越暗,接近于黑色;像素值越接近于255,颜色越亮,接近于白色。

在深度学习中,我们使用的图像大多是彩色图,彩色图由RGB3个通道组成

1.3 图像加载

import numpy as np
import matplotlib.pyplot as plt

# 像素值的理解
def test01():
# 全0数组是黑色的图像
# H, W, C -> 高, 宽, 通道
img = np.zeros(shape=[200, 200, 3])
# 展示图像
plt.imshow(img)
# 对坐标轴进行设置
# off:关闭坐标轴
plt.axis("off")
plt.show()

# 全255数组是白色的图像
img = np.full(shape=[200, 200, 3], fill_value=255)
# 展示图像
plt.imshow(img)
plt.show()

# 图像的加载
def test02():
# 读取图像
img = plt.imread("data/img.jpg")
# 保存图像
plt.imsave("data/img1.jpg", img)
# 打印图像形状 高,宽,通道
print("图像的形状(H, W, C):\\n", img.shape)
# 展示图像
plt.imshow(img)
plt.axis("off")
plt.show()

if __name__ == '__main__':
test01()
test02()

2 卷积神经网络(CNN)概述

2.1 什么是卷积神经网络

        卷积神经网络是深度学习在计算机视觉领域的突破性成果,专门用于处理图像、视频、语音等数据的神经网络

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

CNN网络主要由三部分构成:卷积层、池化层和全连接层构成:

(1)卷积层负责提取图像中的局部特征

(2)池化层用来大幅降低参数量级(降维)

(3)全连接层类似人工神经网络的部分,用来输出想要的结果

2.2 卷积神经网络应用

图像分类:最常见的应用,例如识别图片中的物体类别

目标检测:检测图像中物体的位置和类别

图像分割:将图像分成多个区域,用于语义分割

人脸识别:识别图像中的人脸

医学图像分析:用于检测医学图像中的异常(如癌症检测、骨折检测等)

自动驾驶:用于识别交通标志、车辆、行人

2.3 CNN中的经典算法/网络架构

LeNet-5:作为最早的CNN架构之一,证明了CNN在图像识别任务上的有效性,为后续的CNN发展奠定了基础

  • 卷积层: 提取图像的边缘、角点等基本特征

  • 池化层 (子采样层): 降低特征图的维度,减少计算量,并提高模型对输入图像微小变化的鲁棒性

  • 全连接层: 将卷积层和池化层提取的特征进行组合,用于最终的分类

AlexNet:显著提升了ImageNet图像分类的准确率,证明了深度学习在计算机视觉领域的潜力,并推动了深度学习的快速发展

  • 卷积层: 使用更大的卷积核和更多的卷积核,提取更丰富的图像特征

  • ReLU激活函数: 加速训练过程,并提高模型的性能

  • 最大池化层: 降低特征图的维度

  • Dropout层: 防止过拟合

  • 全连接层: 用于最终的分类

VGGNet:探索了网络深度对性能的影响,证明了更深的网络可以提取更抽象和更具表达力的特征

  • 卷积层: 使用更小的卷积核 (3×3),并堆叠多个卷积层,增加了网络的深度,提取更复杂的特征

  • 最大池化层: 降低特征图的维度

  • 全连接层: 用于最终的分类

GoogLeNet (Inception):提出了 Inception 模块,在提高性能的同时减少了计算量,为后续的网络架构设计提供了新的思路

  • Inception 模块: 并行使用不同大小的卷积核和池化操作,然后将它们的输出连接起来,增加了网络的宽度,提高了网络的效率

ResNet:解决了深度网络训练困难的问题,使得可以训练更深的网络,从而显著提高了模型的性能

  • 残差块 (Residual Block): 引入跳跃连接 (Shortcut Connection),允许梯度直接反向传播到浅层,解决了深度网络的梯度消失问题,使得训练非常深的网络成为可能

DenseNet:

  • 密集块 (Dense Block): 将每一层都与之前的所有层连接,特征重用更加充分,进一步提高了网络的性能和参数效率

  • DenseNet通过密集连接(Dense Connectivity)在网络中各层之间建立了直接的连接,即每一层都接收前面所有层的输出作为输入。这种设计增强了特征传递和梯度流动,避免了梯度消失问题,并提高了信息的利用率

2.4 卷积层

        卷积层(Convolutional Layer)通过卷积操作提取输入数据中的特征(例如图像中的边缘、纹理、形状等)。

        卷积层利用卷积核(滤波器)对输入进行处理,从而生成特征图(feature map),并且每个卷积层能够提取不同层次的特征,从低级特征(如边缘)到高级特征(如物体的形状)。

卷积层的主要作用如下:

  • 特征提取:卷积层的主要作用是从输入图像中提取低级特征(如边缘、角点、纹理等)。通过多个卷积层的堆叠,网络能够逐渐从低级特征到高级特征(如物体的形状、区域等)进行学习。

  • 权重共享:在卷积层中,同一个卷积核在整个输入图像上共享权重,这使得卷积层的参数数量大大减少,减少了计算量并提高了训练效率。

  • 局部连接:卷积层中的每个神经元仅与输入图像的一个小局部区域相连,这称为局部感受野,这种局部连接方式更符合图像的空间结构,有助于捕捉图像中的局部特征。

  • 空间不变性:由于卷积操作是局部的并且采用权重共享,卷积层在处理图像时具有平移不变性。也就是说,不论物体出现在图像的哪个位置,卷积层都能有效地检测到这些物体的特征。

2.5 Padding(填充)

通过上面的卷积计算过程,最终的特征图比原始图像小很多,如果想要保持经过卷积后的图像大小不变, 可以在原图周围添加 Padding 来实现。

Padding(填充)操作是一种用于==在输入特征图的边界周围添加额外像素(通常是零)==。

Padding的主要作用:

  • 保持空间维度:如果不使用 padding,每次卷积操作后,特征图的尺寸都会缩小。多次卷积后,特征图会变得非常小,可能会丢失重要的边缘信息。Padding可以帮助维持输出特征图的尺寸与输入相同或接近相同。

  • 保留边缘信息:图像边缘的像素在卷积过程中参与的计算次数较少,这意味着边缘信息在特征提取过程中容易丢失。Padding通过在边缘添加额外的像素,增加了边缘像素的参与度,从而更好地保留了边缘信息。

  • 提高性能:Padding有助于避免由于特征图尺寸快速缩小而导致的信息丢失,从而提高模型的性能,尤其是在处理较小的图像或需要进行多层卷积时。

Padding的类型:

  • Valid Padding (No Padding): 不进行任何填充。卷积核只在输入图像的有效区域内滑动。输出尺寸会缩小。

  • Same Padding: 添加足够的填充,使得输出特征图的尺寸与输入相同。

  • Full Padding: 尽可能多地添加填充,使得卷积核的每个元素都至少在输入图像上滑动一次。输出尺寸会增大。

Padding的选择:取决于具体的应用场景和网络架构

  • Valid Padding: 适用于不需要保持输出尺寸的场景,或者输入图像足够大,边缘信息丢失不重要的情况。

  • Same Padding: 广泛应用于各种CNN架构中,因为它可以保持特征图的尺寸,方便网络设计和计算。

  • Full Padding: 较少使用,因为它会增加计算量,并且可能会在边缘引入一些伪影。

2.5 Stride(步长)

        Stride(步长)指的是卷积核在图像上滑动时的步伐大小,即每次卷积时卷积核在图像中向右(或向下)移动的像素数。步长直接影响卷积操作后输出特征图的尺寸,以及计算量和模型的特征提取能力。

2.6 特征图大小

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

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.7 PyTorch卷积层API

conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)

"""
参数说明:
in_channels: 输入通道数,RGB图片一般是3
out_channels: 输出通道,也可以理解为卷积核kernel的数量
kernel_size:卷积核的高和宽设置,一般为3,5,7…
stride:卷积核移动的步长
整数stride:表示在所有维度上使用相同的步长 stride=2 表示在水平和垂直方向上每次移动2个像素
元组stride: 允许在不同维度上设置不同的步长 stride=(2, 1) 表示在水平方向上步长为2,在垂直方向上步长为1
padding:在四周加入padding的数量,默认补0
padding=0:不进行填充。
padding=1:在每个维度上填充 1 个像素(常用于保持输出尺寸与输入相同 padding=输入形状大小-输出形状大小)。
padding='same'(从 PyTorch 1.9+ 开始支持):让输出特征图的尺寸与输入保持一致。PyTorch会自动计算需要的填充量。stride必须等于1,不支持跨行,因为计算padding时可能出现小数
padding=kernel_size-1:Full Padding 完全填充
"""

2.8 多通道多卷积核卷积

import torch
import torch.nn as nn
import matplotlib.pyplot as plt

# 对图像进行卷积
# 1 读取图像 显示图像
# 2 定义卷积层
# 3 变换数据形状 1-转成tensor 2-通道要求[C H W] 3-批次数要求 [batch, C, H, W]
# 4 给卷积层喂数据 [1, 3, 640, 640] —> [1, 4, 319, 319])
# (H-F+2p)/s +1 = (640-3+0)/2 + 1 = 319.5向下取整319
def test01():

# 1 读取图像
img = plt.imread('./data/img.jpg')
print('img.shape', img.shape)

plt.imshow(img)
plt.show()

# 2 定义卷积层
myconv2d = nn.Conv2d(in_channels=3, out_channels=4, kernel_size=3, stride=2, padding=0)
print('myconv2d—>', myconv2d)

# 3 变换数据形状
# ①转换成tensor
# ②通道要求[C, H, W], 默认[H, W, C]
# ③批次数要求[batch, C, H, W],多少个图像(一个图像是三维数组,四维有多少个三维就是多少个图像)
# [0, 1, 2] –> [2, 0, 1]
img2 = torch.tensor(img).permute(2, 0, 1)
print('img2.shape—>', img2.shape)
# 图像数为1,变为4维张量
img3 = img2.unsqueeze(0)
print('img3.shape—>', img3.shape)

# 4 给卷积层喂数据 [1, 3, 640, 640] —> [1, 4, 319, 319])
# (H-F+2p)/s + 1 = (640-3+0)/2 + 1 = 319.5向下取整319
img4 = myconv2d(img3.type(torch.float32))
print('img4–>', img4.shape)

if __name__ == '__main__':
test01()

3 池化层

池化层(Pooling Layer)是用于降低输入数据的空间维度(例如图像的高度和宽度),从而减少计算量、减少内存消耗,并提高模型的鲁棒性。

池化层通常位于卷积层之后,它通过对卷积层输出的特征图进行下采样,保留最重要的特征信息,同时丢弃一些不重要的细节。

池化层的主要作用如下:

– **降维和计算量减少**:池化层通过减少特征图的尺寸,从而降低了计算量,特别是在多层网络中,随着层数的增加,池化能够显著减少计算资源的消耗。

– **提高鲁棒性**:池化操作可以使得特征对小的变换、平移和旋转变得更加不敏感。这样,模型在面对噪声或图像的轻微变化时,依然能够稳定工作。

– **防止过拟合**:通过池化减少了特征图的大小,减少了模型的复杂度,从而有助于防止过拟合,尤其是在较小的数据集上。

– **抽象特征**:通过池化层的操作,可以提取更为抽象和高层次的特征,使得网络能够学习到更具泛化能力的表示。

3.1 池化层计算

最大池化(Max Pooling) :通过池化窗口进行最大池化,**取窗口中的最大值作为输出**

平均池化(Avg Pooling) :**取窗口内的所有值的均值作为输出**

3.2 多通道池化计算

        在处理多通道输入数据时,池化层对每个输入通道分别池化,而不是像卷积层那样将各个通道的输入相加。这意味着==池化层的输出和输入的通道数是相等。==

**池化只在宽高维度上池化**,**在通道上是不发生池化**(池化前后,多少个通道还是多少个通道)

3.3 PyTorch池化层API

在PyTorch中进行池化的API是:

# 最大池化
nn.MaxPool2d(kernel_size=2, stride=2, padding=1)
# 平均池化
nn.AvgPool2d(kernel_size=2, stride=1, padding=0)
"""
参数说明:
kernel_size:核的高和宽设置,一般为3,5,7…
stride:核移动的步长
padding:在四周加入padding的数量,默认补0
"""

#单通道池化
import torch
import torch.nn as nn

# 1. 单通道池化
# 定义输入数据 [1,3,3]
inputs = torch.tensor([[[0, 1, 2], [3, 4, 5], [6, 7, 8]]], dtype=torch.float)
# 修改stride,padding观察效果
# 1. 最大池化
pooling = nn.MaxPool2d(kernel_size=2, stride=1, padding=0)
output = pooling(inputs)
print("最大池化:\\n", output)
# 2. 平均池化
pooling = nn.AvgPool2d(kernel_size=2, stride=1, padding=0)
output = pooling(inputs)
print("平均池化:\\n", output)

#多通道池化
# 2. 多通道池化
# 定义输入数据 [3,3,3]
inputs = torch.tensor([[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
[[10, 20, 30], [40, 50, 60], [70, 80, 90]],
[[11, 22, 33], [44, 55, 66], [77, 88, 99]]], dtype=torch.float)
# 最大池化
pooling = nn.MaxPool2d(kernel_size=2, stride=1, padding=0)
output = pooling(inputs)
print("多通道池化:\\n", output)

赞(0)
未经允许不得转载:网硕互联帮助中心 » 卷积神经网络CNN
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!