CNN,一种帮助机器拥有基础“视力”的人工智能算法
一、像素和图像
1. 像素和图像的结构
- minecraft,我相信大家都玩过这款像素风游戏,他的画面就凸显了像素的特点。
- 每个图像都是由像素组成的网格,也可以看成是一堆按顺序排列的数字,数值为0到255,255 代表白色,0 代表黑色,其他数值是不同的灰度。
- 上图是只有黑白颜色的灰度图,而更普遍的图片表达方式是RGB颜色模型,即红、绿、蓝三原色的色光以不同的比例相加,以产生多种多样的色光。RGB颜色模型中,单个矩阵就扩展成了有序排列的三个矩阵,也可以用三维张量去理解。
- 其中的每一个矩阵又叫这个图片的一个channel(通道),宽, 高, 深来描述。
2. 机器如何理解图像?
-
如果每个像素点代表一种颜色,机器能通过这些点的排列来判断图片的内容吗?
-
机器通过分析这些像素之间的关系来理解图像。比如识别边缘时,需要知道哪些像素的颜色差异较大。
二、卷积神经网络vs传统神经网络
- 在传统神经网络中,我们要识别下图红色框中的图像时,我们很可能识别不出来,因为这六张图的位置都不通,计算机无法分辨出他们其实是一种形状或物体。
- 传统神经网络原理如下图:
- 传统的神经网络(如多层感知器,MLP)在处理图像时存在以下几个问题,导致其难以有效处理图片数据:
- 输入维度过高:
- 图像通常是高维数据,例如一张 256x256 的彩色图片有 256 * 256 * 3 = 196,608 个像素(RGB 三通道),需要 196,608 个输入节点。
- 传统神经网络对每个像素的值都建立一个神经元,这导致网络参数量巨大,使计算资源需求和内存占用极高。
- 丧失空间信息:
- 图像具有空间信息,像素之间的相对位置和结构很重要。
- 传统神经网络将所有像素展开成一维向量处理,丢失了图像中像素的空间结构(如边缘、角点等),无法有效地提取局部特征。
- 参数共享性差:
- 在传统神经网络中,每个神经元都是独立的,没有共享参数。
- 卷积神经网络(CNN)通过卷积核共享权重,可以在图像的不同位置重复使用相同的特征提取器(如边缘检测),从而有效减少了参数数量,并提高了模型的泛化能力。
- 计算效率低:
- 由于参数数量庞大,传统神经网络在处理图像时的计算效率非常低。
- CNN 通过池化和卷积操作来减少特征图的大小,从而降低计算需求,并保留图像的主要特征,使得它在图像处理任务中更加高效。
- 输入维度过高:
- 因此,传统神经网络在处理图像时不仅计算成本高,且无法有效提取图像的空间特征,无法实现对图像内容的有效理解。
- 我们希望一个物体不管在画面左侧还是右侧,都会被识别为同一物体,这一特点就是不变性。为了实现平移不变性,卷积神经网络(CNN)等深度学习模型在卷积层中使用了卷积操作,这个操作可以捕捉到图像中的局部特征而不受其位置的影响。
三、卷积神经网络
1. 卷积的概念
- 卷积的定义:
- 卷积(Convolution)是卷积神经网络(CNN)的核心概念,主要用于提取图像中的局部特征,如边缘、纹理、形状等。卷积操作通过一个小矩阵(称为卷积核或滤波器)在图像上滑动,每次只关注图像的一小块区域,逐步构建出特征图,用来表示图像中的关键特征。
- 将卷积比作放大镜或滤镜,用来在图像中找到重要信息(例如边缘、纹理)。
- CNN 通过在图像上应用多个“卷积核”(或滤镜)来识别不同的图像特征。
- 卷积核(滤波器)的定义和作用:
- 卷积核(kernel)是一个小的矩阵,通常是 3x3 或 5x5 的大小,用来扫描图像的局部区域并提取特征。
-
卷积核应用在图像上的计算公式为:
\[(I * K)(i, j) = \sum_{m}\sum_{n} I(i+m, j+n) \cdot K(m, n)\]其中 $I$ 是图像,$K$ 是卷积核矩阵,$i$ 和 $j$ 是图像像素的坐标。
- 卷积核的计算:
- 示例1:
- 示例2:
- 示例1:
- 卷积核的效果示例:
-
边缘检测卷积核:
\[K = \begin{bmatrix} -1 & -1 & -1 \\ -1 & 8 & -1 \\ -1 & -1 & -1 \\ \end{bmatrix}\]该卷积核能够突出图像中的边缘信息,因为边缘处的像素值差异较大。
-
模糊卷积核:
\[K = \begin{bmatrix} 1/9 & 1/9 & 1/9 \\ 1/9 & 1/9 & 1/9 \\ 1/9 & 1/9 & 1/9 \\ \end{bmatrix}\]该卷积核通过平均相邻像素值来模糊图像,使得图像中的细节被“平滑”处理。
- 不同的卷积核有不同的效果,可以让模型识别出特定特征,如边缘、颜色变化等。
- 多个卷积核和特征提取:
- 多个卷积核:通常,CNN 会在同一层中使用多个卷积核,每个卷积核提取不同的特征。这样可以生成多个特征图,每个特征图关注图像的不同方面(例如水平边缘、垂直边缘、纹理等)。
- 逐层提取更高级的特征:随着卷积层的加深,模型能够逐步提取更复杂、更抽象的特征。例如,低层卷积层可能关注边缘或纹理,而高层卷积层则可能关注更大的结构(如眼睛、鼻子等面部特征)。
-
- 卷积核滑动过程:
- 下面这个动图生动形象地说明了卷积核如何在图像上滑动,并逐个计算每个位置的结果,将这些结果组合成一个新的“特征图”。
- 这张图中蓝色的框就是指一个数据窗口,红色框为卷积核(滤波器),最后得到的绿色方形就是卷积的结果(数据窗口中的数据与卷积核逐个元素相乘再求和)
- 将卷积核放置在图像的某一位置,使其覆盖图像的一个小区域。
- 将卷积核中的每个值与图像对应区域的像素值相乘。
- 将这些乘积求和,得到一个数值,这个数值代表该位置的特征。
- 将卷积核按固定步长(stride)向右滑动,再重复上述步骤,直到完成整个图像的遍历。
- 最终得到的新图像称为特征图(Feature Map),表示原图像中的特征。
- 注意事项:
- 步长stride:每次滑动的位置步长。
- 卷积核的个数:决定输出的depth厚度。同时代表卷积核的个数。
-
填充值zero-padding:在外围边缘补充若干圈0,方便从初始位置以步长为单位可以刚好滑倒末尾位置,通俗地讲就是为了总长能被步长整除。
以上面这个动图为例,那么:
- 数据窗口每次移动两个步长取 3*3 的局部数据,即 stride=2。
- 两个神经元,即 depth=2 ,意味着有两个滤波器。
- zero-padding=1 。
- 为什么要进行数据填充:
-
假设有一个大小为 4x4 的输入图像:
\[\begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \\ \end{bmatrix}\] - 现在,我们要应用一个 3x3 的卷积核进行卷积操作,步幅(stride)为 1。如果不使用填充,卷积核的中心将无法对齐到输入图像的边缘,导致输出特征图尺寸变小。假设我们使用步幅(stride)为 1 进行卷积,那么在不使用填充的情况下,输出特征图的尺寸将是 2x2。
-
所以我们要在它的周围填充一圈0,填充为 1 意味着在输入图像的周围添加一圈零值。添加填充后的图像:
\[\begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 2 & 3 & 4 & 0 \\ 0 & 5 & 6 & 7 & 8 & 0 \\ 0 & 9 & 10 & 11 & 12 & 0 \\ 0 & 13 & 14 & 15 & 16 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ \end{bmatrix}\] - 现在,我们将 3x3 的卷积核应用于这个填充后的输入图像,计算卷积结果,得到大小不变的特征图。
- 数据填充的主要目的是确保卷积核能够覆盖输入图像的边缘区域,同时保持输出特征图的大小。这对于在CNN中保留空间信息和有效处理图像边缘信息非常重要。
-
- 卷积的优势:
- 参数共享:卷积核的权重在整个图像中共享,能够大幅减少模型参数数量,相比传统神经网络更加高效。
- 局部感受野:卷积操作只关注图像的局部区域,使得模型能够提取局部特征,这些特征可以逐层组合成更高级的特征。
- 平移不变性:由于卷积核在图像上的滑动操作,即使物体在图像中出现位置不同,模型仍然可以有效识别,这使得卷积具有平移不变性。
2. 激活函数
- 激活函数的作用:
- 激活函数的目的是给模型一个“开关”机制,用来判定哪些特征更重要。
- 简单来说,它会让某些特征保持较强的影响力,而让不重要的特征减少或忽略。
- ReLU 激活函数:
-
ReLU(Rectified Linear Unit)是 CNN 中常用的激活函数。其公式如下:
\[f(x) = \max(0, x)\]即:如果输入值 $x$ 大于 0,则输出 $x$;否则输出 0。
- ReLU 将负值转为 0,只保留正值,这样可以让模型关注“更重要的特征”。
-
如下,一个包含负数和正数的特征图通过 ReLU 后,将负数变成 0,仅保留了重要信息。
\[Feature Map = \begin{bmatrix} -1 & 2 & -3 \\ 4 & -5 & 6 \\ -7 & 8 & -9 \\ \end{bmatrix}\] \[ReLU Output = \begin{bmatrix} 0 & 2 & 0 \\ 4 & 0 & 6 \\ 0 & 8 & 0 \\ \end{bmatrix}\]
-
- ReLU 在 CNN 中的作用:
- 在 CNN 中,ReLU 激活函数通常应用于每个卷积层的输出之后,将其转化为非线性特征。具体作用如下:
- 引入非线性:
- 卷积操作本质上是线性的,即在卷积层中,特征是通过线性加权和的方式进行提取的。如果没有非线性激活函数,整个网络将变成一个线性组合,无法捕捉复杂的模式和结构。
- 通过在卷积层后应用 ReLU 激活函数,模型能够学习非线性特征,从而可以对复杂的图像特征进行识别和分类。
- 提高训练速度:
- 由于 ReLU 函数简单且计算高效,CNN 使用 ReLU 后的训练速度显著加快,网络可以更快地收敛到最优解。
- ReLU 的梯度为常数(0 或 1),不会出现梯度消失的问题,尤其在深层网络中,ReLU 可以更好地保留梯度信息,从而加速训练。
- 稀疏表示:
- 由于 ReLU 会将负数部分的输出截断为零,因此它使得每层的输出特征图中有大量零值,这种稀疏性在 CNN 中有助于增强特征的鲁棒性。
- 稀疏表示可以减少后续层的计算量,避免信息冗余,有利于提高模型的泛化能力。
- 抑制噪声:
- 在卷积操作之后,某些噪声信息可能会带来小于零的输出,ReLU 会自动将这些负值置零,从而起到一定的噪声过滤作用。
- 这种抑制噪声的能力使得 CNN 在实际应用中更加稳定,对图像中的微小扰动具有一定的鲁棒性。
- 在 CNN 中,ReLU 激活函数通常应用于每个卷积层的输出之后,将其转化为非线性特征。具体作用如下:
- 激活函数的优势:
- ReLU 的优势在于计算简单且能减少模型的复杂度。它有效避免了梯度消失问题,帮助模型更快地收敛。
- 提升模型性能:ReLU 激活函数的引入让 CNN 模型在处理复杂图像任务时表现更加优秀。例如,在图像分类、目标检测等领域,CNN 的性能很大程度上依赖 ReLU 的非线性特征。
- 计算高效:ReLU 简单的计算方式使得 CNN 可以在大型数据集上高效训练,并在硬件加速上(如 GPU)更具优势。
- 与卷积层的完美配合:ReLU 与卷积层结合后,模型可以捕捉到更丰富的特征和模式,让 CNN 不仅关注简单的边缘和形状,还能识别更高级的结构和语义信息。
- 类比:激活函数相当于让模型在分析图像时自动关注最明显的特征,忽略那些影响较小的细节。
3. 池化层(Pooling)
- 池化的概念:
- 我们可以将池化理解为“缩小视角”。例如,当我们观看一幅画时,可以从远处看整体内容,而不去关注每一个细小的细节。同样,池化操作通过压缩图像数据来提取主要信息,忽略细节部分。
- 池化层(Pooling)是卷积神经网络(CNN)中的关键操作之一。池化的目的是降低特征图的维度,同时尽量保留主要信息,从而减少计算量,提高计算效率,并增强模型的泛化能力。池化操作主要通过在图像的局部区域中提取重要特征来完成。
- 池化层的提出主要是为了缓解卷积层对位置的过度敏感性。池化层中的池化函数通过使用某一位置的相邻输出的总体统计特征来代替网络在该位置的输出。
- 池化层主要有以下三点作用:
- 增加特征平移不变性。汇合可以提高网络对微小位移的容忍能力。
- 减小特征图大小。汇合层对空间局部区域进行下采样,使下一层需要的参数量和计算量减少,并降低过拟合风险。
- 最大汇合可以带来非线性。这是目前最大汇合更常用的原因之一。
- 池化层中的填充和步幅机制与卷积层一致,值得注意的是:在处理多通道输入数据时,池化层对每个输入通道分别池化,而不是像卷积层那样将各通道的输入按通道相加。这意味着池化层的输出通道数与输入通道数相等。
-
最大池化(Max Pooling):
-
最大池化是一种常用的池化方法。它通过在一个局部区域内选择最大值来代表该区域的特征。最大池化可以帮助模型在特征图中保留最显著的特征。
- 操作步骤:
- 选择一个池化窗口大小(如 2x2)。
- 在特征图上滑动该窗口,每次覆盖一个局部区域。
- 在每个窗口区域中选择最大值作为该区域的池化结果。
- 继续滑动池化窗口直到覆盖整个特征图。
- 数学公式:
-
对于特征图 $I$,在位置 $(i, j)$ 的最大池化操作可以表示为:
\[P(i, j) = \max_{(m, n) \in \text{window}} I(i + m, j + n)\]其中:
- $P(i, j)$ 表示池化后的值。
- $(i, j)$ 是池化输出特征图的位置坐标。
- “window” 表示固定大小的池化区域(如 2x2 区域)。
- $I(i + m, j + n)$ 是池化窗口覆盖区域中的像素值。
-
- 示例:
-
假设有一个 4x4 的特征图:
\[I = \begin{bmatrix} 1 & 3 & 2 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 2 & 0 & 3 \\ 4 & 7 & 5 & 1 \\ \end{bmatrix}\] -
使用 2x2 的最大池化操作,结果如下:
- 左上角 2x2 区域:$\begin{bmatrix}1 & 3 \ 5 & 6\end{bmatrix}$,最大值为 6。
- 右上角 2x2 区域:$\begin{bmatrix}2 & 4 \ 7 & 8\end{bmatrix}$,最大值为 8。
- 左下角 2x2 区域:$\begin{bmatrix}9 & 2 \ 4 & 7\end{bmatrix}$,最大值为 9。
- 右下角 2x2 区域:$\begin{bmatrix}0 & 3 \ 5 & 1\end{bmatrix}$,最大值为 5。
-
因此,池化后的特征图为:
\[P = \begin{bmatrix} 6 & 8 \\ 9 & 5 \\ \end{bmatrix}\]
-
-
-
池化的其他类型:
- 除了最大池化,还有其他几种常见的池化方法:
- 平均池化(Average Pooling):
- 操作:在池化窗口中计算所有值的平均值,作为该区域的池化结果。
-
公式:对于池化区域“window”,平均池化的计算方式为:
\[P(i, j) = \frac{1}{\text{window size}} \sum{(m, n) \in \text{window}} I(i + m, j + n)\] - 特点:平均池化在某些情况下可以保留更多细节,但对噪声的抑制不如最大池化明显。
- 全局池化(Global Pooling):
- 操作:在整个特征图上取平均值或最大值,生成一个单一的值,用于表示整个特征图。
- 应用:全局池化常用于最后一层,将特征图压缩为单个值,通常用于生成分类结果的概率值。
-
池化的作用和优势:
- 降低计算复杂度:
- 通过池化操作,特征图的尺寸大大减小,使得模型的计算需求减少。这对于深层 CNN 非常重要,因为它显著减小了网络的计算量和内存需求。
- 例如,通过池化将 4x4 特征图变为 2x2 特征图,参数减少为原来的四分之一,计算量也随之下降。
- 增强特征的鲁棒性:
- 最大池化能够保留特征中最重要的部分,例如边缘和纹理,这些特征往往是图片内容的主要信息。
- 平均池化可以降低输入图像的噪声,使得特征更平滑。这对于去除局部的极端数值效果显著。
- 提升平移不变性:
- 池化操作使得 CNN 对图像的微小位移或扭曲更具鲁棒性。例如,即使输入图片稍微偏移,池化后的特征图也不会有明显变化。
- 平移不变性对图像分类和识别任务非常重要,因为在不同的拍摄角度或视角下,图片会有细微的变化,池化层能够帮助模型更加稳健地识别这些图像。
- 避免过拟合:
- 池化层通过减少特征图的维度和信息量,可以在一定程度上防止模型对训练数据的过拟合。过拟合是指模型在训练数据上表现很好,但在新数据上表现不佳,而池化通过抽象主要特征来提高模型的泛化能力。
- 降低计算复杂度:
-
总结:
-
池化层在 CNN 中发挥了不可或缺的作用,尤其在图像处理任务中。其主要作用体现在以下几个方面:
- 减少数据量和计算复杂度:池化层降低了特征图的大小,减少了网络中的计算资源需求。
- 保留主要信息:池化能够保留区域内的关键特征,尤其是最大池化有助于突出图像中的显著信息。
- 增强模型的泛化能力和鲁棒性:池化层提升了模型对位移和平移的适应能力,同时有助于防止过拟合。
-
通过池化层的处理,CNN 能够高效地从输入图像中提取出稳定的、抽象的特征,使得模型在图像分类、目标检测等任务中表现更为优异。
-
四、卷积神经网络的构造
1. 层次结构
- 输入层:
- 输入层接收原始图像数据。图像通常由三个颜色通道(红、绿、蓝)组成,形成一个二维矩阵,表示像素的强度值。
- 卷积和激活:
- 卷积层将输入图像与卷积核进行卷积操作。然后,通过应用激活函数(如ReLU)来引入非线性。这一步使网络能够学习复杂的特征。
- 池化层:
- 池化层通过减小特征图的大小来减少计算复杂性。它通过选择池化窗口内的最大值或平均值来实现。这有助于提取最重要的特征。
- 多层堆叠:
- CNN通常由多个卷积和池化层的堆叠组成,以逐渐提取更高级别的特征。深层次的特征可以表示更复杂的模式。
- 全连接和输出:
- 最后,全连接层将提取的特征映射转化为网络的最终输出。这可以是一个分类标签、回归值或其他任务的结果。
五、CNN的工作流程 – 模型如何“学习”
- 在卷积神经网络(CNN)中,模型通过一个类似人类学习的过程,不断调整内部参数(即“权重”)以提高识别精度。
- 这个学习过程依赖两个关键概念:损失函数和反向传播。以下是它们的详细解释:
1. 类比人类学习区分猫和狗
-
假设我们学习如何分辨猫和狗。最初,可能无法很好地区分它们,但经过大量观察和不断尝试错误,我们逐渐能准确识别猫和狗的特征。这种学习过程类似于机器如何“学习”识别图像。
-
在 CNN 中,模型会通过大量的带标签的图像(例如标记为“猫”或“狗”的图片)进行训练。每张图像传入网络后,CNN 会根据当前的权重生成预测结果。接着,模型会比较预测值和真实标签的差距,调整参数以减少这个差距,从而逐步提高准确性。
2. 损失函数:机器学习中的“评分系统”
- 损失函数是机器用来评估模型预测准确性的一个指标。它衡量模型输出(预测值)与真实值(标签)之间的差距,输出一个表示“错误程度”的数值。
- 定义:损失函数是一个数学公式,用于衡量模型预测结果和真实结果之间的偏差。偏差越大,损失值就越大,偏差越小,损失值也越小。
- 常用的损失函数:
- 均方误差(Mean Squared Error, MSE)
- 交叉熵损失(Cross-Entropy Loss)
- 损失函数的作用:
- 损失函数提供了一个清晰的“评分系统”,告诉模型预测的好坏程度。
- 每次计算损失后,模型会根据损失值的大小调整权重,以减少未来的预测误差。
3. 反向传播:调整权重的关键
- 反向传播(Backpropagation)是一个优化算法,旨在通过最小化损失函数来调整模型的权重,从而提高模型的准确性。
- 过程概述:
- 前向传播:将输入数据通过网络各层传递,计算出预测结果,并计算损失值。
- 反向传播:从输出层开始,计算损失函数相对于每个参数的导数,即“梯度”。梯度反映了损失函数随每个参数变化的敏感度。
- 调整权重:使用梯度下降算法,根据每个参数的梯度更新参数,使得损失函数最小化。
- 反向传播的计算细节:
- CNN 通过链式法则计算每一层的梯度。首先计算输出层的梯度,然后逐层反向传递,依次更新每一层的权重。
- 在卷积层中,反向传播的计算稍微复杂,因为每个卷积核需要与多层输入相连接。然而,通过链式法则,我们可以有效地计算每层参数的梯度并更新它们。
4. 模型的学习过程概述
- 在 CNN 中,“学习”是一个逐步减少损失的过程:
- 初始化:模型的权重最初被随机初始化,模型的预测可能是随机的或完全错误的。
- 前向传播:将输入图像通过卷积层、池化层、激活函数和全连接层,得到预测输出。
- 计算损失:通过损失函数,计算预测结果与真实结果之间的误差。
- 反向传播:使用反向传播算法计算每个权重的梯度。
- 权重更新:应用梯度下降方法,根据损失梯度调整权重,使损失减少。
- 循环迭代:上述步骤不断循环,直到损失函数达到预期的较小值或训练达到指定的轮次。
- 通过损失函数和反向传播,CNN 可以不断改进其内部权重,使得每次输入图像时,网络能够更准确地识别其中的特征,从而完成图像分类、目标检测等任务。
小结与未来方向
现在,大家应该对CNN有一个虽然基础但比较全面的认识了吧,包括卷积层、激活函数、池化层的作用,以及CNN在识别图像中的关键特征等等。
我们知道,CNN在图像识别、自然语言处理、语音识别等方面都有广泛的应用,非常鼓励大家进一步了解CNN在各领域中的实际应用。
对计算机视觉感兴趣的朋友们还可以激素探索其他相关的神经网络结构,更深入的有AlexNet、VGG、ViT等等。