星期五, 一月 31日 2020, 8:06 晚上

  4.4k 字     19 分钟  

这些天正在试图入门机器学习的相关内容,正好前几天与同学讨论了反向传播算法的一些问题,自己遂花了一些时间来研究了一下,正好也借着这个机会入门一下机器学习的知识,这里记录一下我对于这个算法具体理解和解读。

反向传播算法

定义

反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。
反向传播要求有对每个输入值想得到的已知输出,来计算损失函数梯度。因此,它通常被认为是一种监督式学习方法,虽然它也用在一些无监督网络(如自动编码器)中。它是多层前馈网络的Delta规则的推广,可以用链式法则对每层迭代计算梯度。反向传播要求人工神经元(或“节点”)的激励函数可微。

——来自Wiki百科的定义

Cost Function(代价函数)

代价函数(有的地方也叫损失函数,Loss Function)在机器学习中的每一种算法中都很重要,因为训练模型的过程就是优化代价函数的过程,代价函数对每个参数的偏导数就是梯度下降中提到的梯度,防止过拟合时添加的正则化项也是加在代价函数后面的。
代价函数非常好理解,我觉得其实就是,反映神经网络输出的结果与训练样本的y之间的差别的函数(其中输入变量是神经网络的权重参数)。这个函数要具有一些特性,一般情况下,我们要尽可能的最小化代价函数,寻找代价函数的全局最小值,从而找到神经网络的最优权值参数,这里不展开讨论,仅仅解释一下概念。

明确我们的目标

在完成一次前向传播后,已知J(Θ)J(\Theta)也就是C(Θ)C(\Theta)(代价函数),为了实现梯度下降:θ(l):=θ(l)Cθ(l)\theta^{(l)}:=\theta^{(l)}-\frac{\partial C}{\partial \theta^{(l)}}。我们需要求Cθ(l)\frac{\partial C}{\partial \theta^{(l)}}

算法流程详解

-注:此处以吴恩达机器学习视频中讲解的算法首先进行阐述。
假设目前我们已经有了一个多层,但是网络权值参数还没有更新。

首先,我要说明一下计算中所用到的参数符号及其解释:

  • xjx_j仅仅表示最左侧输入层的输入,下标jj表示第jj个单元(unit)。

  • θi,j(l)\theta_{i,j}^{(l)}表示从第(l)(l)层的第ii个单元到第(l+1)(l+1)层的第j个单元的θ\theta

  • θ(l)\theta^{(l)}θi,j(l)\theta_{i,j}^{(l)}的矩阵形式。θ(l)\theta^{(l)}中的每一行(ii相同)是ai(l)a_i^{(l)}所散发给下一层的参数,是aj(l)a_j^{(l)}的接收参数

  • ll表示网络的总层数,l=l=网络总层数

  • aj(l)a_{j}^{(l)}表示表示第ll层的第jj个神经元的输出

  • zj(l)z_{j}^{(l)}表示表示第ll层的第jj个神经元的输入

  • aj(l)=g(zj(l))=sigmoid(zj(l))a_{j}^{(l)}=g^{\prime}\left(z_{j}^{(l)}\right)=\operatorname{sigmoid}^{\prime}\left(z_{j}^{(l)}\right)其中sigmoid是激活函数

  • aj(l1)a_{j}^{(l-1)}zj(l)z_{j}^{(l)}的转化如图所示

  • C(Θ)C(\Theta)是代价函数,在这里

    J(Θ)=C(Θ)=1mi=1mk=1k[yk(i)log((hΘ(x(i)))k)+(1yk(i))log(1(hΘ(x(i)))k)]+λ2ml=1L1i=1slj=1s(l+1)(Θj,i(l))2J(\Theta)=C(\Theta)=\\-\frac{1}{m} \sum_{i=1}^{m} \sum_{k=1}^{k}\left[y_{k}^{(i)} \log \left(\left(h_{\Theta}\left(x^{(i)}\right)\right)_{k}\right)+\left(1-y_{k}^{(i)}\right) \log \left(1-\left(h_{\Theta}\left(x^{(i)}\right)\right)_{k}\right)\right]\\+\frac{\lambda}{2 m} \sum_{l=1}^{L-1} \sum_{i=1}^{s l} \sum_{j=1}^{s_{(l+1)}}\left(\Theta_{j, i}^{(l)}\right)^{2}

  • s(l)s_{(l)}表示a(l)a^{(l)}神经元的个数

  • 当然你也可以使用其他的代价函数,还有一个常用的代价函数是二次代价函数:

    C=12nxy(x)aL(x)2C=\frac{1}{2 n} \sum_{x}\left\|y(x)-a^{L}(x)\right\|^{2}

