Convolutional Neural Networks (CNN): A Beginner’s Guide
作者:禅与计算机程序设计艺术
1.简介
什么是卷积神经网络(Convolutional Neural Network)?它在计算机视觉、自然语言处理等领域有何应用?卷积神经网络(Convolutional Neural Network,CNN),也被称为卷积网络或时域卷积网络,是一种深度学习模型,特别适用于处理图像、视频等结构化数据。该模型能够通过局部感受野扫描输入数据,自动提取图像特征,并利用这些特征进行分类或回归任务。其主要优势在于能够有效识别目标类别,同时还能提取图像的空间结构信息,这使其在物体边界检测、场景分割、图像配准等方面表现出色。因此,CNN被视为机器学习领域的重要研究方向之一。本文将深入探讨CNN的基本概念、工作原理及其在图像处理中的实际应用。
2.基本概念、术语及说明
2.1 模型结构
基于卷积神经网络(CNN)的结构特点,其由一系列关键层按顺序构成,具体包括输入层、卷积层、池化层、全连接层和输出层等。如图所示,该网络架构设计科学合理,各层功能分工明确。其中,输入层的主要作用是接收原始输入数据,包括图像、视频和文本等多种形式的信息;卷积层通过卷积运算,能够有效提取图像中的局部特征;池化层则对卷积层输出的特征进行空间降维处理,从而降低计算复杂度;全连接层则将网络中所有特征进行深度结合,实现目标的分类或回归任务。
2.2 卷积层
卷积层是CNN中最基本的层级结构,通过卷积核对输入图像进行特征提取,获取图像的局部特征描述。每个卷积层通常由多个卷积核组成,每个卷积核对应输入图像中的一个小区域,对该区域的像素进行加权求和,从而生成特定的特征输出。在相同输入条件下,不同卷积核对同一位置像素的特征提取可能存在差异,这体现了特征提取过程的多样性。通过参数训练,卷积层能够不断更新卷积核的参数配置,从而提升特征提取的准确性。
2.3 池化层
池化层作为卷积神经网络中的一种关键组件,具有显著的功能。其主要功能是进一步缩小输出特征图的空间尺寸,同时增强模型的泛化能力,提升整体鲁棒性。通常,池化层采用最大池化或平均池化策略,通过取窗口内像素的最大值或平均值来生成池化特征。通过池化操作,网络能够更专注于局部特征的提取,从而有效避免了基于全局图像信息导致的过拟合现象。
2.4 正向传播
正向传播即为在输入数据输入后,网络依次经过卷积层、池化层和全连接层,输出结果即为网络的最终计算结果。
2.5 反向传播
反向传播即为基于网络误差对权重参数影响的梯度下降方法。通过反向传播误差梯度,调整网络参数以实现准确标签预测。
2.6 超参数
模型超参数是调节模型复杂度和训练效率的关键变量,例如卷积核的数量、大小、步长以及学习率等。在模型训练之前,需要合理设置这些参数,否则可能会导致模型出现欠拟合或过拟合的问题。
2.7 激活函数
在深度学习领域,激活函数(activation function)是一种非线性映射,用于模拟非线性关系,从而提升网络的非线性处理能力。通过激活函数,神经网络能够模拟复杂的非线性系统,进而增强其表达性能。在实际应用中,常用的激活函数包括sigmoid函数、双曲正切函数、修正线性单元函数以及softmax函数等。
2.8 损失函数
损失函数(loss function)用于衡量模型输出与真实值之间的差异程度,是评估模型预测准确性的重要指标。常见的损失函数包括平方损失、交叉熵以及L1/L2范数损失等。
2.9 优化器
优化算法(optimizer)是基于损失函数梯度更新模型参数的过程,其目标是降低损失函数的值。在深度学习中,常用的优化算法包括 AdaGrad、AdaDelta、RMSProp 和 Adam 等。
2.10 Batch Normalization
Batch Normalization(BN)是一种在卷积神经网络(CNN)中广泛应用的技术,其核心作用是通过归一化处理使各层输出保持相互独立。该方法通过滑动窗口计算输入数据的均值和标准差,对每个batch的输入样本进行标准化处理,从而实现各通道间的同步归一化和零均值输出。
2.11 ResNet
ResNet 是深度学习领域中的一个重要创新,它基于残差网络(residual network)进行了优化。其主要原因是为了解决梯度消失和梯度爆炸问题。随着深度网络的逐步加深,网络输出值趋向于零,导致梯度消失(vanishing gradient)问题愈发突出。然而,直接采用ReLU或其他激活函数可能导致某些节点输出为负值,这会阻碍梯度反向传播。通过跳跃连接(skip connection),残差网络成功解决了这一问题。
2.12 Dropout
Dropout是一种用于深度学习的正则化技术,其作用是缓解神经元之间高度相关的状态。通过随机将部分神经元的输出设为0,该方法有效地减少了神经元之间过强的依赖关系。其核心机制在于,每次训练时,随机停用部分神经元的计算,从而防止神经网络过于依赖特定的神经元,增强其泛化能力。Dropout技术通过引入噪声机制,既降低了模型在训练过程中可能产生的过拟合风险,又保持了模型在面对新数据时的稳定性和可靠性。该方法通过在每次训练迭代中动态调整神经元的参与程度,确保模型在学习过程中始终保持一定的鲁棒性。
2.13 批归一化
批归一化(Batch Normalization,BN)是一种常用的正则化技术,在卷积神经网络和全连接层之间引入了一系列的缩放、偏移和饱和操作,通过归一化处理输入数据,从而增强网络的健壮性和加速训练收敛。其核心理念是通过实现各层输入均值为0、方差为1的标准化,使网络各层之间能够实现有效的统一控制,有效提升训练过程的稳定性。
2.14 LSTM 和 GRU
LSTM网络和GRU网络是两种主流的循环神经网络结构,它们旨在有效解决序列数据在训练过程中梯度消失和梯度爆炸的问题。具体来说,LSTM网络通过遗忘门、输入门和输出门来控制单元状态的变化,而GRU网络则仅使用更新门来实现这一功能。GRU网络计算过程相对简单,运行速度较快,但其性能略逊于LSTM网络。
3.核心算法原理和具体操作步骤及数学公式
3.1 卷积操作
卷积运算是一种线性操作。输入信号与卷积核进行逐点乘积运算,得到输出信号。二维卷积过程可视为将卷积核铺展至输入图像上,通过逐行和列进行互相关运算来生成输出特征图。
3.1.1 单输入通道、多核
考虑一个大小为 w \times h 的输入图像 I,其中包含 m 个卷积核,每个卷积核的尺寸为 k_i \times k_j,输出通道数为 c_o。卷积核在水平和垂直方向上进行平移操作,卷积过程可表示为:其中,(n_p, n_q) 表示卷积核的中心位置,i_0 和 j_0 分别为卷积核左上角的索引,使用向上取整符号‘+’,\delta_i 和 \delta_j 则表示卷积核相对于中心位置的横向和纵向偏移量。
3.1.2 多输入通道、单核
假设有一个 w \times h 大小的输入图像 I,它包含 c_i 个输入通道,每个通道均为一个 W_i \times H_i 大小的二维矩阵。卷积核的尺寸为 k_i \times k_j,输出通道的数量为 c_o。对每个输入通道 I_c 施加卷积操作,其公式定义为:对于卷积核的中心位置 (n_p, n_q) 和左上角索引 (i_0, j_0),以及输入通道编号 c_i,执行以下计算。
3.1.3 多输入通道、多核
假设有一个 w \times h 大小的输入图像 I,其中包含 c_i 个输入通道,每个通道均为一个 W_i \times H_i 大小的二维矩阵。在每个通道中,配置了 m_i 个卷积核,每个卷积核的尺寸为 k_i \times k_j。整个网络共有 m_o 个输出通道。通过将每个输入通道 I_c 与相应的卷积核 K_i^m 进行卷积操作,可以得到最终的输出特征图。其中,(n_p, n_q, c_o) 表示卷积核的中心位置坐标,i_0 和 j_0 分别表示卷积核左上角的索引。
3.1.4 填充方式
在卷积操作执行时,因为卷积核尺寸小于输入图像,所以必须对输入图像进行扩展,以便与卷积核进行卷积运算。常见的扩展方法包括以下几种:
zero padding:将原始输入图像填充为0至卷积核大小的整数倍,从而完成卷积操作。
replication padding:将原始输入图像扩展为卷积核大小的整数倍,从而完成卷积操作。
reflection padding:将原始输入图像延展为卷积核大小的整数倍,从而完成卷积操作。
edge padding:将原始输入图像的边缘截取后延展为卷积核大小的整数倍,从而完成卷积操作。
3.2 池化操作
池化操作是对卷积后特征图的降维操作,其主要目标是通过降维操作进一步提取图像特征,从而增强模型的鲁棒性和泛化能力。池化操作的目的是减少网络参数数量,同时保持输入语义信息。常用的池化方法包括最大池化和平均池化。
3.2.1 最大池化
最大池化是对卷积后特征图中特定区域的元素进行筛选,通过选择该区域中最大的数值作为输出,并舍弃其他数值。这种操作有助于捕捉图像中的关键特征。
3.2.2 平均池化
平均池化是对卷积后特征图中特定区域的元素进行提取,将该区域的平均值作为输出结果,并舍弃剩余元素。该过程能够有效提取图像中的局部特征信息。
3.2.3 选取池化尺寸
池化窗口的大小决定了其对特征图降维规模的影响程度,不建议将整个图像作为池化窗口。常用的池化窗口大小包括2x2、3x3、4x4等。
3.3 卷积网络
卷积神经网络(Convolutional Neural Network,CNN)是一种深度学习模型,主要用于处理图像识别、图像分类以及物体检测等问题。通过结合卷积层和池化层,CNN能够有效提取图像中的局部特征,并通过全连接层实现最终的分类或回归目标。以下将介绍卷积网络的关键组件。
3.3.1 网络结构
卷积神经网络由卷积层、池化层、全连接层和输出层等层次结构构成。卷积层和池化层的数量及其输出通道数共同决定了网络的深度、特征图的尺寸以及通道数。具体而言,AlexNet和VGGNet分别采用了两个卷积层、四个池化层、八个卷积层和三个全连接层;而GoogleNet则由五个卷积层、七个全连接层构成,并引入了Inception模块,显著提升了网络的深度和精度。
3.3.2 卷积核大小
卷积核的尺寸设置决定了网络的感受野范围,一般采用奇数尺寸,以保持卷积操作后的图像尺寸与原图一致。
3.3.3 卷积步长
卷积步长决定了卷积核滑动的步长,一般取 1 或 2,可以减少参数量和计算量。
3.3.4 池化窗口大小
池化窗口大小决定了池化步长,通常取 2 或 3,可以减少参数量和计算量。
3.3.5 损失函数
损失函数常见的有交叉熵(cross entropy)、均方误差(mean squared error)等。
3.3.6 优化器
优化器用于更新模型参数,常用的有 AdaGrad、AdaDelta、RMSprop、Adam 等。
3.3.7 BN 操作
批量归一化(Batch Normalization)操作有助于提高网络在训练过程中的稳定性,并降低过拟合的风险。
3.3.8 dropout 操作
dropout 操作是一种正则化方法,可以在训练过程中阻止过拟合。
3.3.9 skip connections
残差网络(ResNet)通过 skip connections将前面层的输出直接连接并传递给后面层的输入,从而有效抑制梯度爆炸,同时防止梯度消失,从而提升网络的训练效果。
3.4 深度可分离卷积层(Depthwise Separable Convolutions)
深度可分离卷积层(Depthwise Separable Convolutions)是一种通过优化计算资源来提升模型效率的卷积层结构。该层通过依次对输入图像执行宽度方向和高度方向的卷积操作,实现了计算效率的提升。在这一过程中,宽度和高度方向上的卷积核共享了参数集,从而有效降低了参数数量。值得注意的是,由于两个方向上的卷积操作没有相互作用,因此能够避免了特征重叠,从而有效提升了特征提取的精度。
4.具体代码实例与解释说明
4.1 LeNet-5
LeNet-5 是首个被广泛应用于计算机视觉领域的卷积神经网络,其结构相对简单,仅包含几层卷积层和池化层,且输入尺寸固定不变。其结构如图所示。
4.1.1 输入层
输入层接收原始图像,它具有 28 \times 28 大小,共有 1 个颜色通道。
inputs = tf.keras.Input(shape=(28, 28, 1))
代码解读
4.1.2 卷积层
卷积层首先在宽度方向上执行卷积操作,使用 6 \times 5 大小的卷积核,共有 6 个卷积核。通过调用 tf.nn.conv2d 函数,可以对输入图像执行卷积操作。另外,通过设置 padding='same' 对输入图像进行填充,确保卷积后的图像大小与池化层输出一致。
conv1 = tf.keras.layers.Conv2D(filters=6, kernel_size=(6, 5), activation='relu')(inputs)
代码解读
4.1.3 池化层
池化层通过执行池化操作对前一层的卷积特征图进行处理,该操作采用 2 \times 2 大小的窗口进行。通过调用 tf.nn.max_pool2d 函数,可以实现对卷积后特征图的池化处理。此外,设置池化操作的步长参数为 strides=(2,2) 可以实现相应的池化效果。
pool1 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2))(conv1)
代码解读
4.1.4 卷积层
通过卷积操作,第二个卷积层能够实现高度方向上的特征提取。该层由16 \times 5的卷积核构成,共有16个独立的卷积滤波器。通过调用tf.nn.conv2d函数,可以对经过池化后的特征图进行卷积操作。为确保卷积后的特征图与原图保持一致的空间维度,通过设置卷积填充方式为'valid',从而实现对卷积后特征图的空间维度缩小4 \times 4。
conv2 = tf.keras.layers.Conv2D(filters=16, kernel_size=(16, 5), activation='relu')(pool1)
代码解读
4.1.5 池化层
在第二层卷积后的特征图上,第三个池化层执行池化操作。该层采用 2 \times 2 大小的池化窗口,通过调用 tf.nn.max_pool2d 函数,可以实现对卷积后特征图的池化。此外,设置池化步长为 strides=(2,2) 以实现有效的特征图降采样。
pool2 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2))(conv2)
代码解读
4.1.6 全连接层
第四个全连接层是完全连接的,它有 120 个节点,使用 tf.nn.relu 激活函数。
fc1 = tf.keras.layers.Dense(units=120, activation='relu')(pool2)
代码解读
4.1.7 全连接层
第五个全连接层是完全连接的,它有 84 个节点,使用 tf.nn.relu 激活函数。
fc2 = tf.keras.layers.Dense(units=84, activation='relu')(fc1)
代码解读
4.1.8 输出层
第六个输出层是分类器,它有 10 个节点,使用 softmax 激活函数。
outputs = tf.keras.layers.Dense(units=10, activation='softmax')(fc2)
代码解读
4.1.9 模型构建
将所有的层都连接起来,构造出完整的卷积神经网络。
model = tf.keras.Model(inputs=inputs, outputs=outputs)
代码解读
4.1.10 模型编译
使用 categorical_crossentropy 作为损失函数,adam 作为优化器。
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
代码解读
4.1.11 模型训练
对模型进行训练,使用 fit() 方法。
history = model.fit(train_data, train_labels, epochs=5, validation_split=0.1)
代码解读
4.2 AlexNet
AlexNet在ImageNet竞赛中取得了显著成绩,其Top-5误差率较之其他方法高出4%。该网络结构较为复杂,由八个卷积层和三个全连接层构成,其显著特点包括引入了归一化处理、随机丢弃技术以及数据增强技术等创新性设计。
4.2.1 数据预处理
AlexNet 使用的数据预处理方法包括:
- 调整图片尺寸:AlexNet 采用了固定尺寸为 227 \times 227 的图片处理方式。
- 分割图片:将图片划分为 5 \times 5 的网格单元,并对每个单元内的图像进行色彩标准化处理。
- 引入均值和方差:计算每张子图像素点的均值和方差,随后进行标准化处理。
- 引入 LRN:AlexNet 通过 LRN 操作减少过拟合,从而增强模型的泛化能力。
4.2.2 网络结构
AlexNet 的网络结构如下图所示:
4.2.2.1 输入层
AlexNet 输入层接收原始图片,它具有 227 \times 227 大小,共有 3 个颜色通道。
inputs = tf.keras.Input(shape=(227, 227, 3))
代码解读
4.2.2.2 卷积层
AlexNet首先采用了五个卷积层结构,其中第一个卷积层采用了大小为11x11的卷积核,共计96个,激活函数为tf.nn.relu。随后采用了5x5的卷积核,共计256个,激活函数同样为tf.nn.relu。第三个卷积层采用了3x3的卷积核,共计384个,激活函数为tf.nn.relu。第四个卷积层同样采用了3x3的卷积核,共计384个,激活函数为tf.nn.relu。最后采用了3x3的卷积核,共计256个,激活函数为tf.nn.relu。
conv1 = tf.keras.layers.Conv2D(filters=96, kernel_size=(11, 11), strides=(4, 4), padding='valid', activation='relu')(inputs)
conv2 = tf.keras.layers.Conv2D(filters=256, kernel_size=(5, 5), strides=(1, 1), padding='same', activation='relu')(conv1)
conv3 = tf.keras.layers.Conv2D(filters=384, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')(conv2)
conv4 = tf.keras.layers.Conv2D(filters=384, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')(conv3)
conv5 = tf.keras.layers.Conv2D(filters=256, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')(conv4)
代码解读
4.2.2.3 池化层
AlexNet采用了三层池化结构,其中第一个池化层运用3x3的窗口,并对卷积层输出进行池化操作。第二个池化层则采用了2x2的窗口,并对第一层池化后的特征图进行二次池化。第三个池化层同样使用2x2的窗口,并对第二层池化后的特征图进行池化处理。
pool1 = tf.keras.layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='valid')(conv1)
pool2 = tf.keras.layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='valid')(conv2)
pool3 = tf.keras.layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='valid')(conv3)
代码解读
4.2.2.4 Flatten 层
AlexNet 通过 Flatten 层把卷积层的输出转换成向量,并进入全连接层。
flatten1 = tf.keras.layers.Flatten()(pool3)
代码解读
4.2.2.5 全连接层
AlexNet由两层全连接层构成。第一层包含4096个神经元,并采用tf.nn.relu作为激活函数。第二层同样包含4096个神经元,并采用tf.nn.relu作为激活函数。第三层拥有1000个神经元,并采用softmax激活函数,输出结果为概率分布。
dense1 = tf.keras.layers.Dense(units=4096, activation='relu')(flatten1)
dense2 = tf.keras.layers.Dense(units=4096, activation='relu')(dense1)
predictions = tf.keras.layers.Dense(units=1000, activation='softmax')(dense2)
代码解读
4.2.3 模型构建
将所有的层都连接起来,构造出完整的卷积神经网络。
model = tf.keras.Model(inputs=inputs, outputs=predictions)
代码解读
4.2.4 模型编译
使用 categorical_crossentropy 作为损失函数,adam 作为优化器。
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
代码解读
4.2.5 模型训练
对模型进行训练,使用 fit() 方法。
history = model.fit(train_data, train_labels, epochs=5, validation_split=0.1)
代码解读
