Skip to content
Bo's Blog
Go back

Coursera机器学习笔记(九) - 神经网络(下)


一. 代价函数

在神经网络中我们使用L来表示总的层数, 例如下图中L=4; 使用sls_l表示在第ll层中unit的个数(不包括bias unit), 如下图中s1=3s_1=3, s2=5s_2=5, s3=5s_3=5, sL=4s_L=4. 对于一个分类问题要么是二分类(Binary classification)要么是多分类(Multi-class classification). 对于二分类问题, 神经网络只需要一个输出单元; 而对于多分类问题, 需要K个输出单元, 其中K为类的个数. 这里我们按照多分类对代价函数进行描述. 下图为神经网络的代价函数与logistic回归的代价函数的对比. 对于前半部分, 因为神经网络中有K个输出, 所以先要对这K个输出的损失求和; 对于后半部分, 因为每一层(除了输出层)都有一个Θ\Theta, 所以正则化项要将这些权重都包括进来(当然, 不需要包括bias unit的权重). 如下图所示, hΘ(x)h_\Theta(x)是一个K维的向量, 即hΘ(x)I!RKh_\Theta(x) \in \rm I\\!R^K, 我们用(hΘ(x))i(h_\Theta(x))_i来表示第ii个输出值.
下面这段文字是这个课程wiki对于神经网络代价函数的解释.

  • the double sum simply adds up the logistic regression costs calculated for each cell in the output layer;
  • the triple sum simply adds up the squares of all the individual Θs in the entire network;
  • the i in the triple sum does not refer to training example i.

二. 逆/反向传播算法

知道了代价函数之后, 我们还是按照套路来求代价函数的最优解. 同样地, 我们希望使用梯度下降来找到最优解. 想要使用梯度下降当然需要求出”梯度”即偏导项Θij(l)J(Θ)\frac{\partial}{\partial\Theta_{ij}^{(l)}}J(\Theta). 而计算这个偏导项的过程就叫做逆传播算法或者叫反向传播算法. 首先我们根据前向传播算法来得到a(1)a^{(1)}, a(2)a^{(2)}, a(3)a^{(3)}, a(4)a^{(4)}z(2)z^{(2)}, z(3)z^{(3)}, z(4)z^{(4)}. 在逆传播算法中我们定义每层的误差

δ(l)=z(l)J(Θ)\delta^{(l)}=\frac{\partial}{\partial z^{(l)}}J(\Theta)

δj(l)\delta_j^{(l)}表示第ll层第jj个节点的误差. 为了求出偏导项Θij(l)J(Θ)\frac{\partial}{\partial\Theta_{ij}^{(l)}}J(\Theta), 我们首先要求每一层的δ\delta(不包括第一层, 因为第一层是输入层). 首先, 对于输出层即第4层(这里我们不考虑正则化):

δj(4)=zi(4)J(Θ) =J(Θ)ai(4)ai(4)zi(4) =ai(4)k=1K[yklogak(4)+(1yk)log(1ak(4))]g(zi(4)) =ai(4)[yilogai(4)+(1yi)log(1ai(4))]g(zi(4))(1g(zi(4))) =(1yi1ai(4)yiai(4))ai(4)(1ai(4)) =(1yi)ai(4)yi(1ai(4)) =ai(4)yi\begin{align} \delta_j^{(4)} & = \frac{\partial}{\partial z_i^{(4)}}J(\Theta) \\\ & = \frac{\partial J(\Theta)}{\partial a_i^{(4)}}\frac{\partial a_i^{(4)}}{\partial z_i^{(4)}} \\\ & = -\frac{\partial}{\partial a_i^{(4)}}\sum_{k=1}^K\left[y_kloga_k^{(4)}+(1-y_k)log(1-a_k^{(4)})\right]g'(z_i^{(4)}) \\\ & = -\frac{\partial}{\partial a_i^{(4)}}\left[y_iloga_i^{(4)}+(1-y_i)log(1-a_i^{(4)})\right]g(z_i^{(4)})(1-g(z_i^{(4)})) \\\ & = \left(\frac{1-y_i}{1-a_i^{(4)}}-\frac{y_i}{a_i^{(4)}}\right)a_i^{(4)}(1-a_i^{(4)}) \\\ & = (1-y_i)a_i^{(4)} - y_i(1-a_i^{(4)}) \\\ & = a_i^{(4)} - y_i \end{align}