下面放一张吴恩达机器学习反向传播的算法的图片:

下面我将一行一行进行讲解:

  1. 首先第一行没什么说的,就是目前有m个训练样本,接下来我们要对这m个训练样本进行一些神奇的操作,使得构建的神经网络更加准确。

  2. 第二行设置了一个变量,每一个ij(l)\triangle_{i j}^{(l)}都对应着θi,j(l)\theta_{i, j}^{(l)},这里ij(l)\triangle_{i j}^{(l)}只是用来计算Θij(l)J(Θ)\frac{\partial}{\partial \Theta_{i j}^{(l)}} J(\Theta)的一个变量,后面我会详细进行解释。

  3. 第三行是一个循环语句,对于每一对训练数据(x(i),y(i))\left(x^{(i)}, y^{(i)}\right)(一共m个),都进行如下的操作。

  4. 首先将训练数据的x输入,也就是a(1)=x(i)a^{(1)}=x^{(i)}

  5. 首先进行正向传播(假设θi,j(l)\theta_{i,j}^{(l)}都有初值,这里的初值后面还会通过反向传播进行更新,应该是可以人为随意确定),这里过程就忽略了,总之通过正向传播我可得到每一层的a(l)a^{(l)}zj(l)z_{j}^{(l)}(当l=2,3,,Ll=2,3, \ldots, L的时候)

  6. 下面开始反向传播的过程,首先计算一个值δ(L)\delta^{(L)},我们通常把这个值叫做"误差",每一个神经元以及每一对训练数据都会对应一个误差值,关于这个误差值为什么这么计算,以及如何用最后一层的误差值来计算前面几层的误差值(其实就是所谓的反向传播),我会放在后文来解释。总之这个目前我们可以理解为,δ\delta用来表示与神经元计算结果与正确结果的偏差值,由于计算结果(最后一层)存在"误差",所以将最后一层的"误差"通过一定的计算方法来反推各个神经元的"误差",然后利用每个神经元的每个训练样本所找到的误差之和来更新θi,j(l)\theta_{i, j}^{(l)},这就是我们反向传播的基本目标,后面我会详细讲解这之中的公式。最后一层"误差"的计算公式是这样的:δ(L)=a(L)y\delta^{(L)}=a^{(L)}-y
    其中L表示最后一层(输出层),这个公式看起来比较合理,你可能会想为什么要这么计算,请 不要着急,关于为什么这么计算,它是有一定的道理的,我会放在后面进行解释。

  7. 下面将进行与正向传播相似的过程,计算δ(L1),δ(L2),,δ(2)\delta^{(L-1)}, \delta^{(L-2)}, \ldots, \delta^{(2)},(计算这些参数的算法我将在后文进行具体的阐述),当然第一层就是输入层,也不存在所谓的"误差",所以并不需要考虑δ(1)\delta^{(1)}
    然后将每个训练样本计算出来的误差先乘以aj(l)a_{j}^{(l)}再进行累加,这个大概的意思是将每个训练样本存在的误差都综合起来,后文我会详细阐述为什么要这么做。

  8. 我们进行最后一步操作(关于为什么要这么做,我会在后面进行详细的解释。):

Di,j(l):=1m(Δi,j(l)+λΘi,j(l)),ifj0Di,j(l):=1mΔi,j(l),ifj=0\begin{aligned} &\cdot D_{i, j}^{(l)}:=\frac{1}{m}\left(\Delta_{i, j}^{(l)}+\lambda \Theta_{i, j}^{(l)}\right), i f j \neq 0\\ &\cdot D_{i, j}^{(l)}:=\frac{1}{m} \Delta_{i, j}^{(l)}, i f j=0 \end{aligned}

通过上一步的式子,我们可以计算出我们的梯度目标:

Θij(l)J(Θ)=Dij(l)\frac{\partial}{\partial \Theta_{i j}^{(l)}} J(\Theta)=D_{i j}^{(l)}

关于为什么要这么算,我会在后面讲解。

关于δ\delta

δ\delta在很多书中翻译为‘误差’,但这与模型预测值与样本y之间的误差不是一个概念。实际上δ\delta是一个微分值。书上将其定义为:

