• 深度学习500问——Chapter03:深度学习基础(1)


    文章目录


    3.1 基本概念

    3.1.1 神经网络组成

    神经网络类型众多,其中最为重要的是多层感知机。为了详细地描述神经网络。我们先从最简单的神经网络说起。

    感知机

    多层感知机中的特征神经元模型称为感知机,由Frank Rosenblatt于1957年发明。

    简单的感知机如下图所示:

    其中,x_1,x_2,x_3为感知机的输入,其输出为:

    \begin{cases} 0, & \text{if } \sum_{i} w_{i}x_{i} < \text{threshold} \\ 1, & \text{if } \sum_{i} w_{i}x_{i} > \text{threshold} \end{cases}

    假如把感知机想象一个加权投票机制,比如3位评委给一个歌手打分,打分分别为4分、1分、-3分,这3位评分的权重分别是1、3、2,则该歌手最终的得分为:

    4\times 1+1\times 3+ (-3)\times 3=1。按照比赛规则,选取的 threshold为3,说明只有歌手的综合评分大于3时,才可顺利晋级。对照感知机,该选手被淘汰,因为:

    \text{if } \sum_{i} w_{i}x_{i} < \text{threshold} = 3, \text{ output } = 0

    用 -b 代替 threshold,输出变为:

    \begin{cases} 0, & \text{if } w \cdot x + b \leq 0 \\ 1, & \text{if } w \cdot x + b > 0 \end{cases}

    设置合适的xb,一个简单的感知机单元的与非门表示如下:

    当输入为0,1时,感知机输出为0×(2)+1×(2)+3=1

    复杂一些的感知机由简单的感知机单元组合而成:

    多层感知机

    多层感知机由感知机推广而来,最主要的特点是有多个神经元层,因此也叫深度神经网络。相比于单独的感知机,多层感知机的第i层的每个神经元和第i1层的每个神经元都有连接。

    输出层可以不止有1个神经元。隐藏层可以只有1层,也可以有多层。输出层为多个神经元的神经网络例如下图所示:

    3.1.2 神经网络有哪些常用模型结构

    下面包含了大部分常用的模型:

    3.1.3 如何选择深度学习开发平台

    现有的深度学习开源平台主要有 Caffe,PyTorch,MXNet,CNTK,Theano,TensorFlow,Keras,fastai等。那如何选择一个适合自己的平台呢。下面列出一些衡量作参考。

    参考1:与现有编程平台、技能整合的难易程度

    主要是前期积累的开发经验和资源,比如编程语言,前期数据集存储格式等。

    参考2:与机器学习、数据预处理生态整合的紧密程度

    深度学习研究离不开各种数据处理、可视化、统计推断等软件包。考虑建模之前,是否具有方便的数据预处理工具?建模之后,是否具有方便的工具进行可视化、统计推断、数据分析。

    参考3:对数据量及硬件的要求和支持

    深度学习在不同应用场景的数据量是不一样的,这也就导致我们可能需要考虑分布式计算、多GPU计算的问题。例如,对计算机图像处理研究的人员往往需要将图像文件和计算任务分布到多台计算机节点上进行执行。当下每个深度学习平台都在快速发展,每个平台对分布式计算等场景的支持也在不断演进。

    参考4:深度学习平台的成熟程度

    成熟程度的考量是一个比较主观的考量因素,这些因素可包括:社区的活跃程度;是否容易和开发人员进行交流;当前的应用势头。

    参考5:平台利用是否多样性

    有些平台是专门为深度学习研究和应用进行开发的,有些平台对分布式计算、GPU等架构都有强大的优化,能否用这些平台/软件做其他的事情?比如有些深度学习软件是可以用来求解二次型优化;有些深度学习平台很容易被扩展,被运用在强化学习的应用中。

    3.1.4 为什么使用深层表示

    1. 深度神经网络是一种特征递进式的学习算法,浅层的神经元直接从输入数据中学习一些低层次的简单特征,例如边缘、纹理等。而深层的特征则基于已学习到的浅层特征继续学习更高级的特征,从计算机的角度学习深层的语义信息。

    2. 深层的网络隐藏单元数量相对较少,隐藏层数目较多,如果浅层的网络想要达到同样的计算结果则需要指数级增长的单元数量才能达到。

    3.1.5 为什么深层神经网络难以训练

    1. 梯度消失

    梯度消失是指通过隐藏层从后向前看,梯度会变得越来越小,说明前面层的学习会显著慢于后面层的学习,所以学习会卡住,除非梯度变大。

    梯度消失的原因受到多种因素的影响,例如学习率的大小,网络参数的初始化,激活函数的边缘效应等。在深层神经网络中,每一个神经元计算得到的梯度都会传递给前一层,较浅层的神经元接收到的梯度受到之前所有层梯度的影响。如果计算得到的梯度值非常小,随着层数增多,求出的梯度更新信息将会以指数形式衰减,就会发生梯度消失。下图是不同隐含层的学习速率:

    2. 梯度爆炸

    在深度神经网络或循环神经网络(Recurrent Neural Network,RNN)等网络结构中,梯度可在网络更新的过程中不断累积,变成非常大的梯度,导致网络权重值的大幅更新,使得网络不稳定;在极端情况下,权重值甚至会溢出,变为 NaN 值,再也无法更新。

    3. 权重矩阵的退化导致模型的有效自由度减少

    参数空间中学习的退化速度减慢,导致减少了模型的有效维数,网络的可用自由度对学习中梯度范数的贡献不均衡,随着相乘矩阵的数量(即网络深度)的增加,矩阵的乘积变得越来越退化。在有硬饱和边界的非线性网络中(例如 ReLU 网络),随着深度增加,退化过程会变得越来越快。Duvenaud等人2014年的论文里展示了关于该退化过程的可视化。

    随着深度的增加,输入空间(左上角所示)会在输入空间中的每个点处被扭曲成越来越细的单丝,只有一个与细丝正交的方向影响网络的响应。

    3.1.6 深度学习和机器学习有什么不同

    机器学习

    利用计算机、概率论、统计学等知识,输入数据,让计算机学会新知识。机器学习的过程,就是训练数据去优化目标函数。

    深度学习

    是一种特殊的机器学习,具有强大的能力和灵活性。它通过学习将世界表示为嵌套的层次结构,每个表示都与更简单的特征相关,而抽象的表示则用于计算更抽象的表示。

    传统的机器学习需要定义一些手工特征,从而有目的的去提取目标信息,非常依赖任务的特异性以及设计特征的专家经验。而深度学习可以从大数据中先学习简单的特征,并从其逐渐学习到更为复杂抽象的深层特征,不依赖人工的特征工程,这也是深度学习在大数据时代受欢迎的一大原因。

    3.2 网络操作与计算

    3.2.1 前向传播与反向传播

    神经网络的计算主要有两种:前向传播(forward propagation,FP)作用于每一层的输入,通过逐层计算得到输出的结果;反向传播(backward propagation,BP)作用于网络的输出,通过计算梯度由深到浅更新网络参数。

    前向传播

    假设上一层结点i,j,k,...等一些结点与本层的结点w有连接,那么结点w的值怎么算呢?就是通过上一层的i,j,k,...等结点以及对应的连接权值进行加权和运算,最终结果再加上一个偏置项(图中为了简单省略了),最后在通过一个非线性函数(即激活函数),如ReLU、sigmoid等函数,最后得到的结果就是本层结点w的输出。

    最终不断的通过这种方法一层层的运算,得到输出层的结果。

    反向传播

    由于我们前向传播最终得到的结果,以分类为例,最终总是有误差的,那么怎么减少误差呢,当前广泛应用的一个算法就是梯度下降算法,但是求梯度就要求偏导数,下面以图中字母为例讲解一下:

    设最终误差为E且输出层的激活函数为线性激活函数,对于输出那么E对于输出节点yl的偏导数是 yltl,其中tl是真实值,ylzl是指上面提到的激活函数,zl是上面提到的加权和,那么这一层的E对于zl的偏导数为Ezl=Eylylzl。同理,下一层也是这么计算,只不过Eyk计算方法变了,一直反向传播到输入层,最后有Exi=Eyjyjzj,且zjxi=wij。然后调整这些过程中的权值,再不断进行前向传播和反向传播的过程,最终得到一个比较好的结果。

    3.2.2 如何计算神经网络的输出

    如上图,输入层有3个节点,我们将其依次编号为1、2、3;隐藏层的4个节点,编号依次是4、5、6、7;最后输出层的两个节点编号为8、9。比如,隐藏层的节点4,它与输入层的三个节点1、2、3之间都有连接,其连接上的权重分别是w41,w42,w43

    为了计算节点4的输出值,我们必须先得到其所有上游节点(也就是节点1、2、3)的输出值。节点1、2、3是输入层的节点,所有,他们的输出值就是输入向量本身。按照上图画出的对应关系,可以看到节点1、2、3的输出值分别是x1,x2,x3

    a4=σ(wa)=σ(w41x1+w42x2+w43x3+w4b)

    其中,w4b是节点4的偏置项。

    同样,我们可以继续计算节点5、6、7的输出值a5,a6,a7

    计算输出层的节点8的输出值y1

    y1=σ(wa)=σ(w84a4+w85a5+w85a6+w87a7+w8b)

    其中,w8b是节点8的偏置项。

    同理,我们还可以计算出y2。这样输出层所有节点的输出值计算完毕,我们就得到了在输入向量x1,x2,x3,x4时,神经网络的输出向量y1,y2。这里我们也可以看到,输出向量的维度和输出层神经元个数相同。

    3.2.3 如何计算卷积神经网络输出值

    假设有一个5*5的图像,使用一个3*3的filter 进行卷积,想得到一个3*3的 Featue Map,如下所示:

    xi,j表示图像第i行和第j列元素。wm,n表示 filter 第m行和第n列权重。wb表示 filter 的偏置项。ai,j表示 feature map 第i行第j列元素。f表示激活函数,这里以 ReLU函数为例。

    卷积计算公式如下:

    aij=f(2m=02n=0wm,nxi+m,j+n+wb)

    当步长为 1 时,计算 feature map 元素a0,0如下:

    a0,0=f(2m=02n=0wm,nx0+m,0+n+wb)=relu(w0,0x0,0+w0,1x0,1+w0,2x0,2+w1,0x1,0+w1,1x1,1+w1,2x1,2+w2,0x2,0+w2,1x2,1+w2,2x2,2)=1+0+1+0+1+0+0+0+1=4

    其计算过程图示如下:

    以此类推,计算出全部的Feature Map:

    当步幅为2时,Feature Map计算如下:

    注:图像大小、步幅和卷积后的Feature Map大小是有关系的。他们满足如下关系:

    W2=(W1F+2P)/S+1H2=(H1F+2P)/S+1

    其中,W2是卷积后Feature Map的宽度;W1是卷积前图像的宽度;F是filter的宽度;P是Zero Padding数量,Zero Padding是指在原始图像周围补几圈 0,如果P的值是1,那么就补1圈0;H2卷积后Feature Map的高度;H1是卷积前图像的宽度。

    举例:假设图像宽度W1=5,filter宽度F=3,Zero Padding的P=0,步幅S=2,Z则W2=(W1F+2P)/S+1=(53+0)/2+1=2

    ​ 说明 Feature Map 宽度是2。同样,我们也可以计算出 Feature Map 高度也是 2。

    如果卷积前的图像深度为D,那么相应的 filter 的深度也必须为D。深度大于1的卷积计算公式:

    aij=f(D1d=0F1m=0F1n=0wd,m,nxd,i+m,j+n+wb)

    其中,D是深度;F是filter的大小;wd,m,n表示filter的第d层第m行第n列的权重;ad,i,j表示feature map的第d层第i行第j列像素;其他的符号含义前面相同,不再赘述。

    每个卷积层可以有多个filter。每个filter和原始图像进行卷积后,都可以得到一个 Feature Map。卷积后Feature Map的深度(个数)和卷积层的filter个数相同。下面的图示显示了包含两个filter的卷积层的计算。773输入,经过两个333 filter的卷积(步幅为2),得到了332的输出。图中的Zero padding是1,也就是在输入元素的周围补了一圈0。

    以上就是卷积层的计算方法。这里面体现了局部连接和权值共享:每层神经元只和上一层部分神经元相连(卷积计算规则),且filter的权值对于上一层所有神经元都是一样的。对于包含两个333的 filter 卷积层来说,其参数数量仅有(333+1)2=56个,且参数数量与上一层神经元个数无关。与全连接神经网络相比,其参数数量大大减少了。

    3.2.4 如何计算Pooling层输出值

    Pooling层主要的作用是下采样,通过去掉Feature Map中不重要的样本,进一步减少参数数量。Pooling的方法很多,最常用的是Max Pooling。Max Pooling实际上就是在nn的样本中取最大值,作为采样后的样本值。下图是 2*2 max pooling。

    除了Max Pooling之外,最常用的还有 Average Pooling——取各样本的平均值。对于深度为Dd Feature Map,各层独立做Pooling,因此 Pooling后的深度仍然为D

    3.2.5 实例理解反向传播

    一个典型的三层神经网络如下所示:

    其中,LayerL1是输入层,LayerL2是隐藏层,LayerL3是输出层。

    假设输入数据集为D=x1,x2,...,xn,输出数据集为y1,y2,...,yn

    如果输入和输出是一样的,即为自编码模型。如果原始数据经过映射,会得到不同于输入的输出。

    假设有如下的网络层:

    输入层包含神经元i1,i2,偏置b1;隐藏层包含神经元h1,h2,偏置b2,输出层为o1,o2wi为层与层之间连接的权重,激活函数为 sigmoid 函数。对以上参数取初始值,如下图所示:

    其中:

    • 输入数据 i1=0.05,i2=0.10
    • 输出数据 i1=0.05,i2=0.10
    • 初始权重 w1=0.15,w2=0.20,w3=0.25,w4=0.30,w5=0.40,w6=0.45,w7=0.50,w8=0.55
    • 目标:给出输入数据i1,i2(0.05和0.01),使输出尽可能与原始输出o1,o2(0.01和0.99)接近。

    前向传播

    1. 输入层 → 输出层:

    计算神经元h1的输入加权和:neth1=w1i1+w2i2+b11 neth1=0.150.05+0.20.1+0.351=0.3775

    神经元h1的输出o1:(此处用到激活函数为 sigmoid 函数):

    outh1=11+eneth1=11+e0.3775=0.593269992

    同理,可计算出神经元h2的输出o1

    outh2=0.596884378

    2. 隐藏层 → 输出层:

    计算输出神经元o1o2的值:

    neto1=w5outh1+w6outh2+b21

    neto1=0.40.593269992+0.450.596884378+0.61=1.105905967

    outo1=11+eneto1=11+e1.105905967=0.75136079

    这样前向传播的过程就结束了,我们得到输出值为[0.75136079,0.772928465],与实际值[0.01,0.99]相差还很远,现在我们对误差进行反向传播,更新权重,重新计算输出。

    反向传播

    1. 计算总误差:

    总误差:(这里使用 Square Error)

    Etotal=12(targetoutput)2

    但是有两个输出,所以分别计算o1o2的误差,总误差为两者之和:

    Eo1=12(targeto1outo1)2=12(0.010.75136079)2=0.274811083

    Eo2=0.023560026

    Etotal=Eo1+Eo2=0.274811083+0.023560026=0.298371109

    2. 隐藏层 → 输出层的权值更新:

    以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5求偏导求出:(链式法则)

    Etotalb5=Etotalouto1outo1neto1neto1b5

    下面的图可以更直观的看清楚误差是怎样反向传播的:

    3.2.6 神经网络更“深”有什么意义

    前提:在一定范围内。

    • 在神经元数量相同的情况下,深层网络结构具有更大容量,分层组合带来的是指数级的表达空间,能够组合成更多不同类型的子结构,这样可以更容易地学习和表示各种特征。
    • 隐藏层增加则意味着由激活函数带来的非线性变换的嵌套层数更多,就能构造更复杂的映射关系。

  • 相关阅读:
    《动态规划 ---- 线性规划一》----- 动态规划的基本概念,线性动态规划-->背包问题
    外包干了2个月,技术退步明显...
    Linux关于yum和vim入门的一些问题
    如何才能在Ubuntu系统部署RabbitMQ服务器并公网访问
    好用的C C++ 日志宏 OutputDebugStringA 写到文件或界面
    《算法导论》第19章-斐波那契堆 引入&& 19.1 斐波那契堆结构
    [iOS]-NSOperation、NSOperationQueue
    大数据之Hudi数据湖_基本概念_文件布局_文件管理 & 基本概念_索引_的原理_索引选项_全局索引与非全局索引---大数据之Hudi数据湖工作笔记0007
    《SpringBoot系列十四》:@ConditionalOnBean、@ConditionalOnMissingBean注解居然失效了
    表白墙服务器版【交互接口、服务器端代码、前端代码、数据存入文件/数据库】
  • 原文地址:https://blog.csdn.net/leonardotu/article/details/136538038