初窥机器视觉与卷积神经网络

1. 什么是卷积神经网络

卷积神经网络(convolutional neural network,CNN)主要用于计算机视觉相关任务,但处理对象并不局限于图像,CNN在序列和语音等上的应用也展现出了强大的优势。

先直观认识一下卷积神经网络:

在这里插入图片描述

我们看到,卷积神经网络由若干个方块盒子构成,盒子从左到右仿佛越来越小,但越来越厚;最左边是一张图像,最右边则变成了两排圆圈。其实,每一个方块都是由大量神经元构成的,只不过它们排成了立方体的形状。左边图像上的每个元素相当于一个神经元,构成了这个卷积神经网络的输入单元。最右侧的圆圈也是神经元,它们排列成了两条直线,构成了该网络的输出,这与普通神经网络中的神经元没有区别。
卷积神经网络其实也是一种前馈神经网络,承载了深层的信息处理过程。信息从左侧输入,经过层层加工处理,最后从右侧输出。对于图像分类任务而言,输入的是一张图像,历经一系列卷积层、池化层和完全连接层的运算,最终输出一组分类的概率,要分成多少类别,就有多少个输出神经元。相邻两层的神经元连接用图中的小立体锥形近似表示,实际上这种锥形遍布更高一层(右侧)立方体中的所有神经元。低层(左侧)到高层(右侧)的运算主要分为两大类:卷积和池化。一层卷积,一层池化,这两种运算交替进行,直到最后一层,我们又把立方体中的神经元拉平成了线性排列的神经元,与最后的输出层进行全连接。

从技术角度看,卷积神经网络是一种至少包含一个卷积层(torch.nn.conv2d)的神经网络,该层的功能是计算其输入与一组可配置的卷积核的卷积,以生成该层的特征输出。
可用一种比较简明的定义描述卷积:卷积的目的是将卷积核(滤波器)应用到某个张量的所有点上,并通过将卷积核在输入张量上滑动而生成经过滤波处理的张量。这样抽象的解释不容易理解,我们用对单张图片卷积的例子来解释什么是卷积运算以及卷积运算是如何进行的。假如有一张1000×1000像素的彩色图片,它的形状是(1000,1000, 3),如果仍然使用全连接模型来提取它的特征,仅输入层就需要有1000×1000×3×2个参数(每一个像素点都需要初始化一个w和b),这是一个特别庞大的神经网络,对于内存和计算都将是巨大的挑战。如果图片像素更高、多层神经网络的可训练参数就会变得极其庞大,将使模型难以训练甚至无法训练。

CNN简化了上面的计算过程,在CNN提取图片特征时,不再为每一个输入初始化一个权重和偏置,而是初始化一个小的卷积核,卷积核的大小可能是3×3、5×5或其他值,使用这个卷积核在图片上滑动,在滑动过程中与图片的不同区域的像素做点乘(实际的卷积运算比这里所说的要复杂,在此仅对原理做解释),这样依次滑过图片得到一个形状为(height_, width_, 1)的张量,这就是提取到的特征。为了更好地提取特征,可以初始化多个卷积核,在图片上面滑动计算卷积,得到更多特征张量,假如有N个卷积核,则得到的特征张量为(height_, width_, N)。要注意的是,特征张量的height_和width_与原图的高和宽不一定相同,卷积运算如下图所示:
在这里插入图片描述

上图是一个卷积运算,使用了2×2的卷积核。首先卷积核与图片左上角的4个像素(In1,In2,In7,In8)做卷积运算,得到一个输出Out1,然后卷积核往后滑动一个像素,这时卷积核与图像中的(In2,In3,In8,In9)做卷积运算,得到第二个输出Out2,以此类推,卷积核在图片上滑动,与图像中的像素做卷积运算得到一个特征输出张量,这就是卷积计算的过程。

一般来说,为了增加拟合能力,卷积计算后会使用激活函数为计算带来非线性,提高卷积运算的特征提取能力。进行卷积的目的是从输入中提取有用的特征。在早期的图像处理中,人们发现可以选择各种类型的卷积核(filter)来提取图片特征。每种类型的filter都有助于从输入图像中提取不同的特征,例如水平、垂直、对角线边缘等特征。在卷积神经网络中,我们仍然通过使用filter来提取不同的特征,不同的是,这些filter的权重是在训练期间自动学习的,然后将所有这些提取的特征“组合”以做出决策。

