2019-09-23 22:12:13 fly975247003 阅读数 41

为什么用CNN

在这里插入图片描述
我们都知道CNN常常被用在影像处理上,如果你今天用CNN来做影像处理,当然也可以用一般的neural network来做影像处理,不一定要用CNN。比如说你想要做影像的分类,那么你就是training一个neural network,input一张图片,那么你就把这张图片表示成里面的pixel,也就是很长很长的vector。output就是(假如你有1000个类别,output就是1000个dimension)dimension。那我相信根据刚才那堂课内容,若给你一组training data你都可以描作出来。

在这里插入图片描述
但是呢,我们现在会遇到的问题是这样的,实际上我们在training neural network时,我们会期待说:在network的structure里面,每一个neural就是代表了一个最基本的classifier,事实在文件上根据训练的结果,你有可能会得到很多这样的结论。举例来说:第一层的neural是最简单的classifier,它做的事情就是detain有没有绿色出现,有没有黄色出现,有没有斜的条纹。

第二个layer是做比这个更复杂的东西,根据第一个layer的output,它看到直线横线就是窗框的一部分,看到棕色纹就是木纹,看到斜条纹+灰色可能是很多的东西(轮胎的一部分等等)

再根据第二个hidden layer的outpost,第三个hidden layer会做更加复杂的事情。

但现在的问题是这样的,当我们一般直接用fully connect feedforward network来做影像处理的时候,往往我们会需要太多的参数,举例来说,假设这是一张100 *100的彩色图(一张很小的imgage),你把这个拉成一个vector,(它有多少个pixel),它有100 *100 3的pixel。
如果是彩色图的话,每个pixel需要三个value来描述它,就是30000维(30000 dimension),那input vector假如是30000dimension,那这个hidden layer假设是1000个neural,那么这个hidden layer的参数就是有30000 *1000,那这样就太多了。那么CNN做的事就是简化neural network的架构。我们把这里面一些根据人的知识,我们根据我们对影像就知道,某些weight用不上的,我们一开始就把它滤掉。不是用fully connect feedforward network,而是用比较少的参数来做影像处理这件事。所以CNN比一般的DNN还要简单的。

等一下我们讲完会觉得发现说:你可能觉得CNN运作很复杂,但事实上它的模型是要比DNN还要更简单的。我们就是用power-knowledge 去把原来fully connect layer中一些参数拿掉就成了CNN。

Small region

在这里插入图片描述
我们先来讲一下,为什么我们有可能把一些参数拿掉(为什么可以用比较少的参数可以来做影像处理这件事情)

这里有几个观察,第一个是在影像处理里面,我们说第一层的 hidden layer那些neural要做的事就是侦测某一种pattern,有没有某一种patter出现。大部分的pattern其实要比整张的image还要小,对一个neural来说,假设它要知道一个image里面有没有某一个pattern出现,它其实是不需要看整张image,它只要看image的一小部分。

举例来说,假设我们现在有一张图片,第一个hidden layer的某一种neural的工作就是要侦测有没有鸟嘴的存在(有一些neural侦测有没有爪子的存在,有没有一些neural侦测有没有翅膀的存在,有没有尾巴的存在,合起来就可以侦测图片中某一只鸟)。假设有一个neural的工作是要侦测有没有鸟嘴的存在,那并不需要看整张图,其实我们只需要给neural看着一小红色方框的区域(鸟嘴),它其实就可以知道说,它是不是一个鸟嘴。对人来说也是一样,看这一小块区域这是鸟嘴,不需要去看整张图才知道这件事情。所以,每一个neural连接到每一个小块的区域就好了,不需要连接到整张完整的图。

Same Patterns

在这里插入图片描述
第二个观察是这样子,同样的pattern在image里面,可能会出现在image不同的部分,但是代表的是同样的含义,它们有同样的形状,可以用同样的neural,同样的参数就可以把patter侦测出来。

比如说,这张图里面有一张在左上角的鸟嘴,在这张图里面有一个在中央的鸟嘴,但是你并不需要说:我们不需要去训练两个不同的detector,一个专门去侦测左上角的鸟嘴,一个去侦测中央有没有鸟嘴。如果这样做的话,这样就太冗了。我们不需要太多的冗源,这个nerual侦测左上角的鸟嘴跟侦测中央有没有鸟嘴做的事情是一样的。我们并不需要两个neural去做两组参数,我们就要求这两个neural用同一组参数,就样就可以减少你需要参数的量

Subsampling

在这里插入图片描述
第三个是:我们知道一个image你可以做subsampling,你把一个image的奇数行,偶数列的pixel拿掉,变成原来十分之一的大小,它其实不会影响人对这张image的理解。对你来说:这张image跟这张image看起来可能没有太大的差别。是没有太大的影响的,所以我们就可以用这样的概念把image变小,这样就可以减少你需要的参数。

CNN架构

在这里插入图片描述
所以整个CNN的架构是这样的,首先input一张image以后,这张image会通过convolution layer,接下里做max pooling这件事,然后在做convolution,再做max pooling这件事。这个process可以反复无数次,反复的次数你觉得够多之后,(但是反复多少次你是要事先决定的,它就是network的架构(就像你的neural有几层一样),你要做几层的convolution,做几层的Max Pooling,你再定neural架构的时候,你要事先决定好)。你做完决定要做的convolution和Max Pooling以后,你要做另外一件事,这件事情叫做flatten,再把flatten的output丢到一般fully connected feedforward network,然后得到影像辨识的结果。

在这里插入图片描述
我们刚才讲基于三个对影像处理的观察,所以设计了CNN这样的架构。

第一个观察是,要生成一个pattern,不要看整张的image,你只需要看image的一小部分。第二是,通用的pattern会出现在一张图片的不同的区域。第三个是,我们可以做subsampling

前面的两个property可以用convolution来处理掉,最后的property可以用Max Pooling这件事来处理。等一下我们要介绍每一个layer再做的事情,我们就先从convolution开始看起。

Convolution

Propetry1

在这里插入图片描述
假设现在我们的network的input是一张6*6的Image,如果是黑白的,一个pixel就只需要用一个value去描述它,1就代表有涂墨水,0就代表没有涂到墨水。那在convolution layer里面,它由一组的filter,(其中每一个filter其实就等同于是fully connect layer里面的一个neuron),每一个filter其实就是一个matrix(3 *3),这每个filter里面的参数(matrix里面每一个element值)就是network的parameter(这些parameter是要学习出来的,并不是需要人去设计的)

每个filter如果是3* 3的detects意味着它就是再侦测一个3 *3的pattern(看3 *3的一个范围)。在侦测pattern的时候不看整张image,只看一个3 *3的范围内就可以决定有没有某一个pattern的出现。这个就是我们考虑的第一个Property

Propetry2

在这里插入图片描述
这个filter咋样跟这个image运作呢?首先第一个filter是一个3* 3的matrix,把这个filter放在image的左上角,把filter的9个值和image的9个值做内积,两边都是1,1,1(斜对角),内积的结果就得到3。(移动多少是事先决定的),移动的距离叫做stride(stride等于多少,自己来设计),内积等于-1。stride等于2,内积等于-3。我们先设stride等于1。

在这里插入图片描述
你把filter往右移动一格得到-1,再往右移一格得到-3,再往右移动一格得到-1。接下里往下移动一格,得到-3。以此类推(每次都移动一格),直到你把filter移到右下角的时候,得到-1(得到的值如图所示)

经过这件事情以后,本来是6 *6的matrix,经过convolution process就得到4 *4的matrix。如果你看filter的值,斜对角的值是1,1,1。所以它的工作就是detain1有没有1,1,1(连续左上到右下的出现在这个image里面)。比如说:出现在这里(如图所示蓝色的直线),所以这个filter就会告诉你:左上跟左下出现最大的值

就代表说这个filter要侦测的pattern,出现在这张image的左上角和左下角,这件事情就考虑了propetry2。同一个pattern出现在了左上角的位置跟左下角的位置,我们就可以用filter 1侦测出来,并不需要不同的filter来做这件事。

[外链图片转存失败(img-WHuHYylG-1569216404710)(res/chapter21-12.png)]

在一个convolution layer 里面会有很多的filter(刚才只是一个filter的结果),那另外的filter会有不同的参数(图中显示的filter2),它也做跟filter1一模一样的事情,在filter放到左上角再内积得到结果-1,依次类推。你把filter2跟 input image做完convolution之后,你就得到了另一个4*4的matrix,红色4 *4的matrix跟蓝色的matrix合起来就叫做feature map,看你有几个filter,你就得到多少个image(你有100个filter,你就得到100个4 *4的image)

在这里插入图片描述
刚才举的例子是一张黑白的image,所以input是一个matrix。若今天换成彩色的image,彩色的image是由RGB组成的,所以,一个彩色的image就是好几个matrix叠在一起,就是一个立方体。如果要处理彩色image,这时候filter不是一个matrix,filter而是一个立方体。如果今天是RGB表示一个pixel的话,那input就是3*6 *6,那filter就是3 *3 *3。

在做convolution的话,就是将filter的9个值和image的9个值做内积(不是把每一个channel分开来算,而是合在一起来算,一个filter就考虑了不同颜色所代表的channel)

convolution和fully connected之间的关系

在这里插入图片描述
convolution就是fully connected layer把一些weight拿掉了。经过convolution的output其实就是一个hidden layer的neural的output。如果把这两个link在一起的话,convolution就是fully connected拿掉一些weight的结果。

在这里插入图片描述
我们在做convolution的时候,我们filter1放到左上角(先考虑filter1),然后做inner product,得到内积为3,这件事情就等同于把6* 6的image拉直(变成如图所示)。然后你有一个neural的output是3,这个neural的output考虑了9个pixel,这9个pixel分别就是编号(1,2,3,7,8,9,13,14,15)的pixel。这个filter做inner product以后的output 3就是某个neuron output 3时,就代表这个neuron的weight只连接到(1,2,3,7,8,9,13,14,15)。这9个weight就是filter matrix里面的9个weight(同样的颜色)