(关于 g(zi(4))g'(z_i^{(4)}) 的证明见本文最后的补充材料。其中 aj(4)a_j^{(4)} 就是 (hΘ(x))j(h_\Theta(x))_jjj 就是输出单元的个数,用向量化的表示为:δ(4)=a(4)y\delta^{(4)}=a^{(4)}-y。对于剩下每层的 δi(l)\delta_i^{(l)} 如下:

δi(l)=zi(l)J(Θ) =j=1SjJ(Θ)zj(l+1)zj(l+1)ai(l)ai(l)zi(l) =j=1Sjδj(l+1)Θij(l)g(zi(l)) =g(zi(l))j=1Sjδj(l+1)Θij(l)\begin{align} \delta_i^{(l)} & = \frac{\partial}{\partial z_i^{(l)}}J(\Theta) \\\ & = \sum_{j=1}^{S_j}\frac{\partial J(\Theta)}{\partial z_j^{(l+1)}}\cdot\frac{\partial z_j^{(l+1)}}{\partial a_i^{(l)}}\cdot\frac{\partial a_i^{(l)}}{\partial z_i^{(l)}} \\\ & = \sum_{j=1}^{S_j}\delta_j^{(l+1)}\cdot\Theta_{ij}^{(l)}\cdot g'(z_i^{(l)}) \\\ & = g'(z_i^{(l)})\sum_{j=1}^{S_j}\delta_j^{(l+1)}\cdot\Theta_{ij}^{(l)} \end{align}

写成向量的形式即为:

δ(l)=(Θ(l))Tδ(l+1).g(z(l))\delta^{(l)}=(\Theta^{(l)})^T\delta^{(l+1)}.*g'(z^{(l)})

求出来所有的δ\delta之后, 可以很容易得到Θij(l)J(Θ)=ai(l)δj(l+1)\frac{\partial}{\partial\Theta_{ij}^{(l)}}J(\Theta)=a_i^{(l)}\delta_j^{(l+1)}, 这就是我们要求的偏导项(忽略正则化). 上面所有的推导都是基于一个样本的, 现在假设有mm个样本, 我们可以使用BGD来求解最优值. 假设我们有一个训练集如下图所示, 对于所有的l,i,jl,i,j我们先令Δij(l)=0\Delta_{ij}^{(l)}=0, 然后对于每一个样本, 都进行如下图所示的计算并使用Δij(l)\Delta_{ij}^{(l)}进行累加. 其中Δij(l):=Δij(l)+aj(l)δi(l+1)\Delta_{ij}^{(l)}:=\Delta_{ij}^{(l)}+a_j^{(l)}\delta_i^{(l+1)}用向量的表示形式为:Δ(l):=Δ(l)+δ(l+1)(a(l))T\Delta^{(l)}:=\Delta^{(l)}+\delta^{(l+1)}(a^{(l)})^T. 最后, 计算出Dij(l)D_{ij}^{(l)}如下图所示(注意,ppt上有个小错误, 根据我们的代价函数应该是Dij(l):=1m(Δij(l)+λΘij(l))D_{ij}^{(l)}:=\frac{1}{m}(\Delta_{ij}^{(l)}+\lambda\Theta_{ij}^{(l)})). 关于BP算法, 可以参考Caltech的Learning from Data.

三. 参数调整

为了使用高级优化算法, 这一节我们讲如何调整参数. 在神经网络中, 参数Θ(j)\Theta^{(j)}是一个矩阵, 而在之前利用高级优化算法的课程中, 我们知道θ\theta是一个向量, 这个时候就需要对Θ\Theta进行Unrolling. 如下图所示的神经网络中, (ppt中出现了一些错误, 根据Θ1\Theta_1, Θ2\Theta_2, Θ3\Theta_3, 这个神经网络应该是有4层, 并且s1=10s_1=10, s2=10s_2=10, s3=10s_3=10, s4=1s_4=1. )Θ(1)\Theta^{(1)}, Θ(2)\Theta^{(2)}, Θ(3)\Theta^{(3)}, D(1)D^{(1)}, D(2)D^{(2)}, D(3)D^{(3)}如下图所示, 在Octave/Matlab中, 我们可以使用如下代码将所有对应的矩阵转化成一个向量:

  thetaVec = [Theta1(:); Theta2(:); Theta3(:)];
  DVec = [D1(:); D2(:); D3(:)]
  %使用如下代码可以得到原来的矩阵
  Theta1 = reshape(thetaVec(1: 110), 10, 11);
  Theta2 = reshape(thetaVec(111: 220), 10, 11);
  Theta3 = reshape(thetaVec(221: 231), 1, 11);

下图为利用unrolling来使用高级优化算法的步骤:

四. 梯度检查

由于神经网络的复杂性, 我们在使用梯度下降或者其他的高级优化算法时可能会出现bug, 即使感觉上好像没什么问题. 那么如何能有效地检查出问题呢, 这个时候就需要使用Gradient Checking. 首先, 如下图所示, 我们使用如下近似:ddθJ(θ)J(θ+ϵ)J(θϵ)2ϵ\frac{d}{d\theta}J(\theta)\approx \frac{J(\theta+\epsilon)-J(\theta-\epsilon)}{2\epsilon}, 通常我们取ϵ=104\epsilon=10^{-4}.
上面的例子中θ\theta是一个实数, 在下图中, θ\theta是一个向量, 此时是对偏导数进行数值估计.
在实际运用中, 我们使用如下代码来计算gradApprox. 然后, 我们将通过逆传播算法计算得来的DVec和gradApprox进行比较, 如果这两个值近似的话, 那么就说明我们的逆传播算法运行地没有问题. 下图描述了使用Gradient Checking时的步骤. 需要主意的是, 在得到gradApprox之后一定要即时关闭Gradient Checking, 因为它会非常大地消耗计算资源.

五. 随机初始化

在之前的linear regression和logistic regression中我们初始化θ\theta的值为0. 在神经网络中也可以这么初始化吗? 现初始化Θij(l)=0\Theta_{ij}^{(l)}=0, 此时会有a1(2)=a2(2)a_1^{(2)}=a_2^{(2)}, δ1(2)=δ2(2)\delta_1^{(2)}=\delta_2^{(2)}. 这样不论进行多少次更新, 永远会有a1(2)=a2(2)a_1^{(2)}=a_2^{(2)}, 也就是说这两个神经元是完全等同的, 这显然不合理, 那么我们应该如何初始化参数呢? 对于Θ(1)R10×11\Theta^{(1)} \in \mathbb{R}^{10\times 11}, 使用随机函数来进行初始化:

Theta1 = rand(10, 11)*(2*INIT_EPSILON) - INIT_EPSILON

六. 模型选择

神经网络有许许多多种结构, 我们应该如何选择神经网络的结构? 在神经网络中, 有两个是确定的, 那就是输入单元的个数和输出单元的个数. 因为前者就是特征的个数(维度), 而后者是分类的数量. 一个合理的默认值为, 有一个隐藏层;或者有多个隐藏层, 并且这些隐藏层单元数量相等.

七. 总结

八. 应用

视频地址

以下为补充材料:

g(z)z=(11+ez)2z(1+ez) =(11+ez)2ez(1) =(11+ez)(11+ez)(ez) =(11+ez)(ez1+ez) =(11+ez)(1+ez1+ez11+ez) =g(z)(1g(z)) \begin{align} \frac{\partial g(z)}{\partial z} & = -\left( \frac{1}{1 + e^{-z}} \right)^2\frac{\partial{}}{\partial{z}} \left(1 + e^{-z} \right) \\\ & = -\left( \frac{1}{1 + e^{-z}} \right)^2e^{-z}\left(-1\right) \\\ & = \left( \frac{1}{1 + e^{-z}} \right) \left( \frac{1}{1 + e^{-z}} \right)\left(e^{-z}\right) \\\ & = \left( \frac{1}{1 + e^{-z}} \right) \left( \frac{e^{-z}}{1 + e^{-z}} \right) \\\ & = \left( \frac{1}{1+e^{-z}}\right)\left( \frac{1+e^{-z}}{1+e^{-z}}-\frac{1}{1+e^{-z}}\right) \\\ & = g(z) \left( 1 - g(z)\right) \\\ \end{align}

Share this post on:

Previous Post
Coursera机器学习笔记(十) - 机器学习经验方法总结
Next Post
Coursera机器学习笔记(八) - 神经网络(上)