zoukankan      html  css  js  c++  java
  • AndrewNG Deep learning课程笔记

    参考,

    An Intuitive Explanation of Convolutional Neural Networks

    http://www.hackcv.com/index.php/archives/104/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

    CNN基础

    CNN网络主要用于compute vision

    对于图片输入而言,是一种极高维度的数据,比如分辨率1000*1000*3的图,可能会产生3 billion的参数,这不太可行

    所以我要使用convolutional NN来解决这种问题,

    首先看看什么是卷积操作,

    如下图,

    原图片6*6

    中间3*3的矩阵,称为filter或卷积核kernel,它表示你需要匹配的模式,这里detect edge,竖线

    最右边4*4的矩阵,就是进行卷积操作后的结果

    为何这个filter可以找出竖线,直观理解,filter找出左右存在色彩反差的区域或者找出由明转向暗的区域,如下图

    实际中还有很多其他的filter,

    但是其实在deep learning中,你不需要去手工设计或者选择filter,因为他们是学习的参数,可以通过模型学习到

    可以看出用卷积可以大大减少需要学习的参数,

     

    为什么卷积网络,可以用这么少的参数?

    首先是参数共享

    通过一个filter可以找出图片上任何位置的特征,如竖线

    这样的好处是无论输入图片多大,参数size都是固定的,由filter本身决定

    第二,稀疏链接

    如果是全连接层,每个输出的每个维度都和输入的每个维度相关,所以需要很多的参数
    而在卷积层,一个输出的某个维度如下图,是由输入中的9个feature算出的,而其他特征无关

    这样需要的参数大大减少,同时也降低了过拟合

    Padding

    上面的卷积操作有两个问题,

    每次卷积操作都会缩小图片的尺寸

    会丢失边缘区域的特征

    所以为了解决这些问题,padding就是把图片扩大一圈,用0填充

    这样就有两种convolution操作,

    valid就是no padding,结果大小的公式,n-f+1

    same就是padding让输出结果大小不变,根据公式算,p=2的时候,就可以保证不变

    这里描述filter一般都是odd,而不会是偶数,直观上讲,如果f是偶数,那么没法对称的padding,而且f是奇数是filter是有中心点的,这个很方便
    所以filter一般都是3*3,5*5,7*7

    strided convolution

    对于convolution,除了调整filter size,padding,还可以调整stride的大小

    可以每次滑动超过1步,那公式会变成如下,

    cross-correlation VS convolution

    在通信或数据中,convolution操作要先把filter,同时在横轴和竖轴上进行翻转,如图,

    这样做的好处,是可以让convolution操作满足结合律 

    但是在DL中,我们其实没有做这种翻转,这种操作其实应该叫做cross-correlation

    但是大家都习惯和默认称为convolution

    convolutions on volumes

    真实的图片有RBG三层,所以是立体的,这样如果进行convolution

    输入数据的层数,称为depth或channel

    当输入数据有3个channel,那么filter对应也需要有3个channel

    如图,上面这个3*3*3的filter可以detect 红色的竖线

    下面这个,可以detect 任意颜色的竖线

    在实际使用中,需要同时detect多个feature,所以有多个filter,如下图

    输出数据的channel数,取决于filter的数目

    one layer of a convolutional network

    那把卷积操作放到网络中的一层结构如下,

    卷积再加上b,就完成了线性变换的部分,后面跟上非线性变换,就完成了一个神经单元

    上图中的各个参数的表示如下,

     

     给出一个完整的CNN的例子,

    每层的结构,根据上面的公式很容易算出,卷积层只是做特征的提取和变换,最终输出前,还是需要fully connected,然后用logistics或softmax输出结果

    CNN网络一般有三种layer组成,convolution层,pooling层,fully connected层

    pooling layers

    池化层,利用采样高效的降低维度和减少特征值

    一般有最大和平均池化,这层是没有参数的

    neural network example

    卷积神经网络的结构比较复杂,而且超参数非常多,所以常用的方法是参考经典的网络结构

    先看个例子,用于手写体数字识别,

    如下图,总结下这个网络的结构,

    能学到的规律,

    首先,池化层没有参数,而卷积层的参数并不多,参数主要集中在全连接层

    然后,CNN的经典结构就是,cov-pool-cov-pool-fc-fc-fc-softmax,几层cov和pool组合,加上几组fc层

    再者,activation size是慢慢减少的,如果降低的太快会影响模型的性能

    Case Studies

    参考,https://zhuanlan.zhihu.com/p/22094600 

    比较直观看出各个网络的年代和性能差距

     

    LeNet-5

    该网络由作者名字LeCun命名,5代表五层模型

    该网络,用于手写数字识别,用于灰度图片,所以图片channel为1

    网络整体有60k的参数,比较小

    用于当时没有padding技术,所以随着网络depth增加,size是不断变小,但是channel是不断变大的

    网络结构被后续沿用,若干cov+pool + 若干fc + output 

    从原始图片1024个像素到最后一层FC的维度84,所以cnn关键就是抽象和提取特征

    AlexNet

    这个网络也是用作者名字命名的

    AlexNet和LeNet其实比较像,就是规模大了许多,参数从60k到60m

    只所以可以训练这么大的网络,是因为AlexNet在工程实践上利用的GPU

    然后AlexNet,采用了Relu和dropout,最终把compute vision带到一个新世界

    VGG

    VGG网络是比AlexNet规模更大,更深的网络模型,参数达到138M之多 

    16表示有参数的layer有16层

    VGG的特点是结构规整,工业化的思路,我们不去精巧的设计,依赖网络的规模和数据规模来解决问题

    首先他用的Conv和Pool模块是固定的,

    Conv是3*3,s=1,same

    Pool是2*2,s=1

    然后为了便于表示,在图中省略了Conv的参数,Conv 64 *2,表示2层卷积层,每层有64个filter

    再者,

    由于这里用same conv,所以conv是不会改变图片size的

    全靠pooling层改变图片size,并且也很有规律

    多个Same Conv后,会接一个Pool,这样picture的size减半,并且每个Pool后,加上的Conv层的channel都会double

    所以还是符合size变小,channel变大的规律,只是更规整

    Residual Networks(ResNets) 

    残差网络的本质是要解决网络太深后难以训练的问题,由于梯度消失或梯度爆炸

    可以看到之前的网络也就十几层,而残差网络都是上百层,甚至上千层

    所以残差网络效果好,不是有什么秘诀,因为更深的网络,更好的性能,这是理所当然的

    只是之前的网络模型,在实践中无法训练到那么深

    残差网络,是由residual block组成的,

    residual block至少两层layer组成,

    除了普通的main path,不同就是多了shotcut或skip connection

    即,会把第一层的输入a1,叠加到第二层的激活函数前

    所以第二层的输出,就从a2 = g(z2),变成a2 = g(z2 + a1)

    我们把很多的residual block 堆叠(stack)在一起,就形成residual network,如下图,

    如图,把plain network变成ResNet,只需要给每两层加上shortcut,这样就可以解决plain network当layer数过大性能明显下降的问题

    为什么残差网络可以帮助网络增加深度?

    NG的观点是,因为residual block对网络是无副作用的

    如下图,由于residual block的输出是a2 = g(z2 + a1)

    那么只要让z2 = w2a1 + b2的参数,w2,b2趋于0(类似正则化),那么a2=g(a1),如果g是relu,那么g(a1)=a1,所以得到a2 = a1

    而让参数为0这是很容易学习的

    所以说residual block最差的情况就是,原封不动的传递输入,这样当然无论迭代多深都没有关系

    但是,如果不是最差情况,能学到些东西,对网络就可以产生正向的帮助 

    这里residual block有个假设,就是z2 + a2,那么两者的size需要一样

    如果不一样了?那这里需要增加一个参数,Ws用于把a2的size转成和z2一样

    下图是个实际的例子,如何将一个plain的cnn,转化为一个ResNet网络

    注意虚线的链接,表示经过pool,size变化后,需要进行size转换

    Inception网络

    inception各个版本对比

    https://blog.csdn.net/xbinworld/article/details/61674836

    inception的命名,是因为在盗梦空间,inception,中有一句台词,“we need to go to deeper”

    所以可以看出,inception network或GoogleNet的主要目的,也是让网络更深

    首先看下1*1 convolution

    1*1 convolution,其实就是单像素点,在各个channels上的线性组合

    它的作用,

    主要就是低成本的调节channel数,或depth;在不需要调整长宽的情况下,用3*3,5*5,比较耗费性能

    再者,因为有relu输出,附带一层非线性效果

    下面就看看啥是inception网络,

    普通的convolution网络,你要选择用什么样的filter或是用pool层,选择困难怎么办?

    Inception的思路就是,都用上,然后把结果stack在一起,让模型去决定

    注意这里要保证输出的size一致,所以这里的pool是same pool,不会压缩尺寸,这是很特殊的pool用法

    这个思路最大的问题就是计算量太大,那么这时我们的1*1 convolution就用上了

    比如上面的例子,直接对输入做5*5 convolution,那么计算量120 million

    用上1*1 convolution,先把depth降下来,再算5*5 convolution,这样计算量只有12 million左右,小十倍

    可以看到,两个方法,输入和输出都是一样的,但用上1*1 convolution降低channel后,计算量大大降低

    中间这层称为,bottleneck layer,使用恰当的情况下,降维优化并不会损失算法的performance

    我个人的理解,由于1*1 convolution是各个channel的线性组合,加上适当数量的filter,并不会丢失太多的信息

    Inception module

    现在来看inception module就比较清楚了,

    如图就是一个inception module,其中1*1 convolution都是用来调节depth的

    比如MaxPool后面的,就把depth调节到32,避免pool的结果在最终stack中占太大的空间 

    而inception网络,就是inception module的堆叠,中间还会加上些红色的pool层来调节size

    Object Detection

    classification with localization

    这个和普通图片分类的区别,就是除了给出类别,还要给出在图中的位置信息

    看这个例子,除了要给出图片是哪一类,1,2,3,4,car是2

    还要给出car的位置,bx,by,bh,bw

    这里假设图片的坐标是,从(0,0)到(1,1)

    这样就有5个输出,其他的和原来一样,还是交给模型去训练

     具体实现如下,

    这里的输出增加一个Pc,表示是否有object,0或1

    bx到bw是代表object的位置

    c1,c2,c3表示具体的类别

    这里给出两个例子,一个是车的,一个是单纯背景无object的

    注意,

    loss function中,如果Pc=0,表示没有object,那么后面的值就没有意义,所以在算loss function的时候就不需要考虑,只需要算第一项的平方误差

    上面是比较简单的位置的例子,还可以检测面部特征或体态特征这样的case,思路都是一样的,关键是定义清楚位置特征作为输出

    当然关键是,你需要有相当的训练集

    sliding windows object detection

    如果一个图里面有多个对象怎么办,这个就是object detection

    传统的方法就是,sliding windows object detection,很naive的方法

    拿一个框去遍历裁剪图片,对每个裁剪下来的小图,做分类,是否有object,是什么object

    这个方法的问题很明显,你如何定义裁剪尺寸,太大就没有意义,太小计算量就会非常大

    传统的方法是用线性回归来做分类,性能还能接受,但是用cnn性能就不行了

    上面的图,显示如何通过cnn进行分类,14*14*3是裁剪的小图片,通过conv层,pool层,然后FC层,最后softmax

    为了优化,我们可以把整个分类的过程,都转化成conv层

    比如,第一层FC,5*5*16,全连接到400的节点

    我们也可以用400个5*5*16的filter,进行卷积,最终得到1*1*400,同样的效果

    这样第二层FC,我们用400个1*1*16的filter来代替

    最后softmax,用4个1*1*16的filter来代替

    这称为,convolutional implementation

    这样的好处,我们可以把遍历裁剪图片分类这个过程,通过一遍cnn计算搞定

    比如,输入图片16*16*3,裁剪大小是14*14*3,如果遍历输入图片会产生4个小图片

    这里我们不用对每个小图片分别采用conv计算,如果这样做会产生大量的重复计算

    而只要整体的做一遍conv计算,如下图,最终得到2*2*4的输出,即一下输出4个裁剪小图片的结果,效率大大提高

    但这个方法,我们仍然需要指定裁剪size,

    但这样只能判断object是否在小图片中,无法给出更精确的位置信息;并且很有可能object无法完整的被任何裁剪小图包含

    Yolo(you only look once)

    Yolo的思路,既然上面单纯的分类无法找到精确边界,那我们加上classification and localization的部分

    对每个图片同时给出分类和边界数据,

    既然我们可以得到精确的边界,所以就没有必要用sliding window,直接用grid把图片切分就可以

    对于下面的例子,我们把图片用3*3的grid划分,最终就得到3*3*8的结果

    训练这个模型,我们也要按照这个格式给出训练集,比如上图中,给出绿色框和黄色框的数据作为实例

    由于这里也用convolutional implementation的方式,使得计算非常高效,

    所以训练集中,x表示输入图片,100*100*3,输出就是3*3*8

    ok,这里明显的问题是

    如果一个grid里面两个objects,怎么办?这个通过用小grid来降低概率,比如用19*19

    反之,如果一个object比较大,占好几个grid怎么办?

    我们只看,object的中心点,bx,by落在哪个grid,那么就认为object属于这个grid,即Pc为1,其他的grid仍然认为没有object 

    所以bx,by一定落在grid内,所以bx,by都是小于1的(grid的边界从0,0到1,1)

    但是由于object是可能占多个格子的,所以bh,bw可能是大于1的

    Intersection over union (IOU)

    如何判断算出的bounding是否精确?

    很简单,交并比

    下图,红框是精确的bounding box,而紫色的算出的bounding box,想判断紫色的bounding box是否足够精确

    Non-max suppression

    用yolo算法的时候,

    在准备训练集的时候,我们可以把一个车根据中心点放到一个grid中

    但是在predict的时候,会有不止一个grid认为车在自己的grid中如图,并用Pc来表示概率

    那么直接的想法,既然Pc表示概率,我们就选概率最大的,其他的都discard掉,就好了

    如果图片中只有一个object,这个方法是可以的

    但是如果有多辆车,我怎么知道哪些grid的bounding box是描述的同一辆车?

    这里就要用到交并比,如果两个bounding box的IOU大于0.5,我们就认为是同一辆车

    所以得到下面的方法,

    首先discard掉所以Pc较小的grid

    然后找到最大的Pc,然后删掉所有和它的IOU大于0.5的grid,这样一个object就保留了一个Pc最大的grid

    如果还有grid剩下,说明有其他的object,再重复上面的过程一一找出

    Anchor boxes

    前面说了当用很小grid的时候,一个grid中有多个object的概率是很小的

    但如果要在一个grid中detect两个object应该怎么做?

    直接的想法是,我用8位的输出来detect一个object

    那如果要detect两个,就用16位输出,分别表示两个object

    比如下图,图片中人和车都在一个grid中,所以我们就用前8位表示人,后8位表示车

    这样讲人可以理解,机器不行

    所以我们要用机器可以理解的概念来定义人和车,

    这里就是用anchor box,anchor box可以人手工设计,也可以用k-means去统计,比如人的平均边界,车的的平均边界

    如下图,我们就用anchor box1代表人,anchor box2代表车

    那么一个object到底是算哪个box?还是用交并比,和谁的交并比大就算谁

     

    这个方法用起来比较麻烦,detect两个object就用16位输出,如果要detect多个object就要更多位的输出

    而且还要指定和设计anchor box

    然后如果grid中出现多于假设个数的object,就没办法处理

    或者两个object的anchor box类似,也很难处理

    Region proposals

    除了,Yolo,还有另外一个思路来加速sliding windows object detection

    region-cnn,思路就是对于sliding windows object detection,我们要遍历所有的裁剪图片去做分类,但是某些裁剪图片明显是没有任何东西的

    所以,region-cnn会对图片做分块,segmentation,如最右图,这样只需要对不同的色块做分类即可

    那么执行分类的candidate变少,性能就提高了

    Face Recognition

    Recognition可以分解成verification的问题,如果解决了verification的问题,那么Recognition只是遍历的问题

    这里要注意的是,如果要在Recognition达到一定精度,verification的精度要提高几个量级

    因为如果verification的精度99%,但库里面有100张图片,所以每次误差的叠加就会很高 

    One-shot training

    在很多场景下,你不会有很多关于某个人的图片,可能只有一张图片作为训练集,当这个人再次出现时,你要能够认出他

    这个用传统的cnn就无法解决,首先训练集太少,无法得到有效的网络

    再者如果要识别的对象增加,比如新员工入职,你需要从新训练网络

    所以采用的方法是,

    Siamese network

    具体的做法,就是通过cnn对图片进行encoding,比如下图,一张图片会编码成128位的向量(往往成为embedding)

    那么训练目标,就是相同人的图片得到的embedding间的距离比较小,反之

    Triplet loss

    Triplet,顾名思义,一个训练集中有3个图片,anchor作为baseline,一个positive,和一个negative

    很明显,

    我们的目的就是,让d(A,P)小于d(A,N),d是距离

    光小于不够,要远小于,所以加上margin超参数alpha

    形式化,

    A和P的选择很简单,

    对于N的选择,我们应该尽量选择和A相近的N,这样算法效率会更高,如果我们随机选择N,会让上面的约束很容易达到,会大大降低训练效率

    除了triplet loss,也有其他的方法训练,siamese network ,比如下面的方法,把两个图片的embedding,作为logistics回归的输入,变成一个分类问题去训练

    Neural sytle transfer

    sytle transfer要做的如下图,

    给出一张content图片C,一张style图片S,要的效果就是生成G

    所以优化目标,J(G),由两部分组成,

    J(C,G),表示G和C在content上的相似度

    J(S,G),表示G和S在style上的相似度

    下面就分别来定义这两个目标函数,

    content cost function

    判断内容是否相似比较直观,和前面脸部识别一样,我们只要把图片encoding成embedding,然后比较相似度就好

    实际做,

    找一个pre-trained的ConNet,选一层l的输出作为embedding,通常l不会太浅也不会太深,这样可以比较好的代表图片的内容

    剩下的就是计算两个embedding的相似度 

     

    style cost function

    关键是要找出,style是什么?

    这里给出的定义是,对于某个layer,style是各个channel的相关系数

    cnn中,某一层的各个channel是由不同的filter生成,filter可以理解代表某一种特征

    直观理解,如果两个channel相关性高,说明其filters所代表的特征常常会同时出现,比如下图,中竖线和橘色两种特征

    形式化定义,我们用style matrix,G[l],来表示图片在第l层的风格,

    G用来表示每个channel之间的关系,所以nc*nc大小的

    k层channel和k‘层channel的相关系数,就是两层对应的每个位置数据的乘积和,也称为gram矩阵

    直观上简化一下,如果数据只有0,1,如果两层不相干,乘积和会为0,只有相关才会同时出现1,这样相关系数才会大

    那么上面就给出在l层上,S和G的style的cost function,其实就是计算S和G的style matrix的差异

    最终J(S,G)会考虑所有layer上的风格矩阵的差异

  • 相关阅读:
    $().each() 与 $.each()区别,以及 jquery ajax 应用
    sql 随机获取数据
    Content type 'text/plain;charset=UTF-8' not supported
    mvn 安装jar到本地仓库
    idea 插件(字母顺序)
    adb连接逍遥模拟器,并自动设置和清除代理
    git仓库重新创建master分支
    js 日期格式化
    java 去除url中指定参数
    okhttp使用post出现:RFC 7230 and RFC 3986错误
  • 原文地址:https://www.cnblogs.com/fxjwind/p/8732844.html
Copyright © 2011-2022 走看看