在fully connected中,一个neural应该是连接在所有的input(有36个pixel当做input,这个neuron应连接在36个input上),但是现在只连接了9个input(detain一个pattern,不需要看整张image,看9个input就好),这样做就是用了比较少的参数了。

在这里插入图片描述
将stride=1(移动一格)做内积得到另外一个值-1,假设这个-1是另外一个neural的output,这个neural连接到input的(2,3,4,8,9,10,14,15,16),同样的weight代表同样的颜色。在9个matrix

当我们做这件事情就意味说:这两个neuron本来就在fully connect里面这两个neural本来是有自己的weight,当我们在做convolution时,首先把每一个neural连接的wight减少,强迫这两个neural共用一个weight。这件事就叫做shared weight,当我们做这件事情的时候,我们用的这个参数就比原来的更少。

Max pooling

在这里插入图片描述
在这里插入图片描述
相对于convolution来说,Max Pooling是比较简单的。我们根据filter 1得到4*4的maxtrix,根据filter2得到另一个4 *4的matrix,接下来把output ,4个一组。每一组里面可以选择它们的平均或者选最大的都可以,就是把四个value合成一个value。这个可以让你的image缩小。

在这里插入图片描述
假设我们选择四个里面的max vlaue保留下来,这样可能会有个问题,把这个放到neuron里面,这样就不能够微分了,但是可以用微分的办法来处理的

在这里插入图片描述
做完一个convolution和一次max pooling,就将原来6 * 6的image变成了一个2 *2的image。这个2 *2的pixel的深度depend你有几个filter(你有50个filter你就有50维),得到结果就是一个new image but smaller,一个filter就代表了一个channel。

在这里插入图片描述
这件事可以repeat很多次,通过一个convolution + max pooling就得到新的 image。它是一个比较小的image,可以把这个小的image,做同样的事情,再次通过convolution + max pooling,将得到一个更小的image。

这边有一个问题:第一次有25个filter,得到25个feature map,第二个也是由25个filter,那将其做完是不是要得到25225^2的feature map。其实不是这样的!

假设第一层filter有2个,第二层的filter在考虑这个imput时是会考虑深度的,并不是每个channel分开考虑,而是一次考虑所有的channel。所以convolution有多少个filter,output就有多少个filter(convolution有25个filter,output就有25个filter。只不过,这25个filter都是一个立方体)

Flatten

在这里插入图片描述
flatten就是feature map拉直,拉直之后就可以丢到fully connected feedforward netwwork,然后就结束了。

CNN in Keras

在这里插入图片描述
唯一要改的是:network structure和input format,本来在DNN中input是一个vector,现在是CNN的话,会考虑 input image的几何空间的,所以不能给它一个vector。应该input一个tensor(高维的vector)。为什么要给三维的vector?因为image的长宽高各是一维,若是彩色的话就是第三维。所以要给三维的tensor