δ(l)=Cz(l)\delta(l)=\frac{\partial C}{\partial z^{(l)}}

我觉得它这么定义是为了简化我们的计算,当然如果没有δ\delta,我们也完全可以使用链式法则的方法来一一计算θ(l)\theta^{(l)},有了这个中间值,可以简化计算,不用对每一层θ的偏导计算都从网络的输出层开始重新计算一遍。事实上没有这个中间值你也能完整表达整个网络的梯度求导,只不过网络层数一多进行计算的式子会非常复杂(容易晕,亲身体会)。
我们的别忘了我们的目的是求Cθ(l)\frac{\partial C}{\partial \theta^{(l)}},如果我们知道δ(l)=Cz(l)\delta(l)=\frac{\partial C}{\partial z^{(l)}},那么由链式法则我们可以知道

Cθ(l)=Cz(l+1)z(l+1)θ(l)=δ(l+1)z(l+1)θ(l)\frac{\partial C}{\partial \theta^{(l)}}=\frac{\partial C}{\partial z^{(l+1)}} \cdot \frac{\partial z^{(l+1)}}{\partial \theta^{(l)}}=\delta^{(l+1)} \cdot \frac{\partial z^{(l+1)}}{\partial \theta^{(l)}}

z(l+1)θ(l)\frac{\partial z^{(l+1)}}{\partial \theta^{(l)}}恰好等于a(l)a^{(l)}(线性函数求导)。
因此:

Cθ(l)=δ(l+1)a(l)\frac{\partial C}{\partial \theta^{(l)}}=\delta^{(l+1)} \cdot a^{(l)}

有了以上的式子,如果我们找到θ(l)\theta^{(l)}θ(l+1)\theta^{(l+1)}之间的关系,那我们就可以计算出所有权重的梯度啦!

寻找层与层之间"误差"的关系

首先我们已知:

z(l+1)=θ(l) sigmoid (z(l))z^{(l+1)}=\theta^{(l)} \cdot \text { sigmoid }\left(z^{(l)}\right)

sigmoid(z(l))=a(l)(1a(l))\text {sigmoid}^{\prime}\left(z^{(l)}\right)=a^{(l)} \cdot\left(1-a^{(l)}\right)

那么由链式法则我们可以知道:

δ(l)=Cz(l)=Cz(l+1)z(l+1)z(l)=δ(l+1)(θ(l))Ta(l)(1a(l))\delta^{(l)}=\frac{\partial C}{\partial z^{(l)}}=\frac{\partial C}{\partial z^{(l+1)}} \cdot \frac{\partial z^{(l+1)}}{\partial z^{(l)}}=\\\delta^{(l+1)} \cdot\left(\theta^{(l)}\right)^{T} \cdot a^{(l)} \cdot\left(1-a^{(l)}\right)

大功告成!我们找到了层与层之间误差的关系,同时这也是吴恩达视频里面提到的公式:


确定输出层的"误差"

由以上的定义我们可以知道,δ(l)=Cz(l)\delta(l)=\frac{\partial C}{\partial z^{(l)}},这里将解释输出层的"误差"为什么是δ(L)=a(L)y\delta^{(L)}=a^{(L)}-y
我们知道δ(l)\delta^{(l)}δ(l+1)\delta^{(l+1)}之间的关系,就能从输出层一层层的往输入层推。但是在输出层因为没有下一层节点,所以δ(l)\delta^{(l)}需要用另一种方式确定。
根据定义:

δ(l)=Cz(l)\delta(l)=\frac{\partial C}{\partial z^{(l)}}

由前文中我们可以知道代价函数为:

J(Θ)=C(Θ)=1mi=1mk=1k[yk(i)log((hΘ(x(i)))k)+(1yk(i))log(1(hΘ(x(i)))k)]+λ2ml=1L1i=1slj=1s(l+1)(Θj,i(l))2J(\Theta)=C(\Theta)=\\-\frac{1}{m} \sum_{i=1}^{m} \sum_{k=1}^{k}\left[y_{k}^{(i)} \log \left(\left(h_{\Theta}\left(x^{(i)}\right)\right)_{k}\right)+\left(1-y_{k}^{(i)}\right) \log \left(1-\left(h_{\Theta}\left(x^{(i)}\right)\right)_{k}\right)\right]\\+\frac{\lambda}{2 m} \sum_{l=1}^{L-1} \sum_{i=1}^{s l} \sum_{j=1}^{s_{(l+1)}}\left(\Theta_{j, i}^{(l)}\right)^{2}

