本章,我们先来讨论一个学习算法,它能在给定训练集时为神经网络拟合参数。
代价函数
假设我们有一个神经网络,如下:
假设我们有一个像这样的训练集:
我们用再做一些记号:
L:代表神经网络的总层数。
S_l:代表第l层的神经元数量,其中不包括第L层的偏差单元。
还记得吗?我们逻辑回归代价函数公式:
现在放出我们的神经网络的代价函数公式:
(哇,看起来很复杂,但其实不难理解)
与回归代价函数相比,神经网络的代价函数公式在它基础上增加了点东西而已。原来cost函数加上求和k之后,等于遍历了神经网络里的cost函数。后面的惩罚值求和公式意思也就是每层s_l层和s_l+1层之间的θ。
代价函数最小化
下面我们来讲讲代价函数最小化的方法。我们也称它为反向传播。
我们需要做的是:写一个代码,这个代码获得输入参数θ并计算代价函数J(θ)和这些j(θ)偏导项。而大部分时间我们要重点关注一下如何计算这些偏导项。
我们有一个神经网络图,如下:
我们从只有一个训练样本的情况讲起,就是假设你的训练集只有一个训练样本(x,y)。
步骤:
首先,我们应该应用前向传播方法来计算一下在给定输入的时候,假设函数h是否会真的输出结果:
x:我们的输入值
a^(1):第一层的激活值,也就是输入层在的地方,如下:
a(2):就是第二层的激活值,g(z(2))是logistic回归的函数,(add a^(2)_0)意思是加上第二层的偏置单元。
后面都同理。
接下来,我们为了计算导数项,我们将使用反向传播的算法。
反向传播(Backpropagation)
记号
我们先了解一个记号,方便后面的理解:
δ(l)_j:代表第l层的第j个节点的误差,也就是是捕捉a(l)_j这个激活值的误差。误差的意思是,这个激活值的值和我们想象的有偏差。
L:是神经网络的总层数,我们用回上图有4层的神经网络结构做例子,所以我们的总层数L = 4
线性问题反向传播的推导与计算(无正则化)
上面我们只说了怎么用,我们却不知道反向传播是怎么推出来的。
其实反向传播的根源,就在我们的代价函数上。
我们换一个使用线性回归函数问题的神经网络图(图4.1)进行解释:
我们把偏置单元从θ中分开出来,并用b代替。
假设我们有n个训练数据:
假设输出为n_L维的,即:
我们也把假设函数h重新闭合起来,令代价函数J变成如下公式:
如图4.1所示,我们的输出有两个,因此我们的每个输出样本为:
我们将代价函数展开一下,得:
如果展开到隐藏层,则有:
我们还可以进行展开,直到输入层,最后可得:
代价函数J仅和权重矩阵θ和偏置变量b相关,调整权重和偏置权重可以减少或增大代价。
所有训练数据的总体(平均)代价可写为:
根据我们以前的经验,显然,我们要做的是把代价函数总体的值达到最小。所以,我们要把调整权重和偏置权重变小。
怎么样让权重变小呢,对,是我们熟悉的梯度下降法,而在神经网络里,我们也可以称其为批量梯度下降法:
输出层的权重参数更新
下面我们讲讲代价函数J对θ、b进行偏导的过程。为了方便,我们把训练集当作只有一个训练样本,去掉J的下标和y的上标,如下:
我们也知道这条公式:
由求导的链式法则,对“输出层神经元的权重参数”求偏导,有:
而我们上面说过的误差值δ,其定义就是代价函数对参数z的偏导:
则代价函数对权重的偏导数可以写为:
而误差值δ也可以等于:
对于输出层神经元的其他权重参数,同样可求得:
其中:
之所以引用记号δ,除了能够简化对输出层的权重参数求偏导的表达形式以外,我们还能通过这层的δ求出下层的δ,加快了整个计算过程。
把公式推广到一般情况,假设神经网络共L层,则:
转成向量形式,则等于:
点乘就是对位元素相乘。
隐藏层的权重参数更新
我们知道了输出层怎么进行参数更新了,那隐藏层怎么进行参数更新呢?
我们再看看上面讲过的代价函数J利用误差值δ的定义对权重θ所求的偏导:
我们再利用“函数之和的求导法则”及“求导的链式法则”,把代价函数J向后展开:
以上就是反向传播的核心公式推导,它利用了l+1层的误差值δ来计算l层的误差值δ,这就是“反向传播算法”名字的由来。
矩阵表示形式:
输出层和隐藏层的偏置导数更新
对应的矩阵形式为:
公式总结
反向传播算法,可总结为下面四个公式:
这四个公式可以写成对应的矩阵(向量形式):
使用步骤
- 初始化参数θ、b,需要使用很小的随机值,不能全0或相等的值。
- 用前向传播公式计算每层的状态z和激活值a。
- 计算所有的误差δ,先算输出层的,再依次计算算从L-1层到第2层的。而第一层没有误差项一说,因为第一层是输入项。
- 求改训练数据的代价函数J对权值θ的偏导数。
分类问题反向传播(无正则化)
根据上面的反向传播推导,我们把上面代价函数J换成logistic回归函数的代价函数,把假设函数换成logistic回归函数的代价函数,进行求解,就能得到下面的一系列公式。以下图为例:
我们把偏置单元b和权重θ重新进行合并。
我们从第4层开始计算误差项δ,公式如下:
第4层的第j个单元的误差项等于这个单元的激活值减去训练样本里第j个元素的值。
因为第4层是输出单元,所以a(4)_j也可以写成假设函数(h_θ(x))_j,即:
我们也可以把δ a y这三个都看作向量,就可以忽略下标j,写成:
下一步,我们就开始计算神经网络中前面几层的误差项δ。
下面式子就是计算隐藏层δ(3)的公式,和线性的求误差公式没有区别:
其中
δ(2)和δ(3)的公式一样,只需改改层数:
而我们的logistic回归的神经网络代价函数J的偏导数是如下公式:
我们先来看个例子。
例子
假设我们有m个样本的训练集:
我们第一步是,初始化我们的误差值:
Δ就是δ的大写版本。我们让第l层的从i到j的参数θ的误差值δ设为接近0的随机值。这主要用于求代价函数J的偏导数。
接下来我们将遍历我们的训练集(x(i),y(i)):
我们要做的第一件事是:
设定a^(1)=输入层的激活函数。
然后,我们用前项传播去计算第二层到输出层的激活值
接着,我们用y(i)去计算δ(L)=a(L)-y(i)
然后,我们用反向传播方法计算δ(L-1)、δ(L-2)、……、δ(2)
最后,我们用Δ来积累我们在前面写好的偏导数项,我们也可以把他写成向量形式:
以上就是循环的内容,循环过后,我们计算D^(l)_ij的值:
j=0是不加正则项,j~=0时加正则项。
D就是我们的代价函数J的偏导值:
梯度检测
一开始,我们不知道我们的梯度公式(代价函数偏导公式)是否写对,这时候我们可以使用拉格朗日中值定理或者导数定义进行梯度的检测。
通过拉格朗日中值定理检测:
当ε接近于0时,就能做到一个检测的效果。
多权重参数时,进行偏导:
通过导数定义检测:
权重随机初始化
我们可以把θ值全部设为0,但是起不到任何作用。
原因是,根据前向传播和后向传播的公式,我们会得到出输出层外的激活值a和误差值δ都相等,这里我就不一一推导了。
所以我们要使用随机初始化的思想进行初始化。
我们需要把所有权重θ随机初始化分配到-ε和ε之间。
具体编程时,我们可以使用一下代码: