第一个Network 架构的变形是 Convolutional 的 Neural Network,它的缩写是 CNN,它是专门被用在影像上的。
Image Classification
我们都假设我们的模型输入的图片大小是固定的,都是 100 × 100 的解析度。
图片可能有大有小,今天常见的处理方式,把所有图片都先 Rescale 成大小一样,再丢到影像的辨识系统裡面。
我们模型的输出应该是什麼呢,我们模型的目标是分类,所以我们会把每一个类别,表示成一个 One-Hot 的 Vector。
假设我们现在类别是一个猫的话,那猫所对应的 Dimension,它的数值就是 1,其他的东西所对的 Dimension 的数值就是 0。
那这个 Dimension 的长度就决定了,你现在的模型可以辨识出多少不同种类的东西,如果你向量的长度是 2000,就代表说你这个模型,可以辨识出 2000 种不同的东西。
我的模型的输出通过 Softmax 以后,输出是 ŷ,然后我们希望 y 和 ŷ 的 Cross Entropy 越小越好。
接下来的问题是怎麼把一张影像当做一个模型的输入,其实对於一个 Machine 来说,一张图片其实是一个三维的 Tensor。
一张图片它是一个三维的 Tensor,其中一维代表图片的宽,另外一维代表图片的高,还有一维代表图片的 Channel 的数目。
一张彩色的图片,今天它每一个 Pixel,都是由 R G B 三个顏色所组成的,所以这三个 Channel 就代表了 R G B 三个顏色,那长跟宽就代表了今天这张图片的解析度,代表这张图片裡面有的 Pixel像素的数目。
那接下来我们就要把这一个三维的 Tensor拉直,就可以丢到一个 Network 裡面去了,那最直觉的方法就是直接拉直它。
在这个例子裡面有 100 × 100×3 个数字,把这些数字通通拿出来排成一排,就是一个巨大的向量,这个向量可以作為 Network 的输入。而这个向量裡面,每一维它裡面存的数值,其实就是某一个 Pixel某一个顏色的强度,每一个 Pixel 有 R G B 三个顏色所组成。
如果我们把向量当做 Fully Connected Network 的输入,我们 Input 这边 Feature Vector,它的长度就是 100 × 100 × 3。
那假设我们现在的,第一层的 Neuron 的数目有 1000 个,那我们现在第一层的 Weight,就有 1000×100 × 100×3,也就是 3×10 的 7 次方。
虽然随著参数的增加,我们可以增加模型的弹性,我们可以增加它的能力,但是我们也增加了 Overfitting 的风险,
那我们怎麼减少在做影像辨识的时候,怎麼避免使用这麼多的参数呢?
那考虑到影像辨识这个问题本身的特性,其实我们并不一定需要 Fully Connected 这件事,我们其实不需要每一个 Neuron,跟 Input的每一个 Dimension 都有一个 Weight。
Observation 1
第一个观察是,对影像辨识这个问题而言,假设我们想要知道这张图片裡面有一隻动物,它要做的就是侦测说现在这张图片裡面,有没有出现一些特别重要的 Pattern。
但是假设我们现在用 Neuron 做的事情,其实就是判断说现在有没有某种 Pattern 出现,那也许我们并不需要每一个 Neuron都去看一张完整的图片。因為这一些重要的 Pattern,比如说鸟嘴、眼睛、鸟爪,并不需要看整张完整的图片,才能够得到这些资讯。
所以这些 Neuron 也许根本就不需要,把整张图片当作输入,它们只需要把图片的一小部分当作输入,就足以让它们侦测某些特别关键的 Pattern有没有出现了。
Simplification 1
根据这个观察,我们就可以做第一个简化。
在 CNN 裡面有一个这样的做法,我们会设定一个区域叫做 Receptive Field,每一个 Neuron 都只关心自己的 Receptive Field 裡面发生的事情。
举例来说 你会先定义说这个蓝色的 Neuron,它的守备范围就是这一个 Receptive Field,这个裡面有 3×3×3 个数值,那对蓝色的 Neuron 来说,它只需要关心这一个小范围就好了,不需要在意整张图片裡面有什麼东西。
它要做的事情就是:
- 把这 3×3×3 的数值拉直,变成一个长度是 3×3×3 也就是 27 维的向量,再把这 27 维的向量作為这个 Neuron 的输入。
- 这个 Neuron 会给 27 维的向量的每一个 Dimension 一个 Weight,所以这个 Neuron 有 3×3×3 27个 Weight。
- 再加上 Bias 得到的输出,这个输出再送给下一层的 Neuron 当作输入,
所以每一个 Neuron,它只考虑自己的 Receptive Field,那这个 Receptive Field 要怎麼决定出来呢,那这个就要问你自己了。
- 你可以说这边有个蓝色的 Neuron,它就看左上角这个范围,这是它的 Receptive Field
- 另外又有另外一个黄色的 Neuron,它是看右下角这个 3×3×3 的范围
- 那你甚至可以两个不同的 Neuron,它们守备看到的范围是一样的。
……
如果你说你要设计很奇怪的 Receptive Field,去解决很特别的问题,那完全是可以的,这都是你自己决定的。
Simplification 1 – Typical Setting
虽然 Receptive Field 你可以任意设计,但也有最经典的 Receptive Field 的安排方式——看所有的 Channel。
一般在做影像辨识的时候,你可能不会觉得有些 Pattern 只出现某一个 Channel 裡面,所以会看全部的 Channel。既然会看全部的 Channel我们在描述一个 Receptive Field 的时候,只要讲它的高跟宽就好了,就不用讲它的深度,反正深度一定是考虑全部的 Channel,而这个高跟宽合起来叫做 Kernel Size。
常见的 Receptive Field 设定方式,就是 Kernel Size 3×3,然后一般同一个 Receptive Field,不会只有一个 Neuron 去关照它,往往会有一组一排 Neuron 去守备它,比如说 64 个 或者是 128 个 Neuron 去守备一个 Receptive Field 的范围。
到目前為止我们讲的都是一个 Receptive Field,那各个不同 Receptive Field 之间的关係,是怎麼样呢,你会把你在最左上角的这个 Receptive Field,往右移一点,然后製造一个另外一个 Receptive Field,这个移动的量叫做 Stride。
像在这个例子裡面 Stride 就等於 2,那 Stride 是一个你自己决定的 Hyperparameter。但这个 Stride 你往往不会设太大,因為你希望这些 Receptive Field之间是有重叠的,因為假设 Receptive Field 完全没有重叠,那有一个 Pattern 就正好出现,在两个 Receptive Field 的交界上面,那就会变成没有任何 Neuron 去侦测它,那你也可能就会 Miss 掉这个 Pattern,所以我们希望 Receptive Field 彼此之间有高度的重叠。
那假设我们设 Stride = 2,它移动的时候超出了影像的范围怎麼办呢?
超出范围做 Padding,Padding 就是补 0,其实也有别的补值的方法,Padding 就是补值的意思。
除了这个横著移动,你也会这个垂直移动。
在这边呢我们一样垂直方向 Stride 也是设 2。所以你有一个 Receptive Field按照这个方式,扫过整张图片,图片裡面每一个位置,都有一群 Neuron 在侦测那个地方,有没有出现某些 Pattern。
Observation 2
第二个观察就是,同样的 Pattern,它可能会出现在图片的不同区域裡面,
比如说鸟嘴这个 Pattern,虽然它们的形状都是一样的 都是鸟嘴,但是它们可能出现在图片裡面的不同的位置。
按照我们刚才的讨论,你同样的 Pattern,出现在图片的不同的位置,似乎也不是太大的问题。因為出现在左上角的鸟嘴,它一定落在某一个 Receptive Field 裡面,因為 Receptive Field 是移动完之后会覆盖满整个图片的,所以图片裡面没有任何地方不是在某个 Neuron 的守备范围内。
那假设在那个 Receptive Field 裡面,有一个 Neuron 它的工作,就是侦测鸟嘴的话,那鸟嘴就会被侦测出来。
这些侦测鸟嘴的 Neuron,它们做的事情其实是一样的,只是它们守备的范围是不一样,我们真的需要每一个守备范围,都去放一个侦测鸟嘴的 Neuron 吗?
如果不同的守备范围,都要有一个侦测鸟嘴的 Neuron,那你的参数量不会太多了吗?
Simplification 2
如果放在影像处理上的话,我们能不能够让不同 Receptive Field 的 Neuron共享参数,也就是做 Parameter Sharing权值共享。
所谓共享参数就是,这两个 Neuron 它们的 weights完全是一样的,我这边特别用顏色来告诉你说,它们的 weights 完全是一样的。
- 上面这个 Neuron 的第一个 weight,叫做 w1,下面这个 Neuron 的第一个 weight 也是 w1,它们是同一个 weight,我用红色来表示。
- 上面这个 Neuron 的第二个 weight 是 w2,下面这个 Neuron 的第二个 weight 也是w2,它们都用黄色来表示,以此类推。
上面这个 Neuron 跟下面这个 Neuron,它们守备的 Receptive Field 是不一样的,但是它们的参数是一模一样的。
那有人可能就会问说,它的参数是一模一样,那它会不会输出永远都是一样?
不会,因為它们的输入是不一样的,这两个 Neuron 的参数一模一样,但是它们照顾的范围是不一样的,所以它的输出不会跟上面这个 Neuron 一样。
Simplification 2 – Typical Setting
我们让一些 Neuron 可以共享参数,那至於要怎麼共享,你完全可以自己决定。如下是常见的在影像辨识上面的共享的方法。
每一个 Receptive Field,它都有一组 Neuron 在负责守备。比如说 64 个 Neuron,所以这个 Receptive Field有 64 个 Neuron,另外一个也有 64 个 Neuron。
我们这边用一样的顏色,就代表说这两个 Neuron,共享一样的参数。所以其实每一个 Receptive Field都只有一组参数而已。
那这些参数有一个名字,叫做 Filter。所以这两个红色 Neuron,它们共用同一组参数,这组参数就叫 Filter1,橙色这两个 Neuron 它们共同一组参数,这组参数就叫 Filter2 ……
Benefit of Convolutional Layer
目前已经讲了两个简化的方法,那我们来整理一下我们学到了什麼,这是 Fully Connected 的 Network。
它是弹性最大的,但有时候不需要看整张图片,也许只要看图片的一小部分就可以侦测出重要的 Pattern,所以我们有了 Receptive Field 的概念。
当我们强制一个 Neuron只能看一张图片裡面的一个范围的时候,它的弹性是变小的。如果是 Fully Connected 的 Network,它可以决定看整张图片,还是只看一个范围,就如果它只想看一个范围,就把很多 Weight 设成 0,就只看一个范围,所以加入 Receptive Field 以后,你的 Network 的弹性是变小的。
接下来我们还有权值共享,权值共享又更进一步限制了 Network 的弹性
加入参数共享以后,就意味著说某一些 Neuron参数要一模一样,所以这又更增加了对 Neuron 的限制,而 Receptive Field 加上 Parameter Sharing,就是 Convolutional Layer。
有用到 Convolutional Layer 的 Network,就叫 Convolutional Neural Network,就是 CNN。
所以从这个图上啊,你可以很明显地看出,其实 CNN 的 Bias 比较大,它的 Model 的 Bias 比较大。Model 的 Bias 大,不一定是坏事。
- 因為当 Model Bias 小,Model 的 Flexibility 很高的时候,它比较容易 Overfitting。Fully Connected Layer可以做各式各样的事情,它可以有各式各样的变化,但是它可能没有办法在任何特定的任务上做好。
- 而 Convolutional Layer,它是专门為影像设计的,虽然它的 Model Bias 很大,但这个在影像上不是问题,但是如果它用在影像之外的任务,你就要仔细想想,那些任务有没有我们刚才讲的影像用的特性。
Convolutional Layer
我们以上讲的,影像用的特性,其实是 CNN 的某一种介绍方式,那现在我们要讲另外一种介绍方式,第二种介绍方式跟刚才讲的介绍方式是一模一样的,只是同一个故事,用不同的版本来说明。
第二个版本是这样的,Convolutional 的 Layer 就是裡面有很多的 Filter
这些 Filter 它们的大小是 3 × 3 × Channel 的 Size,如果今天是彩色图片的话,那就是 RGB 三个 Channel,如果是黑白的图片的话,它的 Channel 就等於 1。
一个 Convolutional 的 Layer 裡面就是有一排的 Filter,每一个 Filter ,它都是一个 3 × 3 × Channel,这麼大的 Tensor。每一个 Filter 的作用就是要去图片裡面某一个 Pattern。
例子裡面,我们假设 Channel 是 1,也就是说我们图片是黑白的图片。
那我们假设这些 Filter 的参数是已知的(Filter 就是一个一个的 Tensor),那实际上这些 Tensor 裡面的数值,其实就是 Model 裡面的 Parameter,这些 Filter 裡面的数值其实是未知的,它是要透过gradient decent去找出来的。
那我们现在已经假设这些 Filter 裡面的数值已经找出来了,我们来看看这些 Filter,是怎麼跟一张图片进行运作,怎麼去图片上面把 Pattern 侦测出来的。
这是我们的图片,它是一个 6 × 6 的大小的图片。那这些 Filter的做法就是,先把 Filter 放在图片的左上角,然后把 Filter 裡面所有的值,跟左上角这个范围内的 9 个值做相乘,做完是 3。
注意!在此处卷集运算中,老师讲的内积,不要理解为线性代数中矩阵的乘法,而是filter跟图片对应位置的数值直接相乘,所有的都乘完以后再相加。
接下来这个 Filter 本来放在左上角,接下来就往右移一点,那这个移动的距离叫做 Stride。
我们 Stride 就设為 1,那往右移一点,然后再把这个 Filter跟这个范围裡面的数值算 Inner Product, 算出来是 -1
然后就以此类推,再往右移一点再算一下,然后这边全部扫完以后,就往下移一点再算一下,以此类推,一直到把这个 Filter 放在右下角,算出一个数值。
这个 Filter 怎麼说它在侦测 Pattern 呢?
你看这个 Filter 裡面,它对角线的地方都是1,所以它看到 Image 裡面也出现连三个 1 的时候,它的数值会最大。
这个图片裡面左上角有出现 3,左上角有出现这个 Pattern,左下角有出现这个,三个 1 连在一起的 Pattern,这个是第一个 Filter。
我们把每一个 Filter,都做重复的 Process,直到把整张图片都扫完,我们又得到另外一群数值。
所以每一个 Filter,都会给我们一群数字,红色的 Filter 给我们一群数字,蓝色的 Filter 给我们一群数字。如果我们有 64 个 Filter,我们就得到 64 群的数字了,那这一群数字啊,它叫做 Feature Map。
所以当我们把一张图片,通过一个 Convolutional Layer,裡面有一堆 Filter 的时候,我们產生出来了一个 Feature Map。
那假设这个 Convolutional Layer裡面,它有 64 个 Filter,那我们產生出来64个 Feature Map,每一组在这个例子裡面是 4 × 4,这个 Feature Map你可以看成是,另外一张新的图片。只是这个图片的 Channel 它有 64 个,而且这并不是 RGB 这个图片的 Channel,在这里每一个 Channel 就对应到一个 Filter,本来一张图片它三个 Channel,通过一个 Convolution,它变成一张新的图片,有 64 个 Channel。
这个 Convolutional Layer 是可以叠很多层的,刚才是叠了第一层,那如果叠第二层会发生什麼事呢?
第二层的 Convolution 裡面,也有一堆的 Filter,那每一个 Filter 呢,它的大小我们这边也设 3 × 3,那它的高度必须设為 64。
Filter 的这个高度就是它要处理的影像的 Channel。所以刚才第一层的 Convolution,假设输入的影像是黑白的 Channel是 1,那我们的 Filter 的高度就是 1,输入的影像如果是彩色的 Channel 是 3,那 Filter 的高度就是 3。那在第二层裡面,它的输入也是一张图片,这个图片的 Channel 是 64,那 Filter 的高度就是 64。
这个 64 是前一个 Convolutional Layer 的 Filter 数目,那输出以后就是 64 个 Channel。
如果我们的 Filter 的大小一直设 3 × 3,会不会让我们的 Network,没有办法看比较大范围的 Pattern 呢,其实不会的。
如果我们一样设 3 × 3 的话,当我们看最左上角这个数值的时候,最左上角这个数值在影像上,其实是对应到这个范围,
右下角的数值在影像上,其实是对应到这个范围。
所以当我们看这 3 × 3 的范围的时候,和第一个 Convolutional Layer 的输出的这个 Feature Map 的 3 × 3 的范围的时候,我们在原来的影像上,其实是考虑了一个 5 × 5 的范围。
所以虽然我们的 Filter 只有 3 × 3,但它在影像上考虑的范围,是比较大的。今天你的 Network 叠得越深,同样是 3 × 3 的大小的 Filter,它看的范围就会越来越大。所以 Network 够深,你不用怕你侦测不到比较大的 Pattern。
刚才我们讲了两个版本的故事了,那这两个版本的故事,是一模一样的。
我们在第一个版本的故事裡面,说到了有一些 Neuron,这些 Neuron 会共用参数,这些共用的参数,就是第二个版本的故事裡面的 Filter。
我们这个 Filter 裡面有 3 × 3 × 3个数字,我这边特别还用顏色,把这些数字圈起来,告诉你说 这个 Weight 就是这个数字。
在刚才第一个版本的故事裡面,我们说不同的 Neuron它们可以 Share Weight,然后去守备不同的范围,而 Share Weight 这件事,其实就是我们把 Filter 扫过一张图片。
那把 Filter 扫过一张图片这件事,其实就是 Convolution,这就是為什麼要叫 Convolutional Layer 的关係。
那所谓的把 Filter 扫过图片这件事情,其实就是不同的 Receptive Field,Neuron 可以共用参数,而这组共用的参数,就叫做一个 Filter。
今天特别从两个不同的方向讲 CNN 这个东西,希望可以帮助你对 CNN 有更深地了解。
為什麼用 CNN 是基於两个观察。
- 第一个观察是我们不需要看整张图片。对於第一个故事而言就是,Neuron 只看图片的一小部分;对 Filter 的故事而言就是,我们有一组 Filter,每个 Filter 只看一个小范围,它只侦测小的 Pattern。
- 第二个观察是同样的 Pattern,可能出现在图片的不同的地方。所以 Neuron 间可以共用参数;对 Filter 的故事而言就是,一个 Filter 要扫过整张图片,这个就是 Convolutional Layer。
Observation 3
Convolutional Layer在做影像辨识的时候,其实还有第三个常用的东西,这个东西叫做 Pooling。
Pooling 来自於另外一个观察,我们把一张比较大的图片做 Subsampling,举例来说你把偶数的 Column 都拿掉,奇数的 Row 都拿掉,图片变成為原来的1/4,但是不会影响裡面是什麼东西,把一张大的图片缩小,这是一隻鸟,这张小的图片看起来还是一隻鸟。
那所以呢有了Pooling 这样的设计,那 Pooling 是怎麼运作的呢?
Pooling 这个东西啊,它本身没有参数,所以它不是一个 Layer,它裡面没有 Weight,它没有要 Learn 的东西。所以有人会告诉你说 Pooling 比较像是一个 Activation Function,比较像是 Sigmoid , ReLU 那些,因為它裡面是没有要 Learn 的东西的,它就是一个 Operator,它的行為都是固定好的,没有要根据 Data 学任何东西。
Pooling 其实也有很多不同的版本,我们这边讲的是 Max Pooling。
刚才说每一个 Filter 都產生一把数字,要做 Pooling 的时候,我们就把这些数字几个几个一组,比如说在这个例子裡面就是 2×2 个一组,每一组裡面选一个代表,在 Max Pooling 裡面,我们选的代表就是最大的那一个。
你不一定要选最大的那一个,这个是你自己可以决定的,Max Pooling 这一个方法是选最大的那一个,但是也有 average Pooling 就是选平均嘛,还有选几何平均的,所以有各式各样的 Pooling 的方法。
也一定要 2×2 个一组吗,这个也是你自己决定的,你要 3×3 4×4 也可以。
Convolutional Layers + Pooling
所以我们做完 Convolution 以后,往往后面还会搭配 Pooling,那 Pooling 做的事情就是把图片变小。
做完 Convolution 以后我们会得到一张图片,这一张图片裡面有很多的 Channel,那做完 Pooling 以后,我们就是把这张图片的 Channel 不变,本来 64 个 Channel 还是 64 个 Channel,但是我们会把图片变得比较狭长一点。
在刚才的例子裡面,本来 4×4 的图片,如果我们把这个 Output 的数值啊,2×2 个一组的话,那 4×4 的图片就会变成 2×2 的图片,这个就是 Pooling 所做的事情。
那一般在实作上啊,往往就是 Convolution 跟 Pooling 交替使用,就是你可能做几次 Convolution,做一次 Pooling,比如两次 Convolution 一次 Pooling,两次 Convolution 一次 Pooling。
不过你可以想见说 Pooling,对於你的 Performance,还是可能会带来一点伤害的,因為假设你今天要侦测的是非常微细的东西,那你随便做 Subsampling,Performance 可能会稍微差一点。
所以近年来你会发现,很多影像电视 Network 的设计,往往也开始把 Pooling 丢掉,他会做这种,Full Convolution 的 Neural Network,就整个 Network 裡面统统都是 Convolution,完全都不用 Pooling。
那是因為近年来运算能力越来越强,Pooling 最主要的理由是為了减少运算量,那如果今天你的运算资源,足够支撑你不做 Pooling 的话,很多 Network 的架构的设计就不做 Pooling,全 Convolution。
The whole CNN
那一般以后,你的架构就是 Convolution + Pooling,那我刚才讲过说 Pooling 是可有可无啦,今天很多人可能会选择不用 Pooling。那如果你做完几次 Convolution 以后,接下来怎麼得到最后的结果呢。
你会把 Pooling 的 Output 做一件事情,叫做 Flatten,就是把这个影像裡面本来排成矩阵的样子的东西拉直,把所有的数值拉直变成一个向量,再把这个向量丢进 Fully Connected 的 Layer 裡面。
最终你可能还要过个 Softmax,然后最终得到影像辨识的结果,这就是一个经典的影像辨识的Network。