zoukankan      html  css  js  c++  java
  • 【DeepLearning】基本概念:卷积、池化、Backpropagation

      终于有了2个月的空闲时间,给自己消化沉淀,希望别有太多的杂事打扰。在很多课程中,我都学过卷积、池化、dropout等基本内容,但目前在脑海中还都是零散的概念,缺乏整体性框架,本系列博客就希望进行一定的归纳和梳理,谋求一个更清晰的思路。

    ## Outline

    ## Notes

    【卷积(Convolution)】

       卷积的目的就是从原始数据中提取出特征,过程是利用卷积核(kernel)按照下面动图的规则进行计算(做点乘),得到的结果称为卷积特征(Convolved Feature)。其中卷积核又叫过滤器(Filter),他是一个W核矩阵,而W矩阵中各个元素的值正是我们进行模型训练时要训练的参数。即CNN的一个主要任务就是学习出卷积核

      很有趣的是,一个卷积核往往只对图中的某一特征感兴趣(如边缘信息、斜线、特定颜色等等),下图就展示了经过不同的kernel处理后得到的特征图。而在我们实际分析时,往往要综合很多内容,这就需要多个卷积核同时工作,如下图动图所示,就是在处理实际问题时的一个例子。

       值得注意的是,我们在上述分析时使用的都是黑白图像,其对应的卷积核都是二维的。而对于彩色图像,这个图像的数据往往是一个三维的数组(每个像素对应有RGB三个颜色通道),这个时候对应的卷积核就也是三维的了,对于更高维的数据,卷积核的维度也相应地改变。下图来自cs231n课程,展示的就是这样的过程:

    我们可以看到,在这个例子中:

    • Input size:输入图片的大小为 5*5*3
    • Filter size:使用了W0、W1两个filter,大小均为3*3*3
    • Stride:卷积时的步长为2
    • padding:填充大小为1

     

      根据上述的公式,我们可以计算出特征图的大小为3.

      值得注意的是:

    1. 左边数据在变化,每次滤波器都是针对某一局部的数据窗口进行卷积,这就是所谓的CNN中的局部感知机制
    2. 数据窗口滑动,导致输入在变化,但中间滤波器Filter w0的权重(即每个神经元连接数据窗口的权重)是固定不变的,这个权重不变即所谓的CNN中的权重共享机制

    【tensorflow-conv】

        tf.nn.conv2d(input,filter, strides, padding, data_format=’NHWC’) 

    • input: 4-D 的Tensor, 每个dimension的意思由data_format指定,默认是[batch, Height, Width, Channel]。
      • batchsize 表示样本数量。
      • Height/Width是图片的高度/宽度
      • Channel是深度,即决定了图片是灰度图还是彩色图。若是灰度图则为1,若是彩色图则为3。
    • filter: 这个filter也是一个4-D的Tensor,每个dimension分别表示 [filter_height, filter_width, in_channels, out_channels]。
      • 通常地称[filter_height, filter_width, in_channels]为单个filter的size,而且filter_height, filter_width一般为奇数并且相等。
      • in_channel必须跟input参数中的Channel相等,卷积运算时,从input中取一个大小为[filter_height, filter_width, in_channels]的slice window跟 单个filter做卷积运算。
      • out_channels表示有多少个这样的filter。因为filter一般用于特征的抽取,所以out_channels决定了卷积层最终输出的channel(depth)。
    • strides: 4-D的Tensor, 表示在对input做卷积运算时,在每个dimension上的步长。
      • 跟input参数一样,每个dimension的顺序由data_format决定。
      • 通常地在Height, Width上步长为1或者2,而batch, Channel的步长设置为1。
    • padding: “SAME” 或者 “Valid”。
      • Same表示边缘自动补零,卷积层的输出的height/width 跟input层的height/width相同。
      • Valid表示no padding,不自动填充,输出层的公式为 (heightfilter_heigth)/stride_height+(width也是一样)。
    weights = {
      'wc1': tf.Variable(tf.random_normal([3,3,1,64],stddev = 0.1))
    }
    _input = tf.reshape(input,shape = [-1,28,28,1])
    _conv1 = tf.nn.con2v(_input , w['wc1'],strides = [1,1,1,1],padding='Same')
    

      

    【池化(Pooling)】

      池化操作(pooling)的本质就是采样,可以采取的操作有:最大化、平均化、加和等。最常用并且被证明效果很好的池化操作为最大池化。 

      所谓最大池化就是,我们定义一个空间临域(比如一个2X2的窗口),并从窗口内的特征图中取出最大的元素。

     

      池化的意义如下:

    1. 有效地减少参数但又能保留主要特征
    2. 有效的防止过拟合(使得卷积核偏好的特征得到保留和增强,削弱其他干扰)
    3. 发挥特征图的“不变性”(invariance),特征的平移、旋转、尺寸变化对网络的影响可以得到一定程度上的缓解

     【tensorflow-pooling】

        tf.nn.max_pool(value, ksize = [1,f,f,1], strides = [1,s,s,1], padding = ‘SAME’, data_format=’NHWC’) 

    • value: 4-D的tensor, 一般地就是上面conv2d的输出,所以输入通常是feature map,依然是[batch, height, width, channels]这样的shape;
    • ksize: 定义了池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],因为我们不想在batch和channels上做池化,所以这两个维度设为了1;
    • strides:和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]
    • padding:和卷积类似,可以取'VALID' 或者'SAME'
    input = tf.reshape(input,[1,4,4,2])
    pooling=tf.nn.max_pool(input,[1,2,2,1],[1,2,2,1],padding='VALID')  
    

     【Backpropagation】

      反向传播是在求解损失函数L对参数w求导时候用到的方法,目的是通过链式法则对参数进行一层一层的求导,进而实现对 W 的更新。下面是简单的BP算法的大致过程,但很难理解,建议先看连接中的内容再回过头来看这个总结。

    • 首先前向传导计算出所有节点的激活值和输出值,

         激活值

    • 计算整体损失函数: 

        损失函数

    • 然后针对第L层的每个节点计算出残差(这里是因为UFLDL中说的是残差,本质就是整体损失函数对每一层激活值Z的导数),所以要对W求导只要再乘上激活函数对W的导数即可 

    cancha

       有一个博客很好的总结了相关的内容:https://blog.csdn.net/u014688145/article/details/78691262

     【梯度消散和梯度爆炸】

    • (基本概念)靠近输入的神经元会比靠近输出的神经元的梯度成指数级衰减。总的来说,就是在这个深度网络中,梯度相当不稳定(unstable)。
      • 靠近输出层的hidden layer 梯度大,参数更新快,所以很快就会收敛;而靠近输入层的hidden layer 梯度小,参数更新慢,几乎就和初始状态一样,随机分布。这种现象就是梯度弥散(vanishing gradient problem)。

      • 而在另一种情况中,前面layer的梯度通过训练变大,而后面layer的梯度指数级增大,这种现象又叫做梯度爆炸(exploding gradient problem)。

    • (问题一)sigmoid时,消失和爆炸哪个更易发生?
      • 最普遍发生的是梯度消失问题。
      • 量化分析梯度爆炸出现时a的输出范围:因为sigmoid导数最大为1/4,故只有当abs(w)>4时才可能出现。由此计算出a的数值变化范围很小,仅仅在此窄范围内会出现梯度爆炸问题。
    • (问题二)如何解决梯度消失和梯度爆炸?
      • 梯度消失:使用ReLU,maxout等替代sigmoid。
      • 梯度爆炸:使用Gradient Clipping(梯度裁剪)。通过Gradient Clipping,将梯度约束在一个范围内,这样不会使得梯度过大。 
    • (问题三)为何用Relu好使?即Relu和sigmoid区别:
      • sigmoid函数值在[0,1],ReLU函数值在[0,+无穷],所以sigmoid函数可以描述概率,ReLU适合用来描述实数;
      • sigmoid函数的梯度随着x的增大或减小和消失,而ReLU不会。

      

     

  • 相关阅读:
    模拟操作(键盘、鼠标)三
    获取硬件信息
    MVC+ajax权限管理
    Socket通信简介
    网页页头meta详解(科普知识)
    .Net 无法打开Offie Open XML文件(上传和下载使用)
    临时散文,哈哈
    SQL server中的一些查询
    vue 钩子函数中获取不到DOM节点
    HTML技巧:怎样禁止图片拖动复制
  • 原文地址:https://www.cnblogs.com/hithongming/p/11163141.html
Copyright © 2011-2022 走看看