1 代价函数和逆向回归
1.1Cost Function
Let’s first define a few variables that we will need to use:
- L = total number of layers in the network
- sl = number of units (not counting bias unit) in layer l
- K = number of output units/classes
Recall that in neural networks, we may have many output nodes. We denote hΘ(x)k as being a hypothesis that results in the kth output. Our cost function for neural networks is going to be a generalization of the one we used for logistic regression. Recall that the cost function for regularized logistic regression was:
For neural networks, it is going to be slightly more complicated:
We have added a few nested summations to account for our multiple output nodes. In the first part of the equation, before the square brackets, we have an additional nested summation that loops through the number of output nodes.
In the regularization part, after the square brackets, we must account for multiple theta matrices. The number of columns in our current theta matrix is equal to the number of nodes in our current layer (including the bias unit). The number of rows in our current theta matrix is equal to the number of nodes in the next layer (excluding the bias unit). As before with logistic regression, we square every term.
Note:
- 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
1.2 反向传播 (B-P)
1.2.1 正向传播
首先回忆上节课中的代价函数
利用上面的公式,我们需要先通过正向传播的方式计算每一层的
让我们粗看一下,使用这样一个训练样本来计算的顺序。
首先我们用向前传播方法来计算一下在给定输入的时候,假设函数的输出结果:
a(1)就是第一层的激励值,也就是输入层
这里记得添加偏差项
a(3)0 这里注意下,这里的z(2) 相当于上面一篇帖子里面图示里面neta2 的命名形式
这里记得添加偏差项
a(3)0 ,这里注意下,这里的z(3) 相当于上面一篇帖子里面图示里面,neta3 的命名形式
通过上面的步骤计算,我们就可以得出假设函数的输出结果了:
1.2.2 反向传播
为了计算导数项,我们将采用一种叫做反向传播(Backpropagation)的算法。
反向传播算法从直观上说就是对每一个节点求下面这一个误差项,这里先引入变量
我们还记得我们使用
更正式一点的说法是δ项实际上是关于
当然cost就是:
这里和我上面一篇的一个推导有关系,就相当于把这个把这个参数对误差造成的影响传递回来,直观的看就是 误差对当前参数
θ 偏导数 = 误差对参数下一层输出的偏导 * 下一层输出对当前参数的偏导,从而用于梯度下降中。
具体本例如下:
反向传播法这个名字源于我们从输出层开始计算δ项,然后我们返回到上一层计算第三隐藏层的δδ项,接着我们再往前一步来计算
所以说我们是类似于把输出层的误差反向传播给了第3层,然后再传到第二层。这就是反向传播的意思。
最后,这个推导过程是出奇的复杂(博主现在也还有点不太明白,ORZ),但是如果你按照这样几个步骤来计算,就有可能简单直接地完成复杂的数学证明。 (相关证明在下面3小结中的拓展部分)
整合一下,求解过程伪代码如下:
这里的
D(i)i,j 就是∂J(Θ)∂Θ(l)i,j ,也就是我们要求的偏导数
而Δ(l)i,j 则是一个累加和,用来对测试集中的每一个组测试用例累加,从而获得最终的偏导数
详细步骤参考链接
1.3 反向传播算法的直观介绍
结合上面一节的说法,反向传播就是在通过如下方式计算
计算过程如下:
2 BP算法练习
2.1 将参数从矩阵展开成向量
在这一节中,我想快速地向你介绍一个细节的实现过程,怎样把你的参数从矩阵展开成向量,以便我们在高级最优化步骤中的使用需要。
function [jVal, gradient] = costFunction(theta)
...
optTheta = fminunc(@costFunction, initialTheta, options)
具体来讲,对代价函数costFunction(theta)传入参数theta,函数返回值是代价函数jVal以及导数值gradient,然后你可以将返回值传递给高级最优化算法fminunc。
因为参数是向量,所以需要将这些参数矩阵转化为向量的形式以及对这些向量再返回值的时候在打包成矩阵。
如果你想讲这些矩阵向量化,那么你要做的是取出你的
thetaVec = [Theta1(:);Theta2(:);Theta3(:)];
同样的,下面这段代码将取出DD矩阵的所有元素,然后展开成一个长向量DVec:
DVec = [D1(:);D2(:);D3(:)];
最后,如果你想要从向量表达式返回到矩阵表达式的话,你要做的就是使用reshape函数,传入向量的区间以及矩阵的行数和列数,即可得到对应的矩阵:
Theta1 = reshape(thetaVec(1:110),10,11);
Theta2 = reshape(thetaVec(111:220),10,11);
Theta3 = reshape(thetaVec(221:231),10,11);
最后总结下:
使用矩阵表达式的好处是:当你的参数以矩阵的形式存储时,你在进行正向传播和反向传播时,你会觉得更加方便。当你将参数存储为矩阵时,一个大好处是充分利用了向量化的实现过程。
相反地,向量表达式的优点是如果你有像thetaVec或者DVec这样的矩阵,当你使用一些高级的优化算法时,这些算法通常要求你所有的参数都展开成一个长向量的形式。
2.2 梯度检验(Gradient Checking)
在之前的视频中,我们讨论了如何使用向前传播和反向传播计算神经网络中的导数,但反向传播作为一个有很多细节的算法,在实现的时候会有点复杂,而且有一个不好的方面是在实现反向传播时,会遇到很多细小的错误。所以如果你把它和梯度下降算法或者其他优化算法一起运行时,可能看起来它运行正常,并且你的代价函数J(Θ)最后可能在每次梯度下降法迭代时,都会减小,即使在实现反向传播时有一些小错误,可能也会检查不出来。
所以它看起来是J(Θ)在减小,但是可能你最后得到的神经网络误差比没有错误的要高,而且你很可能就不知道你的这些结果是这些小错误导致的。那你应该怎么办呢?
有一个想法叫做梯度检验(Gradient Checking)可以解决基本所有的问题。我现在每次实现神经网络的反向传播或者类似的梯度下降算法或者其他比较复杂的模型,我都会使用梯度检验,如果你这么做,它会帮你确定并且能很确信你实现的向前传播和反向传播或者其他的什么算法是100%正确的。
通过如下的原理来实现:
具体实现如下:
2.3 随机初始化Θ
相应代码:
If the dimensions of Theta1 is 10x11, Theta2 is 10x11 and Theta3 is 1x11.
Theta1 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta2 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta3 = rand(1,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
2.4 神经网络总体回顾:所有算法合体吧!
2.4.1 选择适合的神经网络
选择神经网络时注意:
- 在多类别分类问题中,若yy的取值范围是在1,2,3,..,101,2,3,..,10之间,那么你就有10个可能的分类,别忘了把你的y重新写成向量的形式
y=⎡⎣⎢⎢⎢⎢⎢⎢100…0⎤⎦⎥⎥⎥⎥⎥⎥ - 对于隐藏层单元的个数,以及隐藏层的数目,我们有一个默认的规则,那就是只使用单个隐藏层,所以第一种类型的神经网络架构是最常见的
- 如果你使用超过一层的隐藏层的话,同样我们也有一个默认规则,那就是每一个隐藏层通常都应该拥有相同的单元数。所以后面的两种神经网络结构的隐藏层都拥有相同的单元数:
- 通常情况下隐藏单元越多越好,不过我们需要注意的是,如果有大量的隐藏单元,计算量一般会比较大。并且,一般来说,每个隐藏层所包含的单元数量还应该和输入xx的维度相匹配,也要和特征的数目相匹配。可能隐藏单元的数目和输入特征的数量相同,或者是它的二倍或者三倍、四倍。因此,隐藏单元的数目需要和其他参数相匹配。
2.4.2 训练神经网络的步骤
一共有6步:
- Randomly initialize the weights
- Implement forward propagation to get hΘ(x(i)) for any x(i)
- Implement the cost function
- Implement backpropagation to compute partial derivatives
- Use gradient checking to confirm that your backpropagation works. Then disable gradient checking.
- Use gradient descent or a built-in optimization function to minimize the cost function with the weights in theta.
(>>>>母语^.^)
- 构建一个神经网络并且随机初始化权值(Randomly initialize Weight)
- 执行向前传播算法,也就是对于神经网络的任意一个输入
x(i) 计算出对应的hΘ(x(i)) - 通过代码计算出代价函数J(Θ)
- 执行反向传播算法(Backprop)来算出这些偏导数:
∂∂Θ(l)jkJ(Θ) 使用梯度检查来校验结果。用梯度检查来比较这些已经用反向传播算法得到的偏导数值
∂∂Θ(l)jkJ(Θ) 与用数值方法得到的估计值进行比较,来检查,确保这两种方法得到值是基本相近的。使用一个最优化算法(比如说梯度下降算法或者其他更加高级的优化方法,比如说BFGS算法,共轭梯度法,或者其他一些已经内置到fminunc函数中的方法),将所有这些优化方法和反向传播算法相结合,这样我们就能计算出这些偏导数项的值
∂∂Θ(l)jkJ(Θ)
3. 总结和扩展
在NeuralNetwork中,J并不一定是凸型函数,也就是说梯度下降并不能得到全局最小值(可能只能达到局部最小值),但是通常来说,这种算法还是一种表现不错的算法,无伤大雅。
δ 误差数学原来推导
这里我在我的博客里给出了具体例子,更加通俗易懂,会发现和公式是一样的,建议直接用例子推一推