不难发现,通过使用卷积核提取特征,可训练参数大大减小。例如上面的例子,提取特征仅仅需要训练一个大小为2×2的卷积核,整张图片在共享使用这个卷积核的权重计算特征。

那么为什么共享一个卷积核,在图片上滑动提取特征这种方式是有效的呢?
这就要考虑图片的平移不变性,假设图像右上方有一条小狗,当这条小狗移动到左下方时,它依然是一条小狗,因此希望无论小狗在图片什么位置,提取到的特征都应该是一样的。这样的话,使用一个卷积核在图片上滑动,就能实现特征提取的平移不变性。在实际应用中,单个卷积核通常被训练对输入数据中某些特征敏感,例如,在图像中卷积核可能学会识别物体的特征——几何形状,如线条、边缘和其他形状。

为了更好地提取特特征,我们会训练多个卷积核,这些卷积核经过训练能提取到不同的特征,如图下所示:

在这里插入图片描述

在上图的右侧可以看到,卷积操作中因为使用了多个卷积核提取特征,每一个卷积核都提取了一个2D的特征输出,N个卷积核的输出堆叠在一起就是卷积操作的完整结果(height_, width_, N),N也就是输出特征的通道数。这些通道分别代表了每一个卷积核从图像中提取到的某些关键特征。如果使用小批量数据计算,那么卷积运算的结果将是(batch,height_, width_, N)。在PyTorch中内置了torch.nn.Conv2d()方法在三维图片输入时应用2D卷积,其中的最重要参数包括in_channels、out_channels、kernel_size、stride和padding等。

  • in_channels:代表输入的特征层数,如输入通道数为3的彩色图像,则in_channels=3。

  • out_channels:代表输出的特征层数,也就是卷积核的个数,这是一个超参数。

  • kernel_size:代表卷积核的大小,通常使用3×3或者5×5这样的小卷积核,这个参数是一个元组,如果卷积核的长和宽一样,可直接指定为int数值,如kernel_size=3。

  • stride:代表跨度,卷积核在图像上是滑动提取特征的,stride代表每次滑动的步长,图7-2中的stride为1,表示步长为1个像素,也可使用其他步长,如设置stride为2,则卷积核在图像上每次滑动2个像素,显然这样会使输出的特征图像变为大约原来的一半大小,所以stride可影响生成的特征图的大小。

  • padding:代表填充,它表示卷积核在图像边缘的处理方式。

读者可以注意观察上图,如果使用3×3的卷积核提取图片特征,stride使用默认值1,那么得到的特征图会比原图小2个像素,这时,如果设置padding为1,那就表示原图的4条边使用0(这是默认的填充数值)各填充1个像素,原图大小相当于变为(height+2,width+2, channel),这样使用3×3卷积核得到的特征图大小为(height,width, N),也就是说,得到的特征图大小与原图一致了。所以,可以通过padding来控制卷积得到的特征图大小。下面是使用2D卷积的例子,需要注意的是,在PyTorch中使用图片的默认形状为(channel,height,width)。

# 随机生成输入,形状为(20,3,256,256),可以认为是生成了20张大小为(256,256,3)的彩色图像
input = torch.randn(20, 3, 256, 256)  
# 输入的channel为3,我们使用16个卷积核,也就是out channels=16
# #卷积核大小设置为3×3,stride 跨度为1,padding 填充为1
conv_layer = nn.Conv2d(3, 16, (3, 3), stride=1, padding=1)  # 初始化卷积层
output = conv_layer(input)  # 在输入时调用这个卷积层
print(output.shape)  # 输出形状为torch.Size([20, 16, 256, 256])

上面代码中可以认为使用随机函数生成了20张大小为(256, 256, 3)的图片,由于这里的卷积层使用了16个3×3的卷积核(out_channels=16)且padding为1,stride默认也是1。因此经过卷积层计算得到的特征图长和宽不变,通道数为16,最后输出的特征形状为torch.Size([20, 16, 256, 256])。

2. 卷积运算

在这里插入图片描述

如图所示,假设卷积神经网络接收的原始输入图像是一张包含了几个“十”字的图像,它由一系列包含灰度信息的像素构成。与此同时,卷积神经网络的一次卷积运算需要有相应的卷积核。这个卷积核可以看作一张小图,这相当于人头脑中目标的模板。卷积运算就是在原始图像中搜索与卷积核相似的区域,即用卷积核从左到右、从上到下地进行逐个像素的扫描和匹配,并最终将匹配结果表示成一张新的图像,通常称为特征图。特征图上有灰有白,每个像素灰度的高低代表了模板与原始图像相应位置的匹配程度,相似程度越高,就越白。这个特征图就相当于我们在头脑中标记出来与模板匹配的拖鞋的位置。

