卷积神经网络CNN——卷积层、池化层、全连接层
卷积神经网络CNN——卷积层、池化层、全连接层
卷积神经网络(CNN)是深度学习中一种非常重要的神经网络结构,特别适用于处理图像数据。本文将详细介绍CNN的三个主要组成部分:卷积层、池化层和全连接层,并通过一个具体的案例来展示如何使用TensorFlow构建一个简单的CNN模型。
1. CNN网络的构成
CNN网络受人类视觉系统的启发,人类的视觉原理:从原始信号摄入开始(瞳孔摄入像素 Pixels),接着做初步处理(大脑皮层某些细胞发现边缘和方向),然后抽象(大脑判定,眼前的物体的形状,是圆形的),然后进一步抽象(大脑进一步判定该物体是只人脸)。下面是人脑进行人脸识别的一个示例:
CNN网络主要有三部分构成:卷积层、池化层和全连接层构成。其中卷积层是负责提取图像中的局部特征;池化层是用来答复降低参数量级(降维);全连接层类似人工神经网络的部分,用来输出想要的结果。
层 | 作用 |
---|---|
卷积层 | 提取图像特征 |
池化层 | 降维、防止过拟合 |
全连接层 | 输出结果 |
整个CNN网络结果如下图所示:
2. 卷积层
卷积层是卷积神经网络中的核心模块,卷积层的目的是提取输入特征图的特征,如下图所示,卷积核可以提取图像中的边缘信息。
2.1 卷积的计算方法
卷积运算本质上就是在滤波器和输入数据的局部区域做点积。(我们不需要关注这些数据是怎么来的,计算机会自动提取图像的特征)
左上角的点计算的方法为:
同理可以计算其他各点,得到最终的卷积结果:
我们先粗略的讲一下下面名词的含义。
2.2 padding
在上述卷积过程中,特征图比原始图减小了很多,我们可以在原图像的周围进行padding,来保证在卷积过程中特征图大小不变。
如上图,我们在输入图像的一周设置了一个padding(=1),一般都是置为0,后面会详细讲解padding。
2.3 stride
stride表示的就是卷积核一次移动几格的问题。
例如,我们按照步长为1来移动卷积核,计算特征图如下所示:
如果我们把stride增大,设为2,如下图:
2.4 多通道卷积
实际中的图像都是多个通道组成的,我们怎么计算卷积呢?
计算方法如下:当输入有多个通道(channel)时,比如说RGB图片有三个通道,卷积核需要有相同的通道(channel)数,每个卷积核channeyu输入图像对应的channel进行卷积,将每个channel的卷积结果按位相加得到最终的Feature Map(特征图)
2.5 多卷积核卷积
如果有多个卷积核时,每个卷积核学习到不同的特征,对应包含多个channel的Feature Map,例如下面有两个filter(卷积核),所以output有两个通道(channel)。
2.6 特征图大小
最终输出的特征图的大小与一下参数息息相关。
- size:卷积核/过滤器的大小,一般使用奇数,比如说 1 * 1,3 * 3,5 * 5
- padding:零填充的方式
- stride:步长
计算方式如下:
比如我们输入图像的大小是:H1W1D1,卷积核(filter)的数量是K,卷积核的大小是F,步长strides是S,零填充(padding)大小是P。我们输出的特征大小是:H2W2D2
那么:
示例:输入特征图为5x5,卷积核为3x3,外加padding 为1,则其输出尺寸为
如下图所示:
在tf.keras中卷积核的实现:
tf.keras.layers.Conv2D(
filters, kernel_size, strides=(1,1),
padding='vaild', activation=None
)
参数解释如下:
参数 | 描述 |
---|---|
filters | 卷积核(过滤器)的数量,对应输出特征图的通道数 |
kernel_size | 卷积核(过滤器)的大小 |
strides | 步长 |
padding | 填充大小,有两个重要参数;①vaild:对输入周围不进行padding②same:padding后使输入特征图和输出特征图形状相同 |
activation | 激活函数 |
3. 池化层(Pooling)
池化层的目的是为了降低后序网络的输入维度,缩减模型大小,提高计算速度,并且提高Feature Map的鲁棒性,防止过拟合。他主要对卷积层学习到的特征图进行下采样处理,主要有两种。
Q:什么是上采样和下采样?
A:①在卷积神经网络中,由于输入图像通过卷积神经网络(CNN)提取特征后,输出的尺寸往往会变小,而有时我们需要将图像恢复到原来的尺寸以便进行进一步的计算(如图像的语义分割),这个使图像由小分辨率映射到大分辨率的操作,叫做上采样。
②在卷积神经网络(Convolutional Neural Networks, CNNs)中,下采样通常是通过池化层(Pooling Layers)来实现的,例如最大池化(Max Pooling)或平均池化(Average Pooling)。这些池化操作通过对图像中相邻像素区域进行聚合来减小特征图的空间尺寸,从而减少网络中的参数数量,提高计算效率,并且有助于防止过拟合。
3.1 最大池化
Max Pooling:取窗⼝内的最⼤值作为输出,这种⽅式使⽤较⼴泛。
在tf.keras中实现方法为:
tf.keras.layers.MaxPool2D(
pool_size=(2, 2), strides=None, padding='vaild'
)
参数解释如下:
参数 | 描述 |
---|---|
pool_size= | 池化窗口的大小 |
strides | 窗口移动的步长,默认为1 |
padding | 是否进行填充,默认不进行填充 |
3.2 平均池化
Avg Pooling:取窗⼝内的所有值的均值作为输出
在tf.keras中实现方法为:
tf.keras.layers.AveragePooling2D(
pool_size=(2, 2), strides=None, padding='vaild'
)
4. 全连接层
全连接层位于CNN网络的末端,经过卷积层的特征提取与池化层的降维后,将特征图转换成一维向量送入到全连接层中进行分类或回归的操作。
在tf.keras中全连接层使用tf.keras.dense实现。
5. 卷积神经网络的搭建
我们构建卷积神经网络在mnist数据集上进行处理,如下图所示:LeNet-5是一个较简单的卷积神经网络, 输入的二维图像,先经过两次卷积层,池化层,再经过全连接层,最后使用softmax分类作为输出层。
我们先导入相关工具包:
import tensorflow as tf
# 导入数据集
from tensorflow.keras.datasets import mnist
5.1 数据加载
与全连接神经网络的案例一致,首先加载数据集:
# 数据加载
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
5.2 数据处理
卷积神经网络的输入要求是:N H W C ,分别是图片数量,图片高度,图片宽度和图片的通道,本里中因为是灰度图,通道为1。
# 数据处理
# 维度调整
# 训练集
train_images = tf.reshape(train_images, (train_images.shape[0], train_images.shape[1], train_images.shape[2], 1))
# (60000, 28, 28) -> (60000, 28, 28, 1)
# 测试集
test_images = tf.reshape(test_images, (test_images.shape[0], test_images.shape[1], test_images.shape[2], 1))
# (10000, 28, 28) -> (10000, 28, 28, 1)
5.3 模型搭建
Lenet-5模型输入的二维图像,先经过两次卷积层,池化层,再经过全连接层,最后使用softmax分类作为输出层,模型构建如下:
# 模型构建
net = tf.keras.models.Sequential([
# 卷积层:6个5*5的卷积核,激活是sigmoid
tf.keras.layers.Conv2D(filters=6, kernel_size=5, activation='sigmoid'),
# 最大池化
tf.keras.layers.MaxPool2D(pool_size=2, strides=2),
# 卷积层:16个5*5的卷积核,激活是sigmoid
tf.keras.layers.Conv2D(filters=16, kernel_size=5, activation='sigmoid'),
# 最大池化
tf.keras.layers.MaxPool2D(pool_size=2, strides=2),
# 维度调整为1维数据
tf.keras.layers.Flatten(),
# 全卷积层,激活sigmoid
tf.keras.layers.Dense(120, activation='sigmoid'),
# 全卷积层,激活sigmoid
tf.keras.layers.Dense(84, activation='sigmoid'),
# 全卷积层,激活softmax
tf.keras.layers.Dense(10, activation='softmax')
])
5.4 模型编译
设置优化器和损失函数:
# 模型编译,优化器,损失函数,评价指标
net.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.9),
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=['accuracy']
)
5.5 模型训练
模型训练:
# 模型训练
net.fit(train_images, train_labels, epochs=5, batch_size=128, verbose=1)
5.6 模型评估
# 模型评估
net.evaluate(test_images, test_labels, verbose=1)