以算法区分深度学习应用,算法类别可分成三大类:
一般来说,当我们直接用fully connected feedforward network来做影像处理的时候,往往会需要太多的参数。而CNN做的事就是简化neural network的架构。
比如,两张鸟嘴在两张图片的不同位置,nerual侦测左上角的鸟嘴和侦测中央的鸟嘴做的事情是一样的。我们并不需要两个neural去做两组参数,我们要求这两个neural用同一组参数,就样就可以减少需要参数的量。
我们知道一个image可以做subsampling,把一个image的奇数行,偶数列的pixel(像素)拿掉,变成原来十分之一的大小,这其实不会影响人对这张image的理解。对你来说:这两张image看起来可能没有太大的差别,是没有太大的影响的。所以我们就可以用这样的概念把image变小,这样就可以减少需要的参数。
假设现在我们的network的input是一张 6 ∗ 6 6 * 6 6∗6的image,如果是黑白的,一个pixel就只需要用一个value去描述它。在convolution layer里面,它由一组filter,(其中每一个filter其实就等同于是fully connected layer里面的一个neuron),每一个filter在这里就是一个matrix( 3 ∗ 3 3 * 3 3∗3),这每个filter里面的参数(matrix里面每一个element值)就是network的parameter(这些parameter是要学习出来的,并不是需要人去设计的)。
第一个filter是一个 3 ∗ 3 3 * 3 3∗3的matrix,把这个filter放在image的左上角,把filter的9个值和image的9个值做内积,内积的结果就得到3。然后向右移动。
把filter往右移动到右边界,接下来往下移动一格,再从左到右继续移动,以此类推,直到把filter移到右下角的时候,得到的值如上图所示。
上图中的蓝色直线代表了左上和左下出现所得到结果中的最大的值,说明这个filter要侦测的pattern出现在这张image的左上角和左下角,这件事情就考虑了property2。即同一个pattern出现在了左上角的位置和左下角的位置,我们就可以用Filter1侦测出来,并不需要不同的filter来做这件事。
在一个convolution layer里面会有很多的filter,另外的filter会有不同的参数(如图中显示的Filter2),它也做跟Filter1一模一样的事情,从而得到了另一个 4 ∗ 4 4 * 4 4∗4的matrix。
若换成彩色的image,而彩色的image是由RGB组成的,所以一个彩色的image就是好几个matrix叠在一起,就是一个立方体。如果要处理彩色image,这时候filter不是一个matrix,而是一个立方体。如果用RGB表示一个pixel的话,那么input就是 3 ∗ 6 ∗ 6 3 * 6 * 6 3∗6∗6,filter就是 3 ∗ 3 ∗ 3 3 * 3 * 3 3∗3∗3。
在做convolution时将filter的值和image的值做内积(不是把每一个channel分开来算,而是合在一起来算,一个filter就考虑了不同颜色所代表的channel)。即通道方向上有多个特征图时,会按照通道输入数据和过滤器的卷积运算,并将结果相加。如下图所示。
在fully connected中,一个neural应该连接所有的input(这里有36个pixel当做input,则这个neuron应连接在36个input上),但是现在只连接了9个input(侦测一个pattern,不需要看整张image,看9个input就行),这样做就用了比较少的参数。
两个neural本来在fully connected里面有自己的weight,但当我们在做convolution时,把每一个neural连接的weight减少,强迫这两个neural共用一个weight,这件事叫做shared weight。当我们做这件事的时候,我们用的参数就比原来的更少。
比如说,我们把同一深度的平面叫做深度切片(depth slice)(e.g. a volume of size [55x55x96] has 96 depth slices, each of size [55x55]),那么同一个切片应该共享同一组权重和偏置。
池化操作对每个深度切片独立,规模一般为 2 * 2 2*2 2*2,相对于卷积层进行的卷积运算,池化层进行的运算一般有以下几种:
我们根据Filter1得到 4 ∗ 4 4 * 4 4∗4的maxtrix,根据Filter2得到另一个 4 ∗ 4 4 * 4 4∗4的matrix,接下来把output4个一组,每一组里面选择它们的最大。
这就是把四个value合成一个value。这样可以让image缩小。
做完一次convolution和一次max pooling,就将原来 6 ∗ 6 6 * 6 6∗6的image变成了一个 2 ∗ 2 2 *2 2∗2的image。这个 2 ∗ 2 2 * 2 2∗2的pixel的深度取决于有几个filter。得到结果就是一个new image but smaller,一个filter就代表了一个channel。
这边有一个问题:第一次有25个filter,得到25个feature map,第二次也是有25个filter,那将其做完是不是要得到 2 5 2 25^2 252的feature map。其实不是这样的!
假设第一层filter有2个,第二层的filter在考虑这个input时是会考虑深度的,并不是每个channel分开考虑,而是一次考虑所有的channel。所以convolution有多少个filter,output就有多少个filter(convolution有25个filter,output就有25个filter。只不过,这25个filter都是一个立方体)。
唯一要改的是:network structure和input format。本来在DNN中input是一个vector,现在CNN会考虑input image的几何空间,所以不能给它一个vector。应该input一个tensor(高维的vector)。(为什么要给三维的vector?因为image的长宽高各是一维,若是彩色的话就是第三维。所以要给三维的tensor。)
……
Deep Dream是说:如果你给machine一张image,它会在这张image里加上它看到的东西。咋样做这件事情呢?你先找一张image,然后将这张image丢到CNN中,把它的某一个hidden layer拿出来(vector),它是一个vector(假设这里是:[3.9, -1.5, 2.3…])。接下来把postitive dimension值调大,把negative dimension值调小(正的变的更正,负的变得更负)。把这个(调节之后的vector)当做是新的image的目标(把3.9的值变大,把-1.5的值变得更负,2.3的值变得更大。然后找一张image(modify image)用GD方法,让它在hidden layer output是你设下的target)。这样做的话就是让CNN夸大化它所看到的东西。本来它已经看到某一个东西了,你让它看起来更像它原来看到的东西。本来看起来是有一点像东西,它让某一个filter有被active,但是你让它被active得更剧烈(夸大化看到的东西)。
如果你把这张image拿去做Deep Dream的话,你看到的结果是上面这样。右边有一只熊,这个熊原来是一个石头(对机器来说,这个石头有点像熊,它就会强化这件事情,所以它就真的变成了一只熊)。
Deep Dream还有一个进阶的版本,叫做Deep Style。
input一张image,再input一张image,让machine去修改这张图,让它有另外一张图的风格 (类似于风格迁移)。
其中做法的精神是这样的:原来的image丢给CNN,然后得到CNN的filter的output,CNN的filter的output代表这张image有什么content。接下来把呐喊这张图也丢到CNN里面,也得到filter的output。我们并不在意一个filter,而是在意filter和filter之间的convolution,这个convolution代表了这张image的style。
接下来用同一个CNN找一张image,这张image它的content像左边这张相片,但同时这张image的style像右边这张相片。找一张image同时可以maximize左边的图,也可以maximize右边的图。得到的结果就是这张图。