那么,这个过程在数学上是如何进行的呢?

​ 首先,我们要把图像数值化,变成矩阵,其中数值是0~255的整数;其次,我们要把卷积核数值化,也可以将其看作一张3×3的小图像,每个像素都是一个实数值,对应卷积层神经网络的权重,也就是2.1图中锥体所表示的连边。其中,一条连边就对应卷积核(模板)中的一个像素,连边上的权重大小就对应了卷积核(模板)中每个像素的数值。卷积运算实际上是一个多步的过程。第一步,卷积核与原始图像左上角第一片3×3的区域做内积,也就是把对应位置相乘,然后再把这些数字相加,结果就会输出为特征图左上角的第一个像素,如下图所示:

在这里插入图片描述

第二步,卷积核与原始图像左上角第二片3×3的区域做内积,也就是让卷积核内的数值与每一个位的原始图像像素数值相乘,并把最后的结果相加,于是就得到了特征图上第二个像素的数值,如下图所示:

在这里插入图片描述

第三步,卷积核与原始图像左上角第三片3×3的区域做内积。第四步,当做完第一行每个3×3区域的内积之后,再往下滑动一格,做第二行3×3区域的内积,如下图所示:

在这里插入图片描述

卷积核不断从左到右、从上到下地移动,与下一个对应的原始图像做相应运算,得到特征图的下一个像素的输出……就这样,卷积核不断移动计算输出,得到特征图的像素,直到覆盖原始图像,特征图的计算就完成了。结果如下图所示:

在这里插入图片描述

假设原始图像的尺寸是n,卷积核的宽度是w,特征图的大小一般是(n-w+1)x(n-w+1),所以特征图会比原始图像小一些。如果不想让特征图变小,就需要采用补齐(padding)技术将原始图扩大,并用0来填充补充的区域,如下图所示:

在这里插入图片描述

这样卷积以后得到的特征图与原始图大小一样,还是5×5。

多个卷积核与特征图对于同一张原始输入图像,我们可以用不同的卷积核与其相作用,每个卷积核就相当于不同的模板。每一个卷积核在原始图像的运算结果都可以得到一个不同的特征图,如图所示:

在这里插入图片描述

从神经网络的角度看,特征图上每一个像素(神经元)都和原图上3×3大小的一个方形区域的像素相连(即9个连接),每条连边对应卷积核小矩阵的一个单元,数的大小对应连边上的数字,称为权重值。该权重值可学习,可调节。一层卷积可能有多个卷积核,用不同颜色表示,如下图所示:

在这里插入图片描述

我们可以将多个特征图拼在一起组成立方体,从而表示多个特征图。因此,立方体的厚度是多少,就有多少特征图,也就有多少个卷积核。厚度为2,就有两个特征图、两个卷积核。如下图所示,特征图的厚度是100,即100个125×125的特征图,也就有100个卷积核:

在这里插入图片描述

3. 池化层

在构建卷积神经网络时,会用到一个非常重要的层——池化层。
什么是池化层呢?
池化层是另一种滑动窗口类型的层,池化层也有一个池化核,但它没有可训练的权重,当池化核在图片上滑动时,会直接应用某种类型的统计函数选择窗口中的内容。
最常见的池化层称为最大池化,它会选择池化核中像素的最大值。还有其他变种,如平均池化,平均池化会计算池化核所覆盖像素的平均值,在某些情况下也会使用。我们一般使用最大池化。

下图是最大池操作的示例:

在这里插入图片描述

为什么要使用池化层呢?通过上图中可以看出,最大池化能直接缩小输入的大小,这样池化层向下采样的过程就减少了模型中的参数数量。不仅如此,为了降低参数数量,一般会使用比较小的卷积核,卷积核视野很小。所谓视野,是指卷积核所能覆盖的输入图像的面积,小视野的卷积核只能提取比较小的特征。例如表面纹理,池化层将图像的高和宽减小后,卷积核间接覆盖的区域就会变大,从而能够识别更加抽象的特征。

在卷积神经网络中,一般交叉使用卷积层和池化层,这样多层叠加后,特征图像会越来越小,卷积核的视野相当于在不断地放大,从而提取更高阶抽象的特征。在PyTorch中,可选择使用nn.MaxPool2d()方法来初始化一个最大池化层,但因池化层并没有可训练的参数,在实际构建卷积神经网络时,为了省去池化层初始化这一步,我们常常使用torch.max_pool2d()方法来直接应用最大池化。这个方法最重要的一个参数是kernel_size,也就是池化核的大小,举例来说,如果设置池化核的参数kernel_size=2,池化层计算后,输出的高和宽会变为原来的一半。代码如下:

