【李宏毅机器学习2021】(三)CNN
卷积神经网络(CNN,Convolutional Neural Network)是专门用于影像识别的 Network 架构。
现在来看一个图像识别的例子:

现在的问题是怎么一张图片当成模型的输入呢?
对于机器来说,一张图片是一个三维的 tensor,即图片的宽、高和 channel 的数目。对于示例中的彩色图片有 \(100*100\) 个像素点,每个像素点都有3个 channels,即RGB 三种颜色构成。
神经网络中每个输入都是一个特征向量,直觉的做法是把三维的 tensor 拉直变成一个向量。向量中每维储存的数值代表某一个像素点的某一个颜色的强度。

假如采用 Full Connected Network,隐藏层有 1000 个神经元,那么参数的数量将会高达 \(3*10^7\)!过多的参数不仅影响了运算,还更容易导致 overfitting。考虑到影像本身的特性,其实并不需要 Full Connected Network。

Receptive Field
影像本身有什么特性呢?
观察下面图片,相信不少人会看成是一只鸟,但它其实是一只猫!

人类辨识图片的方法是看图片中的关键特征,比如鸟有鸟嘴、鸟眼、爪子等,机器可以借鉴这个思想:辨识一些关键图案(pattern)。

既然现在 Neuron 做的事情是判断图片有没有某种 Pattern 出现,那 Neuron 就没必要去看一张完整的图片,只需把图片的一小部分当做输入即可进行侦测一些特别关键的 Pattern 有没有出现。

根据观察一我们就可以做第一个简化:设定一个区域叫做 Receptive Field(感受域),每一个 Neuron 都只关心自己的 Receptive Field 里发生的事情。

Receptive Field 可以有各种各样的设计:
- 同一个 Receptive Field 可以输入到不同的 Neuron
- Receptive Field 可以重叠
- 不同的 Neuron 可以有不同大小的 Receptive Field
- Receptive Field 可以只覆盖某些 channel
- Receptive Field 除了是正方体还可以是别的形状

我们来看下 Receptive Field 的经典做法:
- 考虑全部的 channel,所以在描述 Receptive Field 时只用考虑 kernel size,即高和宽,一般不会设得太大,常为 \(3*3\)。
- 一个 Receptive Field 会有一组 Neuron 去侦测,不同的 Neuron 侦测不同的 Pattern。
- Receptive Field 往水平方向移动或往垂直方向移动,都会得到新的 Receptive Field,直到整张图片每一个位置都被 Receptive Field 覆盖。移动的量叫 stride,往往设为 1 或 2,这是希望 Receptive Field 之间能有所重叠,防止检测不到交界处上的 Pattern。
- 新的 Receptive Field 可能会超出图片的范围,需要没有值的地方进行 padding。有各种不同的 padding 方法,可以补 0、整张图片里所有值的均值等。

Parameter Sharing
观察下图,当相同的 pattern 出现在不同的区域,意味着每一个 Receptive Field 都需要被一个 Neuron 去侦测该 Pattern,参数量就太多了。

解决方法是让侦测相同 Pattern 的 Neuron 共享参数。
不同 Receptive Field 的 Neuron 共享参数,由于其输入不同,所以输出也会不同。

来看下影像识别上共享参数的经典做法:每一个 Receptive Field 都需要一组 Neuron 来侦测不同的 Pattern,每一个 Receptive Field 中侦测相同 Pattern 的 Neuron 共享同一组参数,这组参数被称为 滤波器(filter)。

总结一下前面学过的内容,没有进行任何简化之前采用的是 Full Connected Layer,具有很高的灵活性,能适应各种任务,但随着参数数量随着输入维度的增加会呈指数增长,导致模型过于复杂。
卷积层采用了 Receptive Field 和 Parameter Sharing 两种策略,大大减少了参数数量,虽然限制了模型的灵活性,但却利用了图像的特性,更适合处理图像等高维数据。

Filter
下面将从另一个角度介绍 CNN。
Convolutional Layer 里有很多 filter,不同 filter 负责检测不同的 Pattern,提取不同的特征。

