本章主要讲解如何求解神经网络的权重(参数)。
Cost Function
主要讲解了神经网络的代价函数(分类问题中的)。
Neural Network(Classification)
引入一些标记方法方便后续讨论:
- 假设神经网络有\(m\)个训练样本,每个训练样本包含一组输入特征\(x\)和一组输出信号\(y\);
- \(L\)表示神经网络层数;
- \(s_l\)表示第\(l\)层的神经元个数(不包含偏置单元),E.g. \(s_L\)代表最后一层神经元个数。
将神经网络的分类问题分为以下两种情况:
- 二元分类:输出\(y\)是一个标量,\(y=1 \space or \space 0\);
- 多元分类:输出\(y\)是一个K(\(K \ge 3\))维向量。
Cost function
参考逻辑回归的代价函数,给出分类问题的神经网络代价函数:
同样的,这里的正则项也不对偏置项进行求解。
我们对每一行特征都预测出\(K\)个不同结果,然后从这\(K\)个预测中选出概率最高的一个,作为预测值,然后和真实值\(y\)进行比较。
Backpropagation Algorithm
上节课介绍了神经网络的代价函数,因此这节课主要介绍如何通过反向传播算法最小化代价函数,也就是求解代价函数的参数。
Gradient computation
和之前一样,如果我们想要求解使得代价函数\(J(\Theta)\)最小对应的参数\(\Theta\),那么我们就需要代码计算\(J(\Theta)\)和\(\frac{\partial}{\partial \Theta_{ij}^{(l)}}J(\Theta)\)。
假设我们的训练集只有一个数据集\((x,y)\),神经网络模型有4层。\(a^{(i)}\)代表第\(i\)层的预测值,E.g 第1层不做任何预测,因此就是原始数据,即\(a^{(1)}=x\)。从左往右一层一层依次计算,这就是前向传播算法(Forward propagation)。
Backpropagation algorithm
计算误差的顺序刚好相反,我们需要从右往左推,也就是反向传播算法(Backpropagation algorithm)。
用\(\delta_j^{(l)}\)表示第\(l\)层神经网络,第\(j\)个节点的误差,E.g. 第4层的误差\(\delta_j^{(4)}\)等于预测值\(a_j^{(4)}\)于实际值\(y_j\)之间的误差,然后再以此计算第3层的误差。第一层是输入变量,不存在误差。
有了所有误差的表达式后,我们就可以计算代价函数的偏导数了,假设\(\lambda=0\),即忽略正则化处理时有:\(\frac{\partial}{\partial\Theta_{ij}^{(l)}}\delta_i^{l+1}\)。
式子中上下标含义:
- \(l\)代表目前计算的是第\(l\)层;
- \(j\)代表目前计算层中激活单元的下标,也将是下一层的第\(j\)个输入变量的下标;
- \(i\)代表下一层中误差单元的下标。
如果我们考虑正则化处理,并且用矩阵的形式表示,那么误差表示为\(\Delta_{ij}^{(l)}\),代价函数的偏导数表示为\(D_{ij}^{(l)}\)。
Backpropagation Intuition
本节课主要介绍了反向传播算法的具体步骤,更直观地感受反向传播算法。
Forward Propagation
先讲解一下前向传播算法。
假设我们在第1层的输入为\((x^{(i)},y^{(i)})\),那么第2层的第1个节点输入则为\(z_i^{(2)}\),再经过sigmoid函数,输出预测值\(a_1^{(2)}\),其他节点以此类推。
E.g. 以第3层第1个节点\(z_1^{(3)}\)为例,分别用上一层的输出值乘以权重,计算公式为:\(z^{(3)}_1=\Theta^{(2)}_{10} \times 1 + \Theta^{(2)}_{11} \times a^{(2)}_1 + \Theta^{(2)}_{12} \times a^{(2)}_2\)。
What is backpropagation doing?
我们会发现反向传播算和前向传播算法其实原理上是一样的。
E.g. 以第2层第2个节点的误差\(\delta^{(2)}_2\)为例,分别用后一层的误差值乘以权重,计算公式为:\(\delta^{(2)}_2= \Theta^{(2)}_{12} \times \delta^{(3)}_1 + \Theta^{(2)}_{22} \times \delta^{(3)}_2\).
Implementation Note: Unrolling Parameters
讲解了在Octave中如何把矩阵转换成向量的操作,跳过。
Gradient Checking
当我们对一个较为复杂的模型(E.g. 神经网络)使用梯度下降算法时,可能会存在一些不易察觉的错误,为了检查我们的梯度下降算法是否正确工作,我们可以采用梯度检验(Gradient checking)进行验证。这种方法的思想是通过估算梯度值来检验我们计算的导数值是否正确。
Numerical estimation of gradients
为了方便讲解,我们先假设参数\(\theta\)属于实数,参数\(\theta\)此时的梯度为蓝色切线的斜率,为了估算该斜率。我们在参数\(\theta\)的左右分别选取两个点\((\theta-\epsilon,\theta+\epsilon)\),我们通过计算这两个点在曲线上连线的斜率(红色斜线),来估算梯度值。即
\[\frac{d}{d\theta}J(\theta) \approx \frac{J(\theta+\epsilon)-J(\theta-\epsilon)}{2\epsilon} \]注意:这里的\(\epsilon\)是一个很小的值,E.g. \(\epsilon=10^{-4}\).
伪代码表示:
gradApprox = (J(theta + EPSILON) – J(theta – EPSILON)) / (2*EPSILON)
Parameter vector
当参数\(\theta=[\theta_1, \theta_2, \cdots, \theta_n]\)是一个向量时,我们就需要对参数内的所有元素进行梯度检验。
伪代码表示:
for i = 1:n,
thetaPlus = theta;
thetaPlus(i) = thetaPlus(i) + EPSILON;
thetaMinus = theta;
thetaMinus(i) = thetaMinus(i) – EPSILON;
gradApprox(i) = (J(thetaPlus) – J(thetaMinus)) / (2*EPSILON);
end;
最后,检查估算出来的梯度值gradApprox
是否和反向传播算法计算出来的梯度值DVec
大约相等,如果大约相等说明计算正确,否则错误。
Implementation Note:
- 采用反向传播算法计算
DVec
; - 采用数值梯度检查计算
gradApprox
; - 确保\(DVec \approx gradApprox\);
- 关闭梯度检查算法,使用反向传播算法进行学习。
Important:确保在训练模型之前关闭梯度检查代码,因为梯度检查计算起来是非常慢的,所以如果在训练模型时没有关闭梯度检查,就会导致梯度下降算法非常缓慢。
Random Initialization
本节课主要介绍如何初始化参数\(\theta\)的值。
对于梯度下降或者高级的优化算法,我们都需要初始化参数\(\theta\)的值。在逻辑回归和线性回归中,我们一般都把\(\theta\)初始化为0,那么在神经网络中能否另\(initialTheta = zeros(n,1)\)?
Zero initialization
假如初始化参数为0,那么所有参数是一样的,我们会得到\(a^{(2)}_1 = a^{(2)}_2\),同样地,\(\delta^{(2)}_1 = \delta^{(2)}_2\),最终会导致梯度下降更新后的参数也是相等的,相当于我们得到了一个只有一个参数的神经网络模型,这显然是不行的。
初始化所有参数都为一个相等的非0值也是一样的结果。
Random initialization: Symmetry breaking
所以为了破坏这种对称性,我们通常采用随机化初始值的方式。初始化每一个参数\(\Theta^{(l)}_{ij}\)为\([-\epsilon, \epsilon]\)之间的随机值。
E.g. Theta1 = rand(10,11)*(2*INIT_EPSILON) - INIT_EPSILON;
初始化一个尺寸为\(10 \times 11\)的参数矩阵。
Putting It Together
前面讲解了神经网络各个方面的相关知识,本节课主要将它们组合起来,做一个汇总,总结一下使用神经网络的步骤。
训练一个神经网络模型的第一步就是选择网络结构,即决定选择多少层以及每层分别有多少个神经单元。
- 第一层输入层的单元数即我们训练集的特征数量;
- 最后一层输出层的单元数是我们训练集的结果的类的数量,E.g. 4分类问题即单元数为4;
- 隐藏层默认选择一层,如果有多层隐藏层,一般每个隐藏层的单元数相同,通常单元数越多越好。
训练神经网络的步骤:
- 随机初始化权重
- 利用正向传播算法计算每个\(x^{(i)}\)的假设函数\(h_\Theta(x^{(i)})\)
- 计算代价函数\(J(\Theta)\)
- 利用反向传播算法计算偏导数\(\frac{\partial}{\partial \Theta^{(l)}_{jk}}J(\Theta)\)
- 利用梯度检查估算\(J(\Theta)\)的梯度和反向传播算法计算的偏导数\(\frac{\partial}{\partial \Theta^{(l)}_{jk}}J(\Theta)\)进行对比(然后就可以关闭梯度检查代码)
- 利用梯度下降或者高级的优化算法来最小化代价函数\(J(\Theta)\)
Backpropagation Example: Autonomous Driving (optional)
主要简单介绍了神经网络的其中一个应用——自动驾驶。