我们考虑单个训练样本,省略m,并且认为输出神经元只有一个,那么式子可以简化为:

J(θ)=C(θ)=[ylog(a(L))+(1y)log(1a(L))]J(\theta)=C(\theta)=-\left[y \cdot \log \left(a^{(L)}\right)+(1-y) \log \left(1-a^{(L)}\right)\right]

我们接着推导:

Cz(L)=J(Θ)a(L)a(L)z(L)\frac{\partial C}{\partial z^{(L)}}=\frac{\partial J(\Theta)}{\partial a^{(L)}} \cdot \frac{\partial a^{(L)}}{\partial z^{(L)}}

Ca(L)=a(L)y(1a(L))a(L)\frac{\partial C}{\partial a^{(L)}}=\frac{a^{(L)}-y}{\left(1-a^{(L)}\right) \cdot a^{(L)}}

a(L)z(L)=a(L)(1a(L))\frac{\partial a^{(L)}}{\partial z^{(L)}}=a^{(L)} \cdot\left(1-a^{(L)}\right)

因此:

Cz(L)=δ(L)=a(L)y\frac{\partial C}{\partial z^{(L)}}=\delta^{(L)}=a^{(L)}-y

大功告成!这个结果似乎出乎意料,这正好与我们概念上理解的误差如此相似!我想这大概就是数学之美吧~

笔者补充

关于Δi,j(l):=Δi,j(l)+aj(l)δi(l+1)\Delta_{i, j}^{(l)}:=\Delta_{i, j}^{(l)}+a_{j}^{(l)} \delta_{i}^{(l+1)}这个式子:
上面已经推导过了,

Cθ(l)=δ(l+1)a(l)\frac{\partial C}{\partial \theta^{(l)}}=\delta^{(l+1)} \cdot a^{(l)}

根据以上式子,我们可以了解到Δ\Delta是用来将每一个样本计算出来的梯度值进行累加,因为我们刚才是将m的条数看作为1,而实际上有很多训练数据,这个操作可以看作是原代价函数的中的m个累加操作,而下面这个式子:

Di,j(l):=1m(Δi,j(l)+λΘi,j(l)),ifj0Di,j(l):=1mΔi,j(l),ifj=0\begin{aligned} &\cdot D_{i, j}^{(l)}:=\frac{1}{m}\left(\Delta_{i, j}^{(l)}+\lambda \Theta_{i, j}^{(l)}\right), i f j \neq 0\\ &\cdot D_{i, j}^{(l)}:=\frac{1}{m} \Delta_{i, j}^{(l)}, i f j=0 \end{aligned}

这两个式子是由原来那个十分复杂的代价函数来求梯度所得到的。其中j=0时是表示偏移项b的梯度,j不等于0时是表示一般项的梯度(其中λΘi,j(l)\lambda \Theta_{i, j}^{(l)}应该表示的是正则项)。
有了梯度值,我们设定了合理的梯度下降参数,就可以更新神经网络的权值啦!


此外,如果你觉得δ\delta这个概念理解起来太困难,也完全没有关系,我认为可以完全不需要理解δ\delta这个概念,直接利用链式法则,从最后一层层层向前推导,其实答案是一样,原理都相同。而且我看了网上这么多的教程,网上对δ\delta这个概念的定义很乱。使用不同的cost function,按照原来的定义来计算δ\delta,最后一层的值就不再是本文中的式子了(这也打破了直观上的"误差"似乎是一种巧合,或者前人专门定义成这样,方便计算与理解)。我们还是不要太纠结于对δ\delta的定义,当然本文使用的是吴恩达的定义,我觉得它的更具权威性,也好理解。
我也是菜鸟一枚,希望写的不对的地方,还希望大家多多指正。

参考

1.吴恩达机器学习视频-B站-反向传播算法
2.https://blog.csdn.net/u014313009/article/details/51039334
3.https://blog.csdn.net/zhq9695/article/details/82864551

另外吹一波公式识别软件(OCR),Mathpix实在是太强大啦!图片,手写公式都能完美转化为Latex格式,简直是科研人的福音,只可惜现在收费了,一个月的免费次数只有50次,嘤嘤嘤,太可惜了。



机器学习     

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

 目录

"觉得赞的话,微信扫一扫赞赏一下吧"



Plugins