filter 本质是一个 tensor,其大小可设为 \(3*3*channel\),filter 里的值其实就是参数,需要学习出来,不妨假设有一张黑白的 \(6*6\) 的图片,且 filter 已经被训练出来了,然后来看下 filter 是如何检测 Pattern 的。
filter 会在输入数据的每个位置进行滑动,与输入数据的对应区域进行点乘操作,然后将点乘结果相加得到一个输出值,扫完整张图片会得到一群数字。
在这个例子里可以看到第一个 filter 检测到的 Pattern 出现在左上角和左下角:

对所有的 filter 都进行同样的步骤,会得到很多群数字,它们叠在一起就组成了特征图(Feature Map)。

可以把 Feature Map 看作是另外一张新的“图片”,它的 channel 数量取决于 filter 数量,每一个 channel 对应一个 filter,每一个数字称为 Feature Map 的一个像素值。

Convolutional Layer 当然也可以叠很多层,对于第二层 Convolutional Layer 来说,输入是一张有 64 个 channel 的图片,所以第二层的 filter 也要有 64 个 channel!

如果 filter 的宽高一直设为 \(3*3\),会不会看不到比较大范围的 Pattern呢?答案是不会。
在第二层时 filter 的宽高仍然是 \(3*3\),但是在原来的图像上实际上是考虑了一个 \(5*5\) 的范围。所以只要 network 够深,就能侦测到够大的 Pattern。

本节从两个角度来介绍 CNN,但其实两者是一模一样的:
filter 扫过整张图片其实就是不同的 Receptive Field 的功能一样的 Neuron 可以共享参数,这组共享参数就是一个 filter。


Pooling
CNN 在做图像识别时还有第三个常用的东西——池化(Pooling)。
对一张比较大的图片做子采样,如把偶数行、奇数列都拿掉,图片变为原来的 1/4,还是能辨别出图片的内容。

Pooling 就是用于减小特征图的空间尺寸来降低计算复杂度,加快网络的训练速度,同时保留重要的特征信息。
Pooling 主要有两种常见的类型:最大池化(Max Pooling)和平均池化(Average Pooling)。
在最大池化中,对于每个池化窗口,只取窗口中的最大值作为输出;而在平均池化中,取窗口中的所有值的平均值作为输出。这样做的目的是通过保留最显著的特征来减小特征图的空间尺寸,从而降低计算复杂度,加快训练速度,并且有助于网络的泛化能力。
假设池化窗口是 \(2*2\),最大池化操作如下:
池化操作通常在卷积层之后使用,可以在卷积神经网络的不同层次进行多次池化。通常情况下,每个池化操作都会减小特征图的尺寸,使得特征图在深度方向上保持不变,但在宽度和高度方向上减小。这有助于提取更高级别的特征,同时减少网络的参数数量。

注:Pooling 操作会丢弃特征图中的部分信息,随着技术的提高,运算能力越来越强,可以不用 Pooling 操作来提高精确度。
经典的影像辨识的network
一个经典的影像辨识的network 在卷积层做完后还有经过 Flatten,将 tensor 拉直成向量,然后丢入全连接层里,最后经过 softmax 处理后才得到图像辨识的结果。

应用
CNN 不仅可以用在影像识别上,还能用于下围棋。

需要注意的是 Pooling 操作去掉行、列会极大影响结果,知名的 Alpha Go 就是不用 Pooling 的。
除此之外,CNN 也能用于语音处理和自然语言处理,不过要重新设计 Receptive Field。

缺点
CNN 不能处理放大、缩小、旋转的问题。比如,CNN 训练出来的模型面对一个比训练图片放大的数据,可能就不能有效识别了。要通过数据增强,对原始图片进行放大、缩小、旋转产生新的图片,然后投入训练才能解决这几个问题。
当然,Spatial Transformer Layer 是可以处理上述问题的网络。

本文来自博客园,作者:hzyuan,转载请注明原文链接:https://www.cnblogs.com/hzyuan/p/18034533
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)