import torch

# 随机生成批次图像,形状为(64,3,256,256)
img_batch = torch.randn((64, 3, 256, 256))
pool_out = torch.max_pool2d(img_batch, kernel_size=(2, 2))  # 应用最大池化
print(pool_out.shape)  # 输出形状为torch.Size([64, 3, 128, 128])

上述代码中生成了批次图像,形状为(64, 3, 256, 256),经过最大池化运算后,输出形状为(64, 3, 128, 128),可以看到图像的高和宽均变为原来的一半,这是因为当调用torch.max_pool2d()方法应用最大池化时,设置了kernel_size为(2, 2),这表示池化核将从2×2大小的输入中选择最大的值作为输出,这样的效果就是高和宽均缩小为原来的一半。

所以简单来说,池化的作用实际上就是获取粗粒度信息,因此它可以将原始图变小。这个过程模拟了人类从更宏观的尺度观察事物,即俯瞰整个森林而不是树木的过程。这里这种模糊化的运算就体现为将多个方格的原始图像压缩为一格像素点,从而忽略信息。

4. 卷积神经网络的整体架构

LeNet-5网络是Yann LeCun在1998年设计的用于手写数字识别的卷积神经网络,曾被美国大多数银行用来识别支票上的手写数字,它是早期卷积神经网络中最有代表性的模型之一。LeNet-5总共有7层,其结构如下图所示:

在这里插入图片描述

LeNet-5模型中主要由2个卷积层、2个池化层、3个全连接层组成。模型的前面部分是两个卷积层加池化层组合,通过卷积提取特征,然后使用池化层对图片进行下采样;卷积层采用的是5×5大小的卷积核,卷积核每次滑动一个像素(stride=1);池化层采用平均池化,使用2×2的池化核,即上一层的4个节点求均值得到池化输出,且输入域不重叠,即每次滑动2个像素,这样的结果就是经过池化层后图像会变为原来一半大小。

经过卷积和池化处理后,生成的特征图会越来越小,但通道数越来越大,也可以说越来越厚了。卷积部分结束后,通过2个全连接层,最后是输出层。这就是卷积神经网络最早、最经典的架构之一,模型通过交叉使用卷积层和池化层,实现对图片特征的提取和下采样,使得图片越来越小、特征层越来越多,也就是图像越来越厚,最后展平为二维数据,连接全连接层得到输出。

通过对LeNet-5网络结构的分析,可以直观地了解卷积神经网络的一般结构形式,有助于后续学习、分析、构建更复杂、更多层的卷积神经网络。LeNet-5模型也充分证明了CNN能够有效提取图像特征、识别图像视觉上的规律。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
神经网络(Convolutional Neural Network,CNN)是一种深度学习算法,主要用于图像处理和计算机视觉任务,如图像分类、目标检测和语义分割等。CNN可以通过学习特征来自动提取图像中的有用信息,从而实现高效的图像处理和识别。 CNN的核心思想是卷操作,它可以从输入图像中提取出特征图。卷操作类似于滤波器,通过对输入图像进行滑动窗口的方式,对每个窗口内的像素进行加权求和,得到一个新的像素值。这个新的像素值就是特征图中的一个像素,它表示了输入图像中某个区域的特征。通过堆叠多个卷层和池化层,可以不断地提取更高级别的特征,最终得到图像的全局特征表示。 机器视觉(Computer Vision)是一种人工智能技术,用于处理和解释数字图像和视频数据。它主要涉及到图像处理、模式识别、计算机图形学等多个领域。机器视觉可以应用于许多实际场景,如自动驾驶、安防监控、医学影像分析等。 机器视觉的主要任务包括图像分类、目标检测和语义分割等。图像分类是指将一张图像分为不同的类别,如识别一张猫的照片。目标检测是指在图像中定位和识别出多个目标,如识别一张照片中的多个人脸。语义分割是指将图像分割成多个区域,并为每个区域分配一个语义标签,如识别一张地图中的不同区域。 总的来说,卷神经网络是实现机器视觉任务的重要算法之一,通过学习图像的特征来实现高效的图像处理和识别。机器视觉应用广泛,可以解决许多实际问题,为人们的生活和工作带来便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰履踏青云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值