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

下面这段文字是这个课程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(Θ). 而计算这个偏导项的过程就叫做逆传播算法或者叫反向传播算法.
首先我们根据前向传播算法来得到a(1), a(2), a(3), a(4)和z(2), z(3), z(4).
在逆传播算法中我们定义每层的误差
δ(l)=∂z(l)∂J(Θ)
δj(l)表示第l层第j个节点的误差. 为了求出偏导项∂Θij(l)∂J(Θ), 我们首先要求每一层的δ(不包括第一层, 因为第一层是输入层). 首先, 对于输出层即第4层(这里我们不考虑正则化):
δj(4) =∂zi(4)∂J(Θ)=∂ai(4)∂J(Θ)∂zi(4)∂ai(4)=−∂ai(4)∂k=1∑K[yklogak(4)+(1−yk)log(1−ak(4))]g′(zi(4))=−∂ai(4)∂[yilogai(4)+(1−yi)log(1−ai(4))]g(zi(4))(1−g(zi(4)))=(1−ai(4)1−yi−ai(4)yi)ai(4)(1−ai(4))=(1−yi)ai(4)−yi(1−ai(4))=ai(4)−yi
(关于 g′(zi(4)) 的证明见本文最后的补充材料。其中 aj(4) 就是 (hΘ(x))j,j 就是输出单元的个数,用向量化的表示为:δ(4)=a(4)−y。对于剩下每层的 δi(l) 如下:
δi(l) =∂zi(l)∂J(Θ)=j=1∑Sj∂zj(l+1)∂J(Θ)⋅∂ai(l)∂zj(l+1)⋅∂zi(l)∂ai(l)=j=1∑Sjδj(l+1)⋅Θij(l)⋅g′(zi(l))=g′(zi(l))j=1∑Sjδj(l+1)⋅Θij(l)
写成向量的形式即为:
δ(l)=(Θ(l))Tδ(l+1).∗g′(z(l))
求出来所有的δ之后, 可以很容易得到∂Θij(l)∂J(Θ)=ai(l)δj(l+1), 这就是我们要求的偏导项(忽略正则化).
上面所有的推导都是基于一个样本的, 现在假设有m个样本, 我们可以使用BGD来求解最优值. 假设我们有一个训练集如下图所示, 对于所有的l,i,j我们先令Δij(l)=0, 然后对于每一个样本, 都进行如下图所示的计算并使用Δij(l)进行累加. 其中Δij(l):=Δij(l)+aj(l)δi(l+1)用向量的表示形式为:Δ(l):=Δ(l)+δ(l+1)(a(l))T. 最后, 计算出Dij(l)如下图所示(注意,ppt上有个小错误, 根据我们的代价函数应该是Dij(l):=m1(Δij(l)+λΘij(l))).
关于BP算法, 可以参考Caltech的Learning from Data.
三. 参数调整
为了使用高级优化算法, 这一节我们讲如何调整参数. 在神经网络中, 参数Θ(j)是一个矩阵, 而在之前利用高级优化算法的课程中, 我们知道θ是一个向量, 这个时候就需要对Θ进行Unrolling.
如下图所示的神经网络中, (ppt中出现了一些错误, 根据Θ1, Θ2, Θ3, 这个神经网络应该是有4层, 并且s1=10, s2=10, s3=10, s4=1. )Θ(1), Θ(2), Θ(3), D(1), D(2), 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.
首先, 如下图所示, 我们使用如下近似:dθdJ(θ)≈2ϵJ(θ+ϵ)−J(θ−ϵ), 通常我们取ϵ=10−4.
上面的例子中θ是一个实数, 在下图中, θ是一个向量, 此时是对偏导数进行数值估计.
在实际运用中, 我们使用如下代码来计算gradApprox. 然后, 我们将通过逆传播算法计算得来的DVec和gradApprox进行比较, 如果这两个值近似的话, 那么就说明我们的逆传播算法运行地没有问题.
下图描述了使用Gradient Checking时的步骤. 需要主意的是, 在得到gradApprox之后一定要即时关闭Gradient Checking, 因为它会非常大地消耗计算资源.

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

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

七. 总结

八. 应用
视频地址

以下为补充材料:
∂z∂g(z) =−(1+e−z1)2∂z∂(1+e−z)=−(1+e−z1)2e−z(−1)=(1+e−z1)(1+e−z1)(e−z)=(1+e−z1)(1+e−ze−z)=(1+e−z1)(1+e−z1+e−z−1+e−z1)=g(z)(1−g(z))