图片一般用的是三维的张量,也就是:
三维就是 长度*高度*通道数,在长宽里面每一个长度、宽度都包含了一个像素,像素里面包含了三个数字(RGB这三个通道的),为了能够输入进神经网络,就把这三维拉直成一个tensor:
从图片可以看出,这样的数据量其实是非常巨大的,于是我们想要简化。那么,我们是如何进行图片识别的?
比如我们识别一个鸟,是通过它的特定部分(比如鸟嘴、爪子)识别的,因此,我们可以对输入信息进行简化,并不需要图片所有的信息,而是只需要特定的部分。
我们可以自己设定Receptive field,每一个神经元都只关心自己的Receptive field里面发生的事:
神经元是如何关心自己的Receptive field里面发生的事情呢?
比如图中是3*3*3的向量,它把这个向量拉直,成为27维的向量,作为Neuron的输入,Neuron会给这个向量的每个维度一个weight,所以有27个weight,再加上bias得到神经元的输出,这个输出又送给下一层神经元作为输入。
各个不同 Receptive Field 之间的关系,是怎么样呢?
再往右移两格就超出了影像的范围:
同样的 Pattern 可能会出现在图片的不同区域里面,比如鸟嘴可能出现在图片的左上角,也可能出现在图片的中间,虽然它们的形状都是一样的,都是鸟嘴,但是它们可能出现在图片的不同的位置。
其实不管鸟嘴出现在哪里,都没有关系,反正一定是在某一个 Receptive Field 的范围内,那个 Receptive Field,一定有一组 Neuron 在照顾,假设其中有一个 Neuron可以侦测鸟嘴,那鸟嘴不管出现在图片的哪里,都会被侦测出来。
但问题是,这些侦测鸟嘴的 Neuron,它们做的事情其实是一样的,只是它们守备的范围是不一样的感受野,我们真的需要每一个守备范围,都去放一个侦测鸟嘴的 Neuron 吗?
如果不同的守备范围,都要有一个侦测鸟嘴的 Neuron,那你的参数量不就太多了吗?
让不同 Receptive Field 的 Neuron共享参数,也就是做 Parameter Sharing权值共享。
所谓共享参数就是,这两个 Neuron 它们的 weights完全是一样的:
刚才已经说过,每一个 Receptive Field,它都有一组 Neuron 在负责守备,比如说 64 个 Neuron,所以左上角这个 Receptive Field有 64 个 Neuron,右下角这个 Receptive Field 也有 64 个 Neuron。
我们这边用一样的顏色,就代表说这两个 Neuron,共享一样的参数,所以其实每一个 Receptive Field都只有一组参数而已。
这些参数有一个名字,叫做 Filter,所以这两个红色 Neuron,它们共用同一组参数,这组参数就叫 Filter1,橙色这两个 Neuron 它们共同一组参数,这组参数就叫 Filter2,以此类推,有64个 Filter。
CNN 的 Model 的 Bias 比较大,这不一定是什么坏事:
用滤波器来进行解释:Convolutional 的 Layer 里面有很多的 Filter
这些 Filter 的大小是, 3 × 3 × Channel 的 Size。如果是彩色图片的话,那就是 RGB 三个 Channel;如果是黑白的图片的话,它的 Channel 就为 1。
一个 Convolutional 的 Layer 里面有一排的 Filter,每一个 Filter 都是一个 3 × 3 × Channel 这么大的 Tensor。
每一个 Filter 的作用就是抓取图片里面某一个 Pattern(Pattern的大小要在 3 × 3 × Channel的范围内,才能够被这些 Filter 抓出来)
那这些 Filter,怎么去图片里面抓 Pattern 呢?
对于Filter1:
这个 Filter 里面,它对角线的地方都是1,所以它看到 Image 里面也出现连三个 1 的时候,它的数值会最大。
所以会发现左上角、左下角的值最大,就告诉我们这个图片左上角、左下角有出现这个三个 1 连在一起的 Pattern。
所以每一个 Filter,都会给我们产生一群数字,如果我们有 64 个 Filter,我们就得到 64 群的数字了,这一群数字叫做 Feature Map。
所以当我们把一张图片,通过一个 Convolutional Layer,里面有一堆 Filter 的时候,我们产生出来了一个 Feature Map。
那假设这个 Convolutional Layer裡面,它有 64 个 Filter,就产生出64个 Feature Map,每一组Feature Map的大小在这个例子裡面是 4 × 4,这个 Feature Map你可以看成是另外一张新的图片。
只是这个图片的 Channel 它有 64 个,而且这并不是 RGB 原图的 Channel。在这里每一个 Channel 对应一个 Filter,原图有三个 Channel,通过一个 Convolution,它变成一张新的图片,有 64 个 Channel。
这个 Convolutional Layer 是可以叠很多层的,刚才是叠了第一层。如果叠加第二层,第二层的 Convolution 裡面,也有一堆的 Filter,那每一个 Filter 呢,它的大小我们这边也设 3 × 3,那它的高度必须设为 64(这个高度就是它要处理的影像的 Channel)。
只要network够深,就可以侦察到足够大小的范围:
上图中,第二层的3×3的Filter在探测时,左上角和右下角的-1、-2分别对应上面原图的两个3 × 3的红色格子。
所以当我们考虑第一个 Convolutional Layer 输出的 Feature Map 的 3 × 3 的范围的时候,我们在原来的影像上,其实是考虑了一个 5 × 5 的范围。
所以 Network 叠得越深,同样是 3 × 3 的大小的 Filter,它看的范围就会越来越大。
所以 Network 够深,就不用怕侦测不到比较大的 Pattern。
第一个版本里面神经元共用的参数,就是第二个版本的故事里面的 Filter,上图中颜色与权重对应。
在刚才第一个版本的故事里面,我们说不同的 Neuron 可以 Share Weight,然后去守备不同的范围,而 Share Weight 这件事,其实就是我们把 Filter 扫过一张图片:
Filter 扫过一张图片这件事,其实就是 Convolution。就是对于不同的 Receptive Field, Neuron 可以共用参数,而这组共用的参数,就叫做一个 Filter。
我们把一张比较大的图片做二次抽样。举例来说把偶数的列都拿掉,奇数的行都拿掉,图片变成原来的1/4,但是不会影响裡面是什麼东西,其实就是把一张大的图片缩小。
Pooling 本身没有参数,所以它不是一个 Layer,它裡面没有 Weight,它没有要 Learn 的东西,所以 Pooling 比较像是一个激活函数,比较像是 Sigmoid , ReLU 那些,因為它裡面是没有要 Learn 的东西的,它就是一个运算符,它的行为都是固定好的,不需要根据 Data 学任何东西。
每一个 Filter 都产生一把数字,要做 Pooling 的时候,我们就把这些数字几个几个一组,然后 Pooling。
所以我们做完 Convolution 以后,往往后面还会搭配 Pooling, Pooling 做的事情就是把图片变小,做完 Convolution 以后我们会得到一张图片,这一张图片裡面有很多的 Channel, 那做完 Pooling 以后,我们就是把这张图片的 Channel 不变,本来 64 个 Channel 还是 64 个 Channel,但是我们会把图片变得比较狭长一点。
比如 4×4 的图片变成 2×2 的图片。
一般在实作上,往往就是 Convolution 跟 Pooling 交替使用。
但是Pooling始终还是有伤害,现在计算量上来了,很多影像电视的 Network 的设计,往往也开始把 Pooling 丢掉,他会做 Full Convolution 的 Neural Network,也就是整个 Network 里面统统都是 Convolution,完全都不用 Pooling。
做完几次 Convolution 以后,接下来会把 Output 做 Flatten(把影像里面本来排成矩阵的样子的东西拉直,把所有的数值拉直变成一个向量),再把这个向量,丢进 Fully Connected 的 Layer 里面。最终你可能还要过个 Softmax,然后最终得到影像辨识的结果。
这就是一个经典的影像辨识的Network,裡面有 Convolution,有 Pooling 有 Flatten,最后再通过几个,Fully Connected 的 Layer 或 Softmax,最终得到影像辨识的结果。
这是一个经典的分类问题。
Network 的输入是一个向量,我们把一个棋盘表示成一个 19 × 19 维的向量,在这个向量里面表示棋子的位置(比如黑子填 1 ,白子填 -1,没有子填 0)。
把这个向量输到一个 Network 里面,然后就可以把下围棋当作一个分类的问题,让 Network 去预测下一步应该落子的位置落在哪裡最好。
所以下围棋,就是一个有 19 × 19 个类别的分类的问题,Network 会 Output 在这19 × 19 个类别裡面,哪一个类别是最好的,应该要选择下一步落子的位置应该在哪里。所以这个问题完全可以用一个 Fully Connected 的 Network 来解决,但是用 CNN 的效果更好。
因为可以把棋盘看成像素 19 × 19 的图片(很小),里面每一个像素就代表棋盘上一个可以落子的位置。
在 AlphaGo 的原始论文中,每一个棋盘的位置,是用 48 个 Channel 来描述的,也就是说棋盘上的每一个位置,它都用 48 个数字来描述那个位置发生了什么事。
围棋中没有用Pooling,因为它很精细,不能轻易Pooling。
CNN 除了下围棋还有影像以外, 近年来也用在语音上,也用在文字处理上。
但是如果你真的想把 CNN 用在语音、用在这个文字处理上,要仔细看一下文献上的方法。在语音、文字上, Receptive Field 的设计、参数共享的设计和影像上不是一样的。
所以要考虑清楚那些 Receptive Field 用在语音,用在文字上的设计跟影像上不是一样,是考虑了语音跟文字的特性以后所设计的。
所以你不要以為在影像上的 CNN,直接套到语音上它也 Work,可能是不 Work 的,你要想清楚说影像,语音有什麼样的特性,那你要怎麼设计合适的 Receptive Field。
比如,给 CNN 看的狗都是上面这个大小,它可以辨识说这是一只狗,当你把这个图片放大的时候,它可以辨识说牠还是一只狗吗,可能是不行的。
对它来说虽然这两张图片的形状是一模一样的,但是如果你把它拉长成向量的话,它裡面的数值就是不一样的,所以对 CNN 来说,虽然你人眼一看觉得它形状很像,但对 CNN 的 Network 来说它是非常不一样。
所以事实上,CNN 并不能够处理影像放大缩小,或者是旋转的问题,当它今天在某种大小的影像上,假设你里面的物件都是比较小的,它在上面学会做影像辨识,你把物件放大它就会整个惨掉。
所以 CNN 并没有你想像的那麼强,那就是为什么在做影像辨识的时候,往往都要做 Data Augmentation(数据增强),所谓 Data Augmentation 的意思就是说,你把你的训练资料,每张图片都裡面截一小块出来放大,让 CNN 有看过不同大小的 Pattern,然后把图片旋转,让它有看过说,某一个物件旋转以后长什麼样子,CNN 才会做到好的结果。
CNN 这个不能够处理缩放和旋转的问题,有一个架构叫 Special Transformer Layer,可以处理这个问题(录像在上图)。
Pooling是对已经被fiter处理过后的数据进行缩小化的。这里说的是CNN不能处理原图片输入有缩小和放大。