model.add(Convolution2D( 25, 3, 3)

25代表有25个filter,3 *3代表filter是一个3 *3的matrix

Input_shape=(28,28,1)

假设我要做手写数字辨识,input是28 *28的image,每个pixel都是单一颜色。所以input_shape是(1,28,28)。如果是黑白图为1(blacj/white),如果是彩色的图时为3(每个pixel用三个值来表述)。

MaxPooling2D(( 2, 2 ))

2,2表示把2*2的feature map里面的pixel拿出来,选择max value

[外链图片转存失败(img-8gaVNQfM-1569216404736)(res/chapter21-24.png)]

假设我们input一个1 *28 * 28的image,你就可以写model.add(Convolution2D( 25, 3, 3, Input_shape=(28,28,1)))。通过convplution以后得到output是25 *26 26(25个filter,通过3 *3得到26 * 26)。然后做max pooling,2 *2一组选择 max value得到 25 *13 * 13

然后在做一次convolution,假设我在这选50个filter,每一个filter是3 *3时,那么现在的channel就是50。13 *13的image通过3 *3的filter,就成11 *11,然后通过2 *2的Max Pooling,变成了50 *5 *5

在第一个convolution layer里面,每一个filter有9个参数,在第二个convolution layer里面,虽然每一个filter都是3 *3,但不是3 *3个参数,因为它input channel 是25个,所以它的参数是3 *3 *25(225)。

在这里插入图片描述
通过两次convolution,两次Max Pooling,原来是1 *28 *28变为50 *5 *5。flatten的目的就是把50 *5 *5拉直,拉直之后就成了1250维的vector,然后把1250维的vector丢到fully connected。

CNN学到了什么?

在这里插入图片描述
很多人常会说:deep learning就是一个黑盒子,然后你learn以后你不知道它得到了什么,所以有很多人不喜欢用这种方法。但还有很多的方法分析的,比如说我们今天来示范一下咋样分析CNN,它到底学到了什么。

分析input第一个filter是比较容易的,因为一个layer每一个filter就是一个3*3的mmatrix,对应到3 *3的范围内的9个pixel。所以你只要看到这个filter的值就可以知道说:它在detain什么东西,所以第一层的filter是很容易理解的,但是你没有办法想要它在做什么事情的是第二层的filter。在第二层我们也是3 *3的filter有50个,但是这些filter的input并不是pixel(3 *3的9个input不是pixel)。而是做完convolution再做Max Pooling的结果。所以这个3 *3的filter就算你把它的weight拿出来,你也不知道它在做什么。另外这个3 *3的filter它考虑的范围并不是3 *3的pixel(9个pixel),而是比9个pxiel更大的范围。不要这3 *3的element的 input是做完convolution再加Max Pooling的结果。所以它实际上在image上看到的范围,是比3 *3还要更大的。那我们咋样来分析一个filter做的事情是什么呢,以下是一个方法。

我们知道现在做第二个convolution layer里面的50个filter,每一个filter的output就是一个matrix(11*11的matrix)。假设我们现在把第k个filter拿出来,它可能是这样子的(如图),每一个element我们就叫做aijka_{ij}^k(上标是说这是第k个filter,i,j代表在这个matrix里面的第i row和第j column)。

接下来我们定义一个东西叫做:“Degree of the activation of the k-th filter”,我们定义一个值代表说:现在第k个filter有多被active(现在的input跟第k个filter有多match),第k个filter被启动的Degree定义成:这个11*11的 matrix里面全部的 element的summation。(input一张image,然后看这个filter output的这个11 *11的值全部加起来,当做是这个filter被active的程度)

截下来我们要做的事情是这样子的:我们想知道第k个filter的作用是什么,所以我们想要找一张image,这张image它可以让第k个filter被active的程度最大。

假设input一张image,我们称之为X,那我们现在要解的问题就是:找一个x,它可以让我们现在定义的activation Degree aka^k最大,这件事情要咋样做到呢?其实是用gradient ascent你就可以做到这件事(minimize使用gradient descent,maximize使用gradient ascent)

这是事还是蛮神妙的,我们现在是把X当做我们要找的参数用gradient ascent做update,原来在train CNN network neural的时候,input是固定的,model的参数是你需要用gradient descent找出来的,用gradient descent找参数可以让loss被 minimize。但是现在立场是反过来的,现在在这个task里面,model的参数是固定的,我们要让gradient descent 去update这个X,可以让这个activation function的Degree of the activation是最大的。

在这里插入图片描述
这个是得到的结果,如果我们随便取12个filter出来,每一个filter都去找一张image,这个image可以让那个filter的activation最大。现在有50个filter,你就要去找50张image,它可以让这些filter的activation最大。我就随便取了前12个filter,可以让它最active的image出来(如图)。

这些image有一个共同的特征就是:某种纹路在图上不断的反复。比如说第三张image,上面是有小小的斜条纹,意味着第三个filter的工作就是detain图上有没有斜的条纹。那不要忘了每一个filter考虑的范围都只是图上一个小小的范围。所以今天一个图上如果出现小小的斜的条纹的话,这个filter就会被active,这个output的值就会比较大。那今天如果让图上所有的范围通通都出现这个小小的斜条纹的话,那这个时候它的Degree activation会是最大的。(因为它的工作就是侦测有没有斜的条纹,所以你给它一个完整的数字的时候,它不会最兴奋。你给它都是斜的条纹的时候,它是最兴奋的)

所以你就会发现:每一个filter的工作就是detain某一张pattern。比如说:第三图detain斜的线条,第四图是detain短的直线条,等等。每一个filter所做的事情就是detain不同角度的线条,如果今天input有不同角度的线条,你就会让某一个activation function,某一个filter的output值最大

分析全连接层

在这里插入图片描述
在做完convolution和Max Pooling以后,要做一件事情叫做flatten,把flatten的结果丢到neural network里面去。那我们想要知道:在这个neural network里面,每一个neural的工作是什么。

我们要做的事情是这样的:定义第j个neural,它的output叫做$a_j$。接下来我们要做事情就是:找一张image(用gradient ascent的方法找一张X),这个image X你把它丢到neural network里面去,它可以让$a_j$的值被maximize。找到的结果就是这样的(如图)

如图是随便取前9个neural出来,什么样的图丢到CNN里面可以让这9个neural最被active output的值最大,就是这9张图(如图)

这些图跟刚才所观察到图不太一样,在刚在的filter观察到的是类似纹路的图案,在整张图上反复这样的纹路,那是因为每个filter考虑是图上一个小小的range(图上一部分range)。现在每一个neural,在你做flatten以后,每个neural的工作就是去看整张图,而不是是去看图的一小部分。

在这里插入图片描述
那今天我们考虑是output呢?(output就是10维,每一维对应一个digit)我们把某一维拿出来,找一张image让那个维度output最大。那我们会得到咋样的image呢?你可以想象说:每一个output,每一个dimension对应到某一个数字。

现在我们找一张image,它可以让对应在数字1的output 最大,那么那张image显然就像看起来是数字1。你可以期待说:我们可以用这个方法让machine自动画出数字。

但是实际上我们得到的结果是这样子的,每一张图分别代表数字0-9。也就是说:我们到output layer对应到0那个neuron,其实是这样的(如图),以此类推。你可能会有疑惑,为什么是这样子的,是不是程序有bug。为了确定程序没有bug,再做了一个实验是:我把每张image(如图)都丢到CNN里面,然后看它classifier的结果是什么。CNN确定就说:这个是1,这个是,…,这个是8。CNN就觉得说:你若拿这张image train出来正确率有98的话,就说:这个就是8。所以就很神奇

这个结果在很多的地方有已经被观察到了,今天的这个neuron network它所学到东西跟我们人类是不太一样的(它所学到的东西跟我们人类想象和认知不一样的)。你可以查看这个链接的paper(如图)

相关的paper

让图更像数字

在这里插入图片描述

我们有没有办法让这个图看起来更像数字呢?想法是这样的:一张图是不是数字我们有一些基本的假设,比如说:这些就算你不知道它是什么数字(显然它不是digit),人类手写出来的就不是这个样子。所以我们应该对x做constraint,我们告诉machine,有些x可能会使y很大但不是数字。我们根据人的power-knowledge就知道,这些x不可能是一些数字。那么我们可以加上咋样的constraint呢?(图中白色的亮点代表的是有墨水的,对一个digit来说,图白的部分其实是有限的,对于一个数字来说,一整张图的某一个小部分会有笔画,所以我们应该对这个x做一些限制)

假设image里面的每一个pixel用xijx_{ij}来表示,(每一个image有28 *28的pixel)我们把所有image上i,ji,j的值取绝对值后加起来。如果你熟悉machine learning的话,这一项就是L1-regularization。然后我们希望说:在找一个x可以让yiy^i最大的同时让xij|x_{ij}|的summation越小越好。也就是我们希望找出的image,大部分的地方是没有涂颜色的,只有非常少的部分是有涂颜色的。如果我们加上constraint以后我们得到的结果是这样的(如右图所示),跟左边的图比起来,隐约可以看出来它是一个数字(得到的结果看起来像数字)

你可能会有一个问题,绝对值咋样去微分,下堂课会讲到

你如果加上一些额外的constraint,比如说:你希望相邻的pixel
是同样的颜色等等,你应该可以得到更好的结果。不过其实有更多很好的方法可以让machine generate数字

Deep Dream

在这里插入图片描述
其实上述的想法就是Deep Dream的精神,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

Deep style

今天input一张image,input一张image,让machine去修改这张图,让它有另外一张图的风格 (类似于风格迁移)


在这里插入图片描述

得到的结果就是这样子的

在这里插入图片描述
这里给一个reference给参考

其中做法的精神是这样的:原来的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右边的图。那你得到的结果就是像最底下的这张图。用的就是刚才讲的gradient ascent的方法找一张image,然后maximize这两张图,得到就是底下的这张图。

CNN的应用

围棋

在这里插入图片描述
我们现在CNN已经在很多不同的应用上,而不是只有影像处理上。比如:CNN现在有一个很知名的应用,就用用在下围棋上面。为什么CNN可以用来下围棋上面呢?

我们知道如果让machine来下围棋,你不见得需要用CNN。其实一般的topic neuron network也可以帮我们做到这件事情。你只要learn一个network(也就是找一个function),它的input是棋盘,output是棋盘上的位置。也就是说:你根据这个棋盘的盘式,如果你下一步要落子的话,你落子的位置其实就可以让machine学会。

所以你用Fully-connected feedforward network也可以帮我们做到让machine下围棋这件事情。也就是你只要告诉input是一个19 *19的vector,每一个vector的dimension对应到棋盘上面的每一个位置。machine就可以学会下围棋了。
如果那个位置有一个黑子的话就是1,如果有一个白子的话就是-1,反之就是0。

但是我们这边采用CNN的话,我们会得到更好的performance。我们之前举的例子是把CNN用在影像上面,也就是input是matrix(也就是把19*19的vector表示成19 *19的matrix),然后当做一个image来看,然后让它output 下一步落子的位置就结束了。

在这里插入图片描述
告诉machine说:看到落子在“5之五”,CNN的output就是在“天元”的地方是1,其他地方是0。看到“5之五”和“天元”都有子,CNN的output就是在“五之5”的地方是1,其他地方是0。这个是supervised部分

在这里插入图片描述
现在大家都说“AlphaGo”,都是懂懂的样子。但是自从“AlphaGo”用了CNN以后,大家都觉得说:CNN应该很厉害。所以如果你没有用CNN来处理你的问题,别人就会问你为什么不用CNN来处理问题(比如说:面试的时候),CNN不是比较强吗

什么时候应该用CNN呢?image必须有该有的那些特性,在CNN开头就有说:根据那三个观察,所以设计出了CNN这样的架构。在处理image时是特别有效的。为什么这样的架构也同样可以用在围棋上面(因为围棋有一些特性跟影像处理是非常相似的)

第一个是:在image上面,有一些pattern是要比整张image还要小的多的(比如:鸟喙是要比整张的image要小的多),只需要看那一小的部分就知道那是不是鸟喙。在围棋上也有同样的现象,如图所示,一个白子被三个黑子围住(这就是一个pattern),你现在只需要看这一小小的范围,就可以知道白子是不是没“气”了,不需要看整个棋盘才能够知道这件事情,这跟image是有同样的性质。

在“AlphaGo”里面它的第一个layer filter其实就是用5*5的filter,显然做这个设计的人觉得说:围棋最基本的pattern可能都是在5 *5的范围内就可以被侦测出来,不需要看整个棋牌才能知道这件事情。

接下来我们说image还有一个特性:同样的pattern会出现在不同的regions,而他们代表的是同样的意义,在围棋上可能也会有同样的现象。像如图这个pattern可以出现在左上角,也可以出现在右下角,它们都代表了同样的意义。所以你可以用同一个pattern来处理在不同位置的同样的pattern。所以对围棋来说,是有这两个特性的。

AlphaGo

在这里插入图片描述
但是没有办法让我想通的地方就是第三点,我们可以对一个image做subsampling,把image变为原来的1/4的大小,但是也不会影响你看这张图的样子。因为基于这个观察,所以有Max Pooling这个layer。但是对围棋来说,你可以做这件事情吗?你可以丢到奇数行偶数类,这样它还是同一个盘式吗,显然不是的,这个让我相当的困扰。

“AlphaGo”里面有用了Max Pooling这个架构,或许这是一个弱点。可以针对这个弱点去攻击它,击败它。但是“AlphaGo”(比李世石还强),没有这个显而易见的弱点

有一天我突然领悟到“AlphaGo”的CNN架构里面有什么特别的地方(“AlphaGo”Paper的附录),在“AlphaGo”Paper里面只说了一句:用CNN架构,但它没有在正文里仔细描述CNN的架构,会不会实际上CNN架构里有什么特别的玄机呢?

在“AlphaGo”Paper的附录里面,描述了neuron network structure,它的input是一个19 *19 *48的image。19 *1是可以理解,因为棋盘就是19 *19。48是咋样来的呢?对于“AlphaGo”来说,它把每一个位置都用48个value来描述。这里面的value包括:我们只要在一个位置来描述有没有白子,有没有黑子;还加上了domain-knowledge(不只是说:有没有黑子或者白子,还会看这个位置是不是出于没“气”的状态,等等)

如果读完这段你会发现:第一个layer有做 zero pads。也就是说:把原来19*19的image外围补上更多的0,让它变成23 *23的image。

第一个hidden layer用的是5*5 filter(总共有k个filter),k的值在Paper中用的是192(k=192);stride设为1;使用RLU activation function等等。

然后你就会发现“AlphaGo”是没有用Max Pooling,所以这个neuron network的架构设计就是“运用之妙,存乎一心”。虽然在image里面我们都会用Max Pooling这个架构,但是针对围棋的特性来设计neuron network的时候,我们是不需要Max Pooling这个架构的,所以在“AlphaGo”里面没有这个架构.

语音

在这里插入图片描述
CNN也可以用在其它的task里面,比如说:CNN也用在影像处理上。如图是一段声音,你可以把一段声音表示成Spectrogram(横轴是时间,纵轴是那段时间里面声音的频率),红色代表:在那段时间里那一频率的energy比较大。

这张image其实是我说“你好”,然后看到的Spectrogram。有通过训练的人,看这张image,就知道这句话的内容是什么。

人既然可以看这个image就可以知道是什么样的声音讯号,那我们也可以让机器把这个Spectrogram当做一张image。然后用CNN来判断:input一张image,它是对应什么样的声音讯号(单位可能是phone)。但是神奇的地方是:CNN里面的时候,在语音上,我们通常只考虑在frequency方向上移动的filter。也就是说:我们的filter是长方形的,其中宽是跟image的宽是一样的,我们在移动filter的时候,我们移这个方向(如图所示)

如果把filter向时间的方向移动的话,结果是没有太大的帮助。这样的原因是:在语音里面,CNN的output还会接其他的东西(比如:LSTM),所以在向时间方向移动是没有太多的帮助。

为什么在频率上的filter会有帮助呢?我们用filter的目的是:为了detain同样的pattern出现在不同的range,我们都可以用同一个的filter detain出来。那在声音讯号上面,男生跟女生发同样的声音(同样说“你好”),Spectrogram看起来是非常不一样的,它们的不同可能只是频率的区别而已(男生的“你好”跟女生的“你好”,它们的pattern其实是一样的)

所以今天我们把filter在frequency direction移动是有效的。当我们把CNN用在application时,你永远要想一想,这个application的特性是什么,根据那个application的特性来design network的structure

文本

在这里插入图片描述
相关的paper

我们知道CNN耶可以用在文字处理上面,这个是从paper截下来的图。在文字处理上面,假设你要做的是:让machine侦测这个word sequence代表的是positive还是negative。首先input一个word sequence,你把word sequence里面的每一个word都用一个vector来表示。这边的每一个vector代表word本身的sementic,如果两个word含义越接近的话,那它们的vector在高维的空间上就越接近,这个就叫做“wordembedding”(每一个word用vector来表示)。

当你把每一个word用vector来表示的时候,你把sentence所有的word排在一起,它就变成一张image。你可以把CNN套用在这个image上面。

当我们把CNN用在文字处理上的时候,你的filter其实是这个样子的(如图所示)。它的高跟image是一样的,你把filter沿着句子里面词汇的顺序来移动,然后你就会得到一个vector。不同的filter就会得到不同的vector,然后Max Pooling,然后把Max Pooling的结果丢到fully connect里面,就会得到最后的结果。在文字处理上,filter只在时间的序列上移动,不会在“embedding dimension”这个方向上移动。如果你有做过类似的task(文字处理),知道“embedding dimension”指的是什么,你就会知道在“embedding dimension”反向上移动是没有帮助的,因为在word embedding里面每一个dimension的含义其实是独立的。所以当我们如果使用CNN的时候,你会假设说:第二个dimension跟第一个dimension有某种特别的关系;第四个dimension跟第五个dimension有某种特别的关系。这个关系是重复的(这个pattern出现在不同的位置是同样的意思)。但是在word embedding里面,不同dimension是独立的(independent)。所以在embedding dimension移动是没有意义的,所以你在做文字处理的时候,你只会在sentence顺序上移动filter,这个是另外的例子。

Reference

在这里插入图片描述
如果你想知道更多visualization事情的话,以上是一些reference。

在这里插入图片描述
如果你想要用Degree的方法来让machine自动产生一个digit,这件事是不太成功的,但是有很多其它的方法,可以让machine画出非常清晰的图。这里列了几个方法,比如说:PixelRNN,VAE,GAN来給参考.

2019-09-18 18:48:31 fly975247003 阅读数 24

李弘毅机器学习笔记:第七章—深度学习的发展趋势

回顾一下deep learning的历史:

  • 1958: Perceptron (linear model)
  • 1969: Perceptron has limitation
  • 1980s: Multi-layer perceptron
    • Do not have significant difference from DNN today
  • 1986: Backpropagation
    • Usually more than 3 hidden layers is not helpful
  • 1989: 1 hidden layer is “good enough”, why deep?
  • 2006: RBM initialization (breakthrough)
  • 2009: GPU
  • 2011: Start to be popular in speech recognition
  • 2012: win ILSVRC image competition
    感知机(Perceptron)非常像我们的逻辑回归(Logistics Regression)只不过是没有sigmoid激活函数。09年的GPU的发展是很关键的,使用GPU矩阵运算节省了很多的时间。

深度学习的三个步骤

我们都知道机器学习有三个step,对于deep learning其实也是3个步骤:
在这里插入图片描述

  • Step1:神经网络(Neural network)
  • Step2:模型评估(Goodness of function)
  • Step3:选择最优函数(Pick best function)

那对于深度学习的Step1就是神经网络(Neural Network)

Step1:神经网络

神经网络(Neural network)里面的节点,类似我们的神经元。

在这里插入图片描述
神经网络也可以有很多不同的连接方式,这样就会产生不同的结构(structure)在这个神经网络里面,我们有很多逻辑回归函数,其中每个逻辑回归都有自己的权重和自己的偏差,这些权重和偏差就是参数。
那这些神经元都是通过什么方式连接的呢?其实连接方式都是你手动去设计的。

完全连接前馈神经网络

概念:前馈(feedforward)也可以称为前向,从信号流向来理解就是输入信号进入网络后,信号流动是单向的,即信号从前一层流向后一层,一直到输出层,其中任意两层之间的连接并没有反馈(feedback),亦即信号没有从后一层又返回到前一层。
在这里插入图片描述

  • 当已知权重和偏差时输入(1,1)(1,-1)​的结果
  • 当已知权重和偏差时输入(1,0)(-1,0)的结果
    在这里插入图片描述
    上图是输入为1和-1的时候经过一系列复杂的运算得到的结果
    在这里插入图片描述
    当输入0和0时,则得到0.51和0.85,所以一个神经网络如果权重和偏差都知道的话就可以看成一个函数,他的输入是一个向量,对应的输出也是一个向量。不论是做回归模型(linear model)还是逻辑回归(logistics regression)都是定义了一个函数集(function set)。我们可以给上面的结构的参数设置为不同的数,就是不同的函数(function)。这些可能的函数(function)结合起来就是一个函数集(function set)。这个时候你的函数集(function set)是比较大的,是以前的回归模型(linear model)等没有办法包含的函数(function),所以说深度学习(Deep Learning)能表达出以前所不能表达的情况。

我们通过另一种方式显示这个函数集:

全链接和前馈的理解
  • 输入层(Input Layer):1层
  • 隐藏层(Hidden Layer):N层
  • 输出层(Output Layer):1层
    在这里插入图片描述
  • 为什么叫全链接呢?
    • 因为layer1与layer2之间两两都有连接,所以叫做Fully Connect;
  • 为什么叫前馈呢?
    • 因为现在传递的方向是由后往前传,所以叫做Feedforward。
深度的理解

那什么叫做Deep呢?Deep = Many hidden layer。那到底可以有几层呢?这个就很难说了,以下是老师举出的一些比较深的神经网络的例子
在这里插入图片描述
在这里插入图片描述

  • 2012 AlexNet:8层
  • 2014 VGG:19层
  • 2014 GoogleNet:22层
  • 2015 Residual Net:152层
  • 101 Taipei:101层

随着层数变多,错误率降低,随之运算量增大,通常都是超过亿万级的计算。对于这样复杂的结构,我们一定不会一个一个的计算,对于亿万级的计算,使用loop循环效率很低。

这里我们就引入矩阵计算(Matrix Operation)能使得我们的运算的速度以及效率高很多:

矩阵计算

如下图所示,输入是 [1211]\begin{bmatrix}&1&-2\\ &-1&1\end{bmatrix},输出是[0.980.12]\begin{bmatrix}&0.98\\ &0.12\end{bmatrix}
计算方法就是:sigmoid(权重w【黄色】 * 输入【蓝色】+ 偏移量b【绿色】)= 输出
在这里插入图片描述

其中sigmoid更一般的来说是激活函数(activation function),现在已经很少用sigmoid来当做激活函数。

如果有很多层呢?
a1=σ(w1x+b1)a2=σ(w1a1+b2)y=σ(wLaL1+bL)a^1 = \sigma (w^1x+b^1) \\ a^2 = \sigma (w^1a^1+b^2) \\ ··· \\ y = \sigma (w^La^{L-1}+b^L) ​

在这里插入图片描述
计算方法就像是嵌套,这里就不列公式了,结合上一个图更好理解。所以整个神经网络运算就相当于一连串的矩阵运算。
在这里插入图片描述
从结构上看每一层的计算都是一样的,也就是用计算机进行并行矩阵运算。
这样写成矩阵运算的好处是,你可以使用GPU加速。
整个神经网络可以这样看:

本质:通过隐藏层进行特征转换

把隐藏层通过特征提取来替代原来的特征工程,这样在最后一个隐藏层输出的就是一组新的特征(相当于黑箱操作)而对于输出层,其实是把前面的隐藏层的输出当做输入(经过特征提取得到的一组最好的特征)然后通过一个多分类器(可以是softmax函数)得到最后的输出y。
在这里插入图片描述

示例:手写数字识别

举一个手写数字体识别的例子:
输入:一个16*16=256维的向量,每个pixel对应一个dimension,有颜色用(ink)用1表示,没有颜色(no ink)用0表示
输出:10个维度,每个维度代表一个数字的置信度。
在这里插入图片描述
从输出结果来看,每一个维度对应输出一个数字,是数字2的概率为0.7的概率最大。说明这张图片是2的可能性就是最大的
在这里插入图片描述
在这个问题中,唯一需要的就是一个函数,输入是256维的向量,输出是10维的向量,我们所需要求的函数就是神经网络这个函数
在这里插入图片描述
从上图看神经网络的结构决定了函数集(function set),所以说网络结构(network structured)很关键。

在这里插入图片描述
接下来有几个问题:

  • 多少层? 每层有多少神经元?
    这个问我们需要用尝试加上直觉的方法来进行调试。对于有些机器学习相关的问题,我们一般用特征工程来提取特征,但是对于深度学习,我们只需要设计神经网络模型来进行就可以了。对于语音识别和影像识别,深度学习是个好的方法,因为特征工程提取特征并不容易。
  • 结构可以自动确定吗?
    有很多设计方法可以让机器自动找到神经网络的结构的,比如进化人工神经网络(Evolutionary Artificial Neural Networks)但是这些方法并不是很普及 。
  • 我们可以设计网络结构吗?
    可以的,比如 CNN卷积神经网络(Convolutional Neural Network )

Step2: 模型评估

损失示例

在这里插入图片描述
对于模型的评估,我们一般采用损失函数来反应模型的好差,所以对于神经网络来说,我们采用交叉熵(cross entropy)函数来对yyy^\hat{y}​的损失进行计算,接下来我们就是调整参数,让交叉熵越小越好。

总体损失

在这里插入图片描述
对于损失,我们不单单要计算一笔数据的,而是要计算整体所有训练数据的损失,然后把所有的训练数据的损失都加起来,得到一个总体损失L。接下来就是在function set里面找到一组函数能最小化这个总体损失L,或者是找一组神经网络的参数θ\theta,来最小化总体损失L

Step3:选择最优函数

如何找到最优的函数和最好的一组参数呢,我们用的就是梯度下降,这个在之前的视频中已经仔细讲过了,需要复习的小伙伴可以看前面的笔记。

在这里插入图片描述
在这里插入图片描述
具体流程:θ\theta是一组包含权重和偏差的参数集合,随机找一个初试值,接下来计算一下每个参数对应偏微分,得到的一个偏微分的集合L\nabla{L}就是梯度,有了这些偏微分,我们就可以不断更新梯度得到新的参数,这样不断反复进行,就能得到一组最好的参数使得损失函数的值最小

反向传播

在这里插入图片描述
在神经网络中计算损失最好的方法就是反向传播,我们可以用很多框架来进行计算损失,比如说TensorFlow,theano,Pytorch等等

思考

为什么要用深度学习,深层架构带来哪些好处?那是不是隐藏层越多越好?

隐藏层越多越好?

在这里插入图片描述
从图中展示的结果看,毫无疑问,层次越深效果越好~~

普遍性定理

在这里插入图片描述
参数多的model拟合数据很好是很正常的。下面有一个通用的理论:
对于任何一个连续的函数,都可以用足够多的隐藏层来表示。那为什么我们还需要‘深度’学习呢,直接用一层网络表示不就可以了?在接下来的课程我们会仔细讲到

2019-09-17 15:57:57 fly975247003 阅读数 32

李弘毅机器学习笔记:第三章—Error的来源

在这里插入图片描述
从上节课测试集数据来看,Average ErrorAverage\ Error 随着模型复杂增加呈指数上升趋势。更复杂的模型并不能给测试集带来更好的效果,而这些 ErrorError 的主要有两个来源,分别是 biasbiasvariancevariance

然而 biasbiasvariancevariance 是什么?可以查看 机器学习中的Bias(偏差),Error(误差),和Variance(方差)有什么区别和联系?

估测

假设真实的模型为 f^\hat f , 如果我们知道 f^\hat f 模型,那是最好不过了,但是 f^\hat f 只有 Niamtic 公司才知道。
在这里插入图片描述
所以我们只能通过收集 Pokemon精灵 的数据,然后通过 step1~step3 训练得到我们的理想模型 ff^*ff^* 其实是 f^\hat f 的一个预估。

在这里插入图片描述
这个过程就像打靶,f^\hat f 就是我们的靶心,ff^* 就是我们投掷的结果。如上图所示,f^\hat fff^* 之间蓝色部分的差距就是偏差和方差导致的。

估测变量x的偏差和方差

我们先理解一下偏差和方差是怎样计算的呢? 偏差(Bias)和方差(Variance)——机器学习中的模型选择

评估x的偏差

  • 假设 xx 的平均值是 μ\mu,方差为 σ2\sigma^2

评估平均值要怎么做呢?

  • 首先拿到 NN 个样本点:{x1,x2,,xN}\{x^1,x^2,···,x^N\}
  • 计算平均值 mm, 得到 m=1Nnxnμm=\frac{1}{N}\sum_n x^n \neq \mu

在这里插入图片描述
但是如果计算很多组的 mm ,然后求 mm 的期望:

E[m]=E[1Nxn]=1NnE[xn]=μE[m]=E[\frac{1}{N}\sum x^n]=\frac{1}{N}\sum_nE[x^n]=\mu

这个估计呢是无偏估计(unbiased)。

然后 mm 分布对于 μ\mu 的离散程度(方差):
Var[m]=σ2NVar[m]=\frac{\sigma^2}{N}

这个取决于 NN,下图看出 NN 越小越离散:

在这里插入图片描述

估测变量x的方差

如何估算方差呢?

在这里插入图片描述
在这里插入图片描述

为什么会有很多的模型?

讨论系列02中的案例:这里假设是在平行宇宙中,抓了不同的神奇宝贝

在这里插入图片描述

用同一个model,在不同的训练集中找到的 ff^∗ 就是不一样的
在这里插入图片描述

这就像在靶心上射击,进行了很多组(一组多次)。现在需要知道它的散布是怎样的,将100个宇宙中的model画出来

在这里插入图片描述

不同的数据集之前什么都有可能发生—||

考虑不同模型的方差

一次模型的方差就比较小的,也就是是比较集中,离散程度较小。而5次模型的方差就比较大,同理散布比较广,离散程度较大。

所以用比较简单的模型,方差是比较小的(就像射击的时候每次的时候,每次射击的设置都集中在一个比较小的区域内)。如果用了复杂的模型,方差就很大,散布比较开。

这也是因为简单的模型受到不同训练集的影响是比较小的。

考虑不同模型的偏差

在这里插入图片描述

这里没办法知道真正的 f^\hat{f},所以假设图中的那条黑色曲线为真正的 f^\hat{f}

结果可视化,一次平均的 fˉ\bar{f} 没有5次的好,虽然5次的整体结果离散程度很高。

一次模型的偏差比较大,而复杂的5次模型,偏差就比较小。

直观的解释:简单的模型函数集的space比较小,所以可能space里面就没有包含靶心,肯定射不中。而复杂的模型函数集的space比较大,可能就包含的靶心,只是没有办法找到确切的靶心在哪,但足够多的,就可能得到真正的 f¯f¯。

偏差v.s.方差

在这里插入图片描述

将系列02中的误差拆分为偏差和方差。简单模型(左边)是偏差比较大造成的误差,这种情况叫做欠拟合,而复杂模型(右边)是方差过大造成的误差,这种情况叫做过拟合。

怎么判断?

分析

在这里插入图片描述

如果模型没有很好的训练训练集,就是偏差过大,也就是欠拟合
如果模型很好的训练训练集,即再训练集上得到很小的错误,但在测试集上得到大的错误,这意味着模型可能是方差比较大,就是过拟合。
对于欠拟合和过拟合,是用不同的方式来处理的

偏差大-欠拟合

此时应该重新设计模型。因为之前的函数集里面可能根本没有包含ff^*。可以:

将更多的函数加进去,比如考虑高度重量,或者HP值等等。
或者考虑更多次幂、更复杂的模型。
如果此时强行再收集更多的data去训练,这是没有什么帮助的,因为设计的函数集本身就不好,再找更多的训练集也不会更好。

方差大-过拟合

简单粗暴的方法:更多的数据

在这里插入图片描述

但是很多时候不一定能做到收集更多的data。可以针对对问题的理解对数据集做调整。比如识别手写数字的时候,偏转角度的数据集不够,那就将正常的数据集左转15度,右转15度,类似这样的处理。

模型选择

现在在偏差和方差之间就需要一个权衡
想选择的模型,可以平衡偏差和方差产生的错误,使得总错误最小
但是下面这件事最好不要做:

在这里插入图片描述
用训练集训练不同的模型,然后在测试集上比较错误,模型3的错误比较小,就认为模型3好。但实际上这只是你手上的测试集,真正完整的测试集并没有。比如在已有的测试集上错误是0.5,但有条件收集到更多的测试集后通常得到的错误都是大于0.5的。

交叉验证

在这里插入图片描述

图中public的测试集是已有的,private是没有的,不知道的。交叉验证 就是将训练集再分为两部分,一部分作为训练集,一部分作为验证集。用训练集训练模型,然后再验证集上比较,确实出最好的模型之后(比如模型3),再用全部的训练集训练模型3,然后再用public的测试集进行测试,此时一般得到的错误都是大一些的。不过此时会比较想再回去调一下参数,调整模型,让在public的测试集上更好,但不太推荐这样。(心里难受啊,大学数模的时候就回去调,来回痛苦折腾)

上述方法可能会担心将训练集拆分的时候分的效果比较差怎么办,可以用下面的方法。

N-折交叉验证

将训练集分成N份,比如分成3份。

在这里插入图片描述

比如在三份中训练结果Average错误是模型1最好,再用全部训练集训练模型1。

2019-09-25 09:24:28 fly975247003 阅读数 70

监督学习和半监督学习

在这里插入图片描述
在supervised里面,你就是有一大推的training data,这些training data的组成是一个function的input跟output,假设你有R笔train data,每一笔train data有xrx^r,y^r\hat{y}^r。假设xrx^r是一张image,y^\hat{y}是class label。semi-supervised learning是在label上面,是有另外一组unlabel的data,这组data记做xux^u,这组data只有input,没有output(U笔data)。在做semi-superised learning时,U远远大于R(unlabel的数量远远大于label data的数量)。semi-surprised learning可以分成两种,一种是transductive learning,一种是inductive learning。这两种最简单的分法是:在做transductive的时候,你的unlabel data就是你的testing data,inductive learning 就是说:不把unlabel data考虑进来。

为什么做semi-supervised learning,因为有人常会说,我们缺data,其实我们不是缺data,其实我们缺的是与label的data。比如说,你收集image很容易(在街上一直照就行了),但是这些image是没有的label。label data 是很少的,unlabel是非常多的。所以semi-surprvised learning如果可以利用这些unlabel data来做某些事是会很有价值的。

我们人类可能一直是在semi-supervised learning,比如说,小孩子会从父母那边得到一点点的supervised(小孩子在街上,问爸爸妈妈这是什么,爸爸妈妈说:这是狗。在以后的日子里,小孩子会看到很多奇奇怪怪的东西,也没有人在告诉这是什么动物,但小孩子依然还是会判别出狗)

半监督学习的好处

在这里插入图片描述
为什么semi-supervised learning有可能会带来帮助呢?假设我们现在要做分类的task,建一个猫跟狗的classifier,我们同时有一大堆猫跟狗的图片。这些图片是没有label的,并不知道哪些是猫哪些是狗。
在这里插入图片描述
那今天我们只考虑有label的猫跟狗的data,画一个boundary,将猫跟狗的train data分开的话,你可能就会画在中间(垂直)。那如果unlabel的分布长的像灰色的点这个样子的话,这可能会影响你的决定。虽然unlabel data只告诉我们了input,但unlabeled data的分布可以告诉我们一些事。那你可能会把boundary变为这样(斜线)。但是semi-supervised learning使用unlabel的方式往往伴随着一些假设,其实semi-supervised learning有没有用,是取决于你这个假设符不符合实际/精不精确。
在这里插入图片描述
这边要讲四件事,第一个是在generative model的时候,怎么用semi-supervised learning。还要讲两个还蛮通用的假设,一个是Low-density Separation Assumption,另一个是Smoothness Assumption,最后还有Better Representation

监督生成模型和半监督生成模型

监督生成模型

在这里插入图片描述
我们都已经看过,supervised generative model,在supervised learning里面有一堆train example,你知道分别是属于class1,class2。你会去估测class1,class2的probability(P(XCi)P(X|C_i))

假设每一个class它的分布都是一个Gaussion distribution,那你会估测说class1是从μ是μ1μ^1,covariance是Σ\Sigma的Gaussion估测出来的,class2是从μ是μ2μ^2,covariance是Σ\Sigma的Gaussion估测出来的。

那现在有了这些probability,有了这些μμ、covariance,你就可以估测given一个新的data做classification,然后你就会决定boundary的位置在哪里。

半监督生成模型

在这里插入图片描述
但是今天给了我们一些unlabel data,它就会影响你的决定。举例来说,我们看左边这笔data,我们假设绿色这些使unlabel data,那如果你的μ\mu跟variance是μ1\mu ^1,μ2,Σ\mu ^2,\Sigma显然是不合理的。今天这个Σ\Sigma应该比较接近圆圈,或者说你在sample的时候有点问题,所以你sample出比较奇怪的distribution。比如说,这两个class label data是比较多的(可能class2是比较多的,所以这边probability是比较大的),总之看这些unlabel data以后,会影响你对probability,μ\mu,Σ\Sigma的估测,就影响你的probability的式子,就影响了你的decision boundary。
在这里插入图片描述
对于实际过程中的做法,我们先讲操作方式,再讲原理。先初始化参数(class1,class2的几率,μ1\mu ^1,μ2,Σ\mu ^2,\Sigma,这些值,你可以用已经有label data先估测一个值,得到一组初始化的参数,这些参数统称θ\theta

  • Step1 先计算每一笔unlabel data的 posterior probability,根据现有的θ\theta计算每一笔unlabel data属于class1的几率,那这个几率算出来是怎么样的是和你的model的值有关的。

  • Step2 算出这个几率以后呢,你就可以update你的model,这个update的式子是非常的直觉,这个C1C_1的probability是怎么算呢,原来的没有unlabel data的时候,你的计算方法可能是:这个N是所有的example,N1N_1是被标注的C1C_1example,如果你要算C1C_1的probability,这件事情太直觉了,如果不考虑unlabel data的话(感觉就是N1N_1除以N)。但是现在我们要考虑unlabel data,那根据unlabel告诉我们的咨询,C1C_1是出现次数就是所有unlabel data它是C1C_1posterior probability的和。所有unlabel data而是根据它的posterior probability决定它有百分之多少是属于C1C_1,有多少是属于C2C_2μ1\mu^1怎么算呢,原来不考虑unlabel data时,μ1\mu^1就是把所有C1C_1的label data都平均起来就结束了。如果今天加上unlabel data的话,其实就是把unlabel data的每一笔dataxux^u根据它的posterior probability做相乘。如果这个xux^u比较偏向class1C1C^1的话,它对class1的影响就大一点,反之就小一点。(不用解释这是为什么这样,因为这太直觉了)C2C_2的 probability就是这样的做的μ1,μ2,\mu^1,\mu^2,\sum也都是这样做的,有了新的model,你就会做step1,有了新的model以后,这个几率就不一样了,这个几率不一样了,在做step2,你的model就不一样了。这样update你的几率,然后就反复反复的下去。理论上这个方法会保证收敛,但是它的初始值跟GD会影响你收敛的结果。

这里的Step1就是Estep,而Step2就是Mstep(也就是熟悉的EM算法)

在这里插入图片描述
我们现在来解释下为什么这样做的:想法是这样子的。假设我们有原来的label data的时候,我们要做的事情是maximum likehood,每一笔train data 它的likehood是可以算出来的。把所有的 log likehood加起来就是log total loss。然后去maximum。那今天是unlabel data的话今天是不一样的。unlabel data我们并不知道它是来自哪一个class,我们咋样去估测它的几率呢。那我们说一笔unlabel dataxux^u出现的几率(我不知道它是从claas1还是class2来的,所以class1,class2都有可能)就是它在C1C_1的posterior probability跟C1C_1这个class产生这笔unlabel data的几率加上C2C_2的posterior probability乘以C2C_2这个class产生这笔unlabel data的几率。把他们通通合起来,就是这笔unlabel data产生的几率。

接下来要做事情就是maximum这件事情。但是由于不是凸函数,所以你要去iteratively solve这个函数

假设一:Low-density Separation

在这里插入图片描述
那接下来我们讲一个general的方式,这边基于的假设是Low-density Separation,也就是说:这个世界非黑即白的。什么是非黑即白呢?非黑即白意思就是说:假设我们现在有一大堆的data(有label data,也有unlabel data),在两个class之间会有一个非常明显的红色boundary。比如说:现在两边都是label data,boundary 的话这两条直线都是可以的,就可以把这两个class分开,在train data上都是100%。但是你考虑unlabel data的话,左边的boundary是比较好的,右边的boundary是不好的。因为这个假设是基于这个世界是一个非黑即白的世界,这两个类之间会有一个很明显的界限。Low-density separation意思就是说,在这两个class交界处,density是比较低的。

Self-training

在这里插入图片描述
Low-density separation最简单的方法是self-training。self-training就是说,我们有一些label data并且还有一些unlabel data。接下来从label data中去train一个model,这个model叫做ff^\ast,根据这个ff^\ast去label你的unlabel data。你就把xux^u丢进ff^\ast,看它吐出来的yuy^u是什么,那就是你的label data。那这个叫做pseudo-label。那接下来你要从你的unlabel data set中拿出一些data,把它加到labeled data set里面。然后再回头去train你的ff^\ast

在做regression时是不能用这一招的,主要因为把unlabeled data加入到训练数据中,ff^\ast并不会受影响

在这里插入图片描述
你可能会觉得slef-training它很像是我们刚才generative model里面用的那个方法。他们唯一的差别就是在做self-training的时候,你用的是hard label;你在做generative mode时,你用的是soft model。在做self-training的时候我们会强制一笔train data是属于某一个class,但是在generative model的时候,根据它的posterior probability 它有一部分是属于class1一部分是属于class2。那到底哪一个比较好呢?那如果我们今天考虑的neural network的话,你可以比较看看哪一个方法比较好。

假设我们用neural network,你从你的 label data得到一笔network parameter(θ\theta^\ast)。现在有一笔unlabel dataxux^u,根据参数θ\theta^\ast分为两类(0.7的几率是class1,0.3的几率是class2)。如果是hard label的话,你就把它直接label成class1,所以xux^u新的target第一维是1第二维是0(拿xux^utrain neural network)。如果去做soft的话。70 percent是属于class1,30percent是属于class2,那新的target是0.7跟0.3。在neural network中,这两个方法你觉得哪个是有用的呢,soft这个方法是没有用的,一定要用hard label。因为本来输出就是0.7和0.3,目标又设成0.7和0.3,相当于自己证明自己,所以没用。但我们用hard label 是什么意思呢?我们用hard label的时候,就是用low-density separation的概念。也就是说:今天我们看xux^u它属于class1的几率只是比较高而已,我们没有很确定它一定是属于class1的,但这是一个非黑即白的世界,如果你看起来有点像class1,那就一定是class1。本来根据我的model说:0.7是class1 0.3是class2,那用hard label(low-density-separation)就改成它属于class1的几率是1(完全就不可能是class2)。soft是不会work的。

基于熵的正则化

在这里插入图片描述
刚才那一招有进阶版是“Entropy-based Regularization”。如果你用neural network,你的output是一个distribution,那我们不要限制说这个output一定要是class1、class2,但是我们做的假设是这样的,这个output distribution一定要是很集中,因为这是一个非黑即白的世界。假设我们现在做五个class的分类,在class1的几率很大,在其他class的几率很小,这个是好的。在class5的几率很大,在其他class上几率很小,这也是好的。如果今天分布很平均的话,这样是不好的(因为这是一个非黑即白的世界),这不是符合low-density separation的假设。

但是现在的问题是咋样用数值的方法evaluate这个distribution是好的还是不好的。这边用的是entropy,算一个distribution的entropy,这个distribution entropy告诉你说:这个distribution到底是集中的还是不集中的。我们用一个值来表示distribution是集中的还是分散的,某一个distribution的entropy就是负的它对每一个class的几率乘以log class的几率。所以我们今天把第一个distribution的几率带到这个公式里面去,只有一个是1其他都是0,你得到的entropy会得到是0(E(yu)=m=15ymu(lnyu)E(y^u)=-\sum_{m=1}^{5}y^u_m(lny^u)),第二个也是0。第三个entropy是ln5ln5​。散的比较开(不集中)entropy比较大,散的比较窄(集中)entropy比较小。

所以我们需要做的事情是,这个model的output在label data上分类整确,但在unlabel data上的entropy越小越好。所以根据这个假设,你就可以去重新设计你的loss function。我们原来的loss function是说:我希望找一个参数,让我现在在label data上model的output跟正确的model output越小越好,你可以cross entropy evaluate它们之间的距离,这个是label data的部分。在unlabel data的部分,你会加上每一笔unlabel data的output distribution的entropy,那你会希望这些unlabel data的entropy 越小越好。那么在这两个中间,你可以乘以一个weight(ln5ln5)来考虑说:你要偏向unlabel data多一点还是少一点

在train的时候,用GD来一直minimize这件事情,没有什么问题的。unlabel data的角色就很像regularization,所以它被称之为 entropy-based regulariztion。之前我们说regularization是在原来的loss function后面加一个惩罚项(L2,L1),让它不要overfitting;现在加上根据unlabel data得到的entropy 来让它不要overfitting。

半监督SVM

在这里插入图片描述
那还有其他semi-supervised的方式,叫做semi-supervised SVM。SVM精神是这样的:SVM做的事情就是:给你两个class的data,找一个boundary,这个boundary一方面要做有最大的margin(最大margin就是让这两个class分的越开越好)同时也要有最小的分类的错误。现在假设有一些unlabel data,semi-supervised SVM会咋样处理这个问题呢?它会穷举所有可能的label,就是这边有4笔unlabel data,每一笔它都可以是属于class1,也可以是属于class2,穷举它所有可能的label(如右图所示)。对每一个可能的结果都去做一个SVM,然后再去说哪一个unlabel data的可能性能够让你的margin最大同时又minimize error。

问题:穷举所有的unlabel data label,这是非常多的事情。这篇paper提出了一个approximate的方法,基本精神是:一开始得到一些label,然后你每次该一笔unlabel data看可不可以让margin变大,变大了就改一下。

假设二:Smoothness Assumption

在这里插入图片描述
接下来,我们要讲的方法是Smoothness Assumption。近朱者赤,近墨者黑

在这里插入图片描述
它的假设是这样子的,如果x是相似的,那label y就要相似。光讲这个假设是不精确的,因为正常的model,你给它一个input,如果不是很deep的话,output就很像,这样讲是不够精确的。

真正假设是下面所要说的,x的分布是不平均的,它在某些地方是很集中,某些地方又很分散。如果今天x1,x2x_1,x_2它们在high density region很close的话,y1,y2y^1,y^2才会是是很像的。
high density region这句话就是说:可以用high density path做connection,可以还不知道在说什么。举个例子,假设图中是data的分布,分布就像是写轮眼一样,那现在假设我们有三笔data(x1,x2,x3x_1,x_2,x_3)。如果我们今天考虑的是比较粗略的假设(相似的x,那么output就很像,那感觉x2,x3x_2,x_3的label比较像,但x1,x2x_1,x_2的label是比较不像),其实Smoothness Assumption更精确的假设是这样的,你的相似是要透过一个high density region。比如说,x1,x2x_1,x_2它们中间有一个high density region(x1,x2x_1,x_2中间有很多很多的data,他们两个相连的地方是通过high density path相连的)。根据真正Smoothness Assumption的假设,它要告诉我们的意思就是说:x1,x2x_1,x_2是可能会有一样的label,x2,x3x_2,x_3可能会有比较不一样的label(他们中间没有high density path)。

那为什么会有Smoothness Assumption这样的假设呢?因为在真实的情况下是很多可能成立的

在这里插入图片描述
比如说,我们考虑这个例子(手写数字辨识的例子)。看到这变有两个2有一个3,单纯算它们peixel相似度的话,搞不好,两个2是比较不像的,右边两个是比较像的(右边的2和3)。如果你把你的data都通通倒出来的话,你会发现这个2(最左边)跟这个2(右边)中间有很多连续的形态(中间有很多不直接相连的相似,但是有很多stepping stones可以直接跳过去)。所以根据smoothness Assumption的话,左边的2跟右边的2是比较像的,右边的2跟3中间没有过渡的形态,它们两个之间是不像的。如果看人脸辨识的是,也是一样的。如果从一个人的左脸照一张相跟右脸照一张相,这是差很多的。如果你拿另外一个人眼睛朝左的相片来比较的话,会比较像这个跟眼睛朝右相比的话。如果你收集更多unlabel data的话,在这一张脸之间有很多过渡的形态,眼睛朝左的脸跟眼睛朝向右的脸是同一个脸。

[外链图片转存失败(img-n5zvx47s-1569328440254)(res/chapter23-17.png)]
这一招在文件分类上也是非常有用的,这是为什么呢?假设你现在要分天文学跟旅游类的文章,那天文学有一个固定的word distribution,比如会出现“asteroid,bright”.那旅游的文章会出现“yellowstone,zion等等”。那如果今天你的unlabel data跟你的label data是有overlap的话,你就很轻易处理这个问题。但是在真是的情况下,你的unlabel data跟label data中间没有overlap word。为什么呢?一篇文章可能词汇不是很多,但是word多,所以你拿到两篇,有重复的word比例其实是没有那么多的。所以很有可能你的unlabel data跟label data之间是没有任何关系的。

在这里插入图片描述
但是如果能收集到够多的unlabeled data的话,就能得到d1和d5比较像,d5和d6比较像,这个像就可以一直传播过去,得到d1和d3像,同样的d4可以和d2一类。

聚类和标记

在这里插入图片描述
如何实践这个smoothness assumption,最简单的方法是cluster and then label。现在distribution长这么样子,橙色是class1,绿色是class2,蓝色是unlabel data。接下来你就做一下cluster,你可能分成三个cluster,然后你看cluster1里面class1的label data最多,所以cluster1里面所有的data都算是class1,cluster2,cluster3都算是class2、class3,然后把这些data拿去learn就结束了,但是这个方法不一定有用。如果你今天要做cluster label,cluster要很强,因为这一招work的假设就是不同class cluster在一起。可是在image里面,把不同class cluster在一起是没有那么容易的。我们之前讲过说,为什么要用deep learning,不同class可能会长的很像,也有可能长的不像,你单纯只有pixel来做class,你结果是会坏掉的。如果你要让class and then label这个方法有用,你的class要很强。你要用很好的方法来描述image,我们自己试的时候我们会用deep autoendcoder,用这个来提取特征,然后再进行聚类。

基于图的方法

刚才讲的是很直觉的方法,另外一个方法是Graph-based Approach,我们用Graph-based approach来表达这个通过高密度路径连接这件事情。就说我们现在把所有的data points都建成一个graph,每一笔data points都是这个graph上一个点,要想把他们之间的range建出来。有了这个graph以后,你就可以说:high density path的意思就是说,如果今天有两个点,他们在这个graph上面是相的(走的到),那么他们这就是同一个class,如果没有相连,就算实际的距离也不是很远,那也不是同一个class。

在这里插入图片描述
建一个graph:有些时候这个graph representation是很自然就得到了。举例来说:假设你现在要做的是网页的分类,而你有记录网页之间的Hyperlink,那Hyperlink就很自然的告诉你网页之间是如何连接的。假设现在做的是论文的分类,论文和论文之间有引用之间的关系,这个引用也是graph,可以很自然地把图画出来给你。

在这里插入图片描述
但有时候你要想办法来建这个graph。通常是这样做的:你要定义xi,xjx^i,x^j咋样来算它们的相似度。影像的话可以用pixel来算相似度,但是performance不太好。用auto-encoder算相似度可能表现就会比较好。算完相似度你就可以建graph,graph有很多种:比如说可以建K Nearest Neighbor,K Nearest Neighbor意思就是说,我现在有一大堆的data,data和data之间,我都可以算出它们的相似度,那我K=3(K Nearest Neighbor),每一个point跟他最近的三个point做标记。或者也可以做e-Neighborhood:意思就是说,每个点只有跟它相似度超过某一个threshold,跟它相似度大于的1点才会连起来。所谓的edge也不是只有相连不相连这样boundary的选择而已,你可以给edge一些weight,你可以让你的edge跟你的要被连接起来的两个data points的相似度是成正比的。怎么定义这个相似度呢?我会建议比较好的选择就是Gaussian Radial Basis function来定义这个相似度。

怎么算这个function呢?你可以先算说:xi,xjx^i,x^j你都把它们用vector来描述的话,算他们的distance乘以一个参数,再取负号,然后再算exponentiation。其实exponential这件事在经验上还是会给你比较好的performance。为什么用这样的方式会给你比较好的performance呢?如果你现在看这个function(Gaussian Radial Basis function)它的下降速度是非常快的。你用这个Gaussian Radial Basis function的话,你能制造出像这个图(有两个橙色距离很近,绿色这个点离橙色也蛮近,如果你用exponential的话,每一个点只能与非常近的点离,它跟稍微远一点就不连了。你要有这样的机制,你才能避免跨海沟的link,所以你用exponential通常效果比较好。

在这里插入图片描述
如果我们现在在graph上有一些label data,在这个graph上我们说这笔data1是属于class1,那跟它有相连的data points属于class1的几率也会上升,所以每笔data会影响它的邻居。光是会影响它的邻居是不够的,如果你只考虑光是影响它的邻居的话可能帮助是不会太大。为什么呢?如果说相连的本来就很像,你train一个model,input很像output马上就很像的话,帮助不会太大。那graph-based approach真正帮助的是:它的class是会传递的,本来这个点有跟class1相连所以它会变得比较像class1。但是这件事会像传染病一样传递过去,虽然这个点真正没有跟class1相连,因为像class1这件事情是会感染,所以这件事情会通过graph link传递过来。

举例来说看这个例子,你把你的data points建成graph,这个如果是理想的例子的话,一笔label是属于class1(蓝色),一笔label是属于class2(红色)。经过garph-based approach,你的graph建的这么漂亮的话(上面都是蓝色的,下面都是红色的)

在这里插入图片描述
这样的semi-supervised有用,你的data要足够多,如果data不够多的话,这个地方没收集到data,那这个点就断掉了,那这个information就传不过去了,比如右上图就出现四个小的cluster。

在这里插入图片描述刚才是定性的说使用这个graph,接下来说怎么定量使用这个graph。那这个定量的使用是在这个graph structure上面定义一个东西叫做:label的 smoothness,我们会定义说label有多符合我们刚才说的smoothness assumption 的假设。

现在看这两个例子,在这两个例子都有四个data points,data point跟data point连接的数字代表了weight。在左边这个例子中,你给它的label是(1,1,1,0),在右边的例子中,给的label是(0,1,1,0)。左边的这个例子是比较smothness的,但是我们需要一个数字定量的描述它说:它有多smothness。常见的做法是这样子的:这个式子是我们考虑两两有相连的point,两两拿出来(summation over所有data i,j),然后计算i,j之间的weight跟y的label减去j的label的平方(这个是summation 所有data,不管他现在是有label还是没有label)。所以你看左边这个case,在summation over所有的data的时候,你只需要考虑,s=0.5(只是在计算时比较方便而已,没有真正的效用),右边的class s=3,这个值(s)越小越smothness,你会希望你得出的labelsmothness的定义算出来越小越好。

现在看这两个例子,在这两个例子都有四个data points,data point跟data point连接的数字代表了weight。在左边这个例子中,你给它的label是(1,1,1,0),在右边的例子中,给的label是(0,1,1,0)。左边的这个例子是比较smothness的,但是我们需要一个数字定量的描述它说:它有多smothness。常见的做法是这样子的:S=12ijwi,j(yiyj)2S=\frac{1}{2}\sum_{ij}w_{i,j}(y^i-y^j)^2。这个式子是我们考虑两两有相连的point,两两拿出来(summation over所有data i,j),然后计算i,j之间的weight跟y的label减去j的label的平方(这个是summation 所有data,不管他现在是有label还是没有label)。所以你看左边这个case,在summation over所有的data的时候,你只需要考虑x3,x4x_3,x_4,s=0.5(只是在计算时比较方便而已,没有真正的效用),右边的class s=3,这个值(s)越小越smothness,你会希望你得出的labelsmothness的定义算出来越小越好。

在这里插入图片描述这个算式可以稍微整理整理一下,可以写成一个简洁的式子。我们把y串成一个vector(现在y包括label data,也包括unlabel data),每一个笔label data和label data都赋一个值给你,现在你有R+U个dimension vector,可以写成y。如果你这样写的话,s这个式子可以写成y(vector)的transform乘以L(matrix)再乘以y,L是属于(R+U)*(R+U)matrix,这个L被叫做“Graph Laplacian”。

这个L的定义是:两个matrix相减(L=D-W)。W就是你把这些data point两两之间weight connection建成一个matrix,这个matrix的四个row个四个columns分别代表datax1x^1x4x^4,D是你把w的每组row合起来。

现在我们可以用yTLyy^TLy去评估我们现在得到的label有多smothness。在这个式子里面我们会看到有y,这个y是label,这个label的值也就是neural network output的值是取决于neural parameters。这一项其实是neural 的depending,所以你要把graph的information考虑到neural network的train的时候,你要做的事情其实就是在原来的loss function里面加一项。假设你原来的loss function是cross entropy,你就加另外一项,你加的这一项是smoothness的值乘以某一个你想要调的参数,后面这一项λ\lambdaS其实就是象征了 regulization term。你不只要调整参数让你那些label data的output跟真正的label越接近越好,你同时还要做到说:output这些label,不管是在label data还是在unlabel data上面,它都符合smothness assuption的假设是由这个s所衡量出来的。所以你要minimize前一项还要minimize后一项(用梯度下降)

其实你要算smothness时不一定要放在output的地方,如果你今天是deep neural network的话,你可以把你的smothness放在network任何地方。你可以假设你的output是smooth,你也可以同时说:我把某一个hidden layer接出来再乘上别的一些transform,它也要是smooth,也可以说每一个hidden layer的output都是smooth

Better Representation

最后一个方法是:Better Representation,这个方法的精神是:“去无存青,化繁为简”,等到unsupervised的时候再讲。
它的精神是这样子的:我们观察到的世界其实是很复杂的,我们在我们观察到的世界背后其实是有一些比较简单的东西在操控着我们这个复杂的世界,所以你只要能看透这个世界的假象,直指它的核心的话就可以让训练变得容易。

2019-09-19 09:15:02 fly975247003 阅读数 31

背景

梯度下降

在这里插入图片描述

  • 给到 θ\theta (weight and bias)
  • 先选择一个初始的 θ0\theta^0,计算 θ0\theta^0 的损失函数(Loss Function)设一个参数的偏微分
  • 计算完这个向量(vector)偏微分,然后就可以去更新 θ\theta
  • 百万级别的参数(millions of parameters)
  • 反向传播(Backpropagation)是一个比较有效率的算法,让你计算梯度(Gradient) 的向量(Vector)时,可以有效率的计算出来

链式法则

在这里插入图片描述

  • 连锁影响(可以看出x会影响y,y会影响z)
  • BP主要用到了chain rule

反向传播

  1. 损失函数(Loss function)是定义在单个训练样本上的,也就是就算一个样本的误差,比如我们想要分类,就是预测的类别和实际类别的区别,是一个样本的,用L表示。
  2. 代价函数(Cost function)是定义在整个训练集上面的,也就是所有样本的误差的总和的平均,也就是损失函数的总和的平均,有没有这个平均其实不会影响最后的参数的求解结果。
  3. 总体损失函数(Total loss function)是定义在整个训练集上面的,也就是所有样本的误差的总和。也就是平时我们反向传播需要最小化的值。
    在这里插入图片描述
    对于L(θ)L(\theta)就是所有lnl^n的损失之和,所以如果要算每个L(θ)L(\theta)的偏微分,我们只要算每个lnl^n的偏微分,再把所有lnl^n偏微分的结果加起来就是L(θ)L(\theta)的偏微分,所以等下我们只计算每个lnl^n​的偏微分。
    我们先在整个神经网络(Neural network)中抽取出一小部分的神经(Neuron)去看(也就是红色标注的地方):
    在这里插入图片描述

取出一个Neuron进行分析

在这里插入图片描述
从这一小部分中去看,把计算梯度分成两个部分

  • 计算zw\frac{\partial z}{\partial w}(Forward pass的部分)
  • 计算lz\frac{\partial l}{\partial z}​ ( Backward pass的部分 )

Forward Pass

那么,首先计算zw\frac{\partial z}{\partial w}​(Forward pass的部分):
在这里插入图片描述
根据求微分原理,forward pass的运算规律就是:

zw1=x1zw2=x2\frac{\partial z}{\partial w_1} = x_1 \\ \frac{\partial z}{\partial w_2} = x_2
这里计算得到的x1x_1x2x_2恰好就是输入的x1x_1x2x_2
直接使用数字,更直观地看到运算规律:

在这里插入图片描述

Backward Pass

(Backward pass的部分)这就很困难复杂因为我们的l是最后一层:
那怎么计算 lz\frac{\partial l}{\partial z} (Backward pass的部分)这就很困难复杂因为我们的ll是最后一层:

在这里插入图片描述
计算所有激活函数的偏微分,激活函数有很多,这里使用Sigmoid函数为例

这里使用链式法则(Chain Rule)的case1,计算过程如下:

lz=azlaσ(z)\frac{\partial l}{\partial z} = \frac{\partial a}{\partial z}\frac{\partial l}{\partial a} \Rightarrow {\sigma}'(z)​
la=zalz+zalz\frac{\partial l}{\partial a} = \frac{\partial z'}{\partial a}\frac{\partial l}{\partial z'} +\frac{\partial z''}{\partial a}\frac{\partial l}{\partial z''}​
在这里插入图片描述
最终的式子结果:

在这里插入图片描述
但是你可以想象从另外一个角度看这个事情,现在有另外一个神经元,把forward的过程逆向过来,其中σ(z){\sigma}'(z)是常数,因为它在向前传播的时候就已经确定了

在这里插入图片描述

case 1 : Output layer

假设lz\frac{\partial l}{\partial z'}lz\frac{\partial l}{\partial z''}​是最后一层的隐藏层
也就是就是y1与y2是输出值,那么直接计算就能得出结果
在这里插入图片描述

但是如果不是最后一层,计算lz\frac{\partial l}{\partial z'}lz\frac{\partial l}{\partial z''}​的话就需要继续往后一直通过链式法则算下去

case 2 : Not Output Layer

在这里插入图片描述
对于这个问题,我们要继续计算后面绿色的lza\frac{\partial l}{\partial z_a}lzb\frac{\partial l}{\partial z_b},然后通过继续乘w5w_5w6w_6得到lz\frac{\partial l}{\partial z'},但是要是lza\frac{\partial l}{\partial z_a}lzb\frac{\partial l}{\partial z_b}都不知道,那么我们就继续往后面层计算,一直到碰到输出值,得到输出值之后再反向往输入那个方向走。

在这里插入图片描述
对上图,我们可以从最后一个lz5\frac{\partial l}{\partial z_5}lz6\frac{\partial l}{\partial z_6}看,因为lza\frac{\partial l}{\partial z_a}lzb\frac{\partial l}{\partial z_b}比较容易通过output求出来,然后继续往前求lz3\frac{\partial l}{\partial z_3}lz4\frac{\partial l}{\partial z_4},再继续求lz1\frac{\partial l}{\partial z_1}lz2\frac{\partial l}{\partial z_2}
最后我们就得到下图的结果
在这里插入图片描述

实际上进行backward pass时候和向前传播的计算量差不多。

总结

我们的目标是要求计算zw\frac{\partial z}{\partial w}(Forward pass的部分)和计算lz\frac{\partial l}{\partial z} ( Backward pass的部分 ),然后把zw\frac{\partial z}{\partial w}lz\frac{\partial l}{\partial z}相乘,我们就可以得到lw\frac{\partial l}{\partial w},所有我们就可以得到神经网络中所有的参数,然后用梯度下降就可以不断更新,得到损失最小的函数
在这里插入图片描述

没有更多推荐了,返回首页