反向传导算法
From Ufldl
Line 6: | Line 6: | ||
- | 假设我们有一个固定样本集 <math>\textstyle \{ (x^{(1)}, y^{(1)}), \ldots, (x^{(m)}, y^{(m)}) \}</math>,它包含 <math>\textstyle m</math> 个样例。我们可以用批量梯度下降法求解神经网络。具体来讲,对于单个样例 <math>\textstyle (x,y)</math> ,其代价函数为: | + | 假设我们有一个固定样本集 <math>\textstyle \{ (x^{(1)}, y^{(1)}), \ldots, (x^{(m)}, y^{(m)}) \}</math>,它包含 <math>\textstyle m</math> 个样例。我们可以用批量梯度下降法求解神经网络。具体来讲,对于单个样例 <math>\textstyle (x,y)</math>,其代价函数为: |
Line 38: | Line 38: | ||
- | 以上的代价函数经常被用于分类和回归问题。在分类问题中,我们用 <math>\textstyle y = 0</math> 或 <math>\textstyle 1</math> ,来代表两种类型的标签(回忆一下,这是因为 sigmoid激活函数的值域为 <math>\textstyle [0,1]</math> ;如果我们使用双曲正切型激活函数,那么应该选用-1和+1作为标签)。对于回归问题,我们首先要变换输出值域(译者注:也就是 <math>\textstyle y</math>),以保证其范围为 <math>\textstyle [0,1]</math> (同样地,如果我们使用双曲正切型激活函数,使其值域范围为 <math>\textstyle [-1,1]</math>)。 | + | 以上的代价函数经常被用于分类和回归问题。在分类问题中,我们用 <math>\textstyle y = 0</math> 或 <math>\textstyle 1</math>,来代表两种类型的标签(回忆一下,这是因为 sigmoid激活函数的值域为 <math>\textstyle [0,1]</math> ;如果我们使用双曲正切型激活函数,那么应该选用-1和+1作为标签)。对于回归问题,我们首先要变换输出值域(译者注:也就是 <math>\textstyle y</math>),以保证其范围为 <math>\textstyle [0,1]</math> (同样地,如果我们使用双曲正切型激活函数,使其值域范围为 <math>\textstyle [-1,1]</math>)。 |
Line 68: | Line 68: | ||
</math> | </math> | ||
- | 以上两行公式稍有不同,第一行比第二行多出一项,是因为权重衰减是作用于 <math>\textstyle W</math> 而不是 <math>\textstyle b</math> 。 | + | 以上两行公式稍有不同,第一行比第二行多出一项,是因为权重衰减是作用于 <math>\textstyle W</math> 而不是 <math>\textstyle b</math>。 |
- | 反向传播算法的思路如下:给定一个样例 <math>\textstyle (x,y)</math>,我们首先进行“前向传导”运算,计算出网络中所有的激活值,包括 <math>\textstyle h_{W,b}(x)</math> 的输出值。之后,针对第 <math>\textstyle l</math> 层的每一个节点 <math>\textstyle i</math> ,我们计算出其“残差” <math>\textstyle \delta^{(l)}_i</math> ,该残差表明了该节点对最终输出值的残差产生了多少影响。对于最终的输出节点,我们可以直接算出网络产生的激活值与实际值之间的差距,我们将这个差距定义为 <math>\textstyle \delta^{(n_l)}_i</math> (这里的第 <math>\textstyle n_l</math> 层表示输出层)。对于隐藏单元我们是如何处理的呢?我们将基于节点(译者注:第 <math>\textstyle l+1</math> 层节点)残差的加权平均值计算 <math>\textstyle \delta^{(l)}_i</math>,这些节点以 <math>\textstyle a^{(l)}_i</math> 作为输入。下面将给出反向传导算法的细节: | + | 反向传播算法的思路如下:给定一个样例 <math>\textstyle (x,y)</math>,我们首先进行“前向传导”运算,计算出网络中所有的激活值,包括 <math>\textstyle h_{W,b}(x)</math> 的输出值。之后,针对第 <math>\textstyle l</math> 层的每一个节点 <math>\textstyle i</math>,我们计算出其“残差” <math>\textstyle \delta^{(l)}_i</math>,该残差表明了该节点对最终输出值的残差产生了多少影响。对于最终的输出节点,我们可以直接算出网络产生的激活值与实际值之间的差距,我们将这个差距定义为 <math>\textstyle \delta^{(n_l)}_i</math> (这里的第 <math>\textstyle n_l</math> 层表示输出层)。对于隐藏单元我们是如何处理的呢?我们将基于节点(译者注:第 <math>\textstyle l+1</math> 层节点)残差的加权平均值计算 <math>\textstyle \delta^{(l)}_i</math>,这些节点以 <math>\textstyle a^{(l)}_i</math> 作为输入。下面将给出反向传导算法的细节: |
<ol> | <ol> | ||
<li>进行前向传导计算,得到 <math>\textstyle L_2</math> 、 <math>\textstyle L_3</math> …直到输出层 <math>\textstyle L_{n_l}</math> 的激活值。 | <li>进行前向传导计算,得到 <math>\textstyle L_2</math> 、 <math>\textstyle L_3</math> …直到输出层 <math>\textstyle L_{n_l}</math> 的激活值。 | ||
- | <li>对于第 <math>\textstyle n_l</math> 层(输出层)的每个输出单元 <math>\textstyle i</math> ,我们根据以下公式计算残差: | + | <li>对于第 <math>\textstyle n_l</math> 层(输出层)的每个输出单元 <math>\textstyle i</math>,我们根据以下公式计算残差: |
:<math> | :<math> | ||
Line 117: | Line 117: | ||
</ol> | </ol> | ||
- | 最后,我们用矩阵-向量表示法重写以上算法。我们使用“<math>\textstyle \bullet</math>” 表示向量乘积运算符(在Matlab或Octave里用“<tt>.*</tt>”表示,也称作阿达马乘积),因此若 <math>\textstyle a = b \bullet c</math>,则 <math>\textstyle a_i = b_ic_i</math> 。在上一个教程中我们扩展了 <math>\textstyle f(\cdot)</math> 的定义,使其包含向量运算,这里我们对偏导数 <math>\textstyle f'(\cdot)</math> 也做了同样的处理(于是又有 <math> f'([z_1, z_2, z_3]) = | + | 最后,我们用矩阵-向量表示法重写以上算法。我们使用“<math>\textstyle \bullet</math>” 表示向量乘积运算符(在Matlab或Octave里用“<tt>.*</tt>”表示,也称作阿达马乘积),因此若 <math>\textstyle a = b \bullet c</math>,则 <math>\textstyle a_i = b_ic_i</math>。在上一个教程中我们扩展了 <math>\textstyle f(\cdot)</math> 的定义,使其包含向量运算,这里我们对偏导数 <math>\textstyle f'(\cdot)</math> 也做了同样的处理(于是又有 <math> f'([z_1, z_2, z_3]) = |
[f'(z_1), f'(z_2), f'(z_3)]</math> )。 | [f'(z_1), f'(z_2), f'(z_3)]</math> )。 | ||
Line 145: | Line 145: | ||
- | '''实现中应注意:'''在以上的第2步和第3步中,我们需要为每一个 <math>\textstyle i</math> 值计算 <math>\textstyle f'(z^{(l)}_i)</math> 。假设 <math>\textstyle f(z)</math> 是sigmoid函数,并且我们已经在神经网络的前向传导运算中得到了 <math>\textstyle a^{(l)}_i</math>。于是,使用我们早先推导出的 <math>\textstyle f'(z)</math> 的表达式,我们可以计算得到 <math>\textstyle f'(z^{(l)}_i) = a^{(l)}_i (1- a^{(l)}_i)</math> 。 | + | '''实现中应注意:'''在以上的第2步和第3步中,我们需要为每一个 <math>\textstyle i</math> 值计算 <math>\textstyle f'(z^{(l)}_i)</math>。假设 <math>\textstyle f(z)</math> 是sigmoid函数,并且我们已经在神经网络的前向传导运算中得到了 <math>\textstyle a^{(l)}_i</math>。于是,使用我们早先推导出的 <math>\textstyle f'(z)</math> 的表达式,我们可以计算得到 <math>\textstyle f'(z^{(l)}_i) = a^{(l)}_i (1- a^{(l)}_i)</math>。 |
Line 152: | Line 152: | ||
<ol> | <ol> | ||
- | <li>对于所有 <math>\textstyle l</math>,令 <math>\textstyle \Delta W^{(l)} := 0</math> , <math>\textstyle \Delta b^{(l)} := 0</math> ,(设置为全零矩阵或全零向量) | + | <li>对于所有 <math>\textstyle l</math>,令 <math>\textstyle \Delta W^{(l)} := 0</math>, <math>\textstyle \Delta b^{(l)} := 0</math>,(设置为全零矩阵或全零向量) |
<li>对于 <math>\textstyle i = 1</math> 到 <math>\textstyle m</math>, | <li>对于 <math>\textstyle i = 1</math> 到 <math>\textstyle m</math>, | ||
<ol type="a"> | <ol type="a"> | ||
- | <li>使用反向传播算法计算 <math>\textstyle \nabla_{W^{(l)}} J(W,b;x,y)</math> 和 <math>\textstyle \nabla_{b^{(l)}} J(W,b;x,y)</math> 。 | + | <li>使用反向传播算法计算 <math>\textstyle \nabla_{W^{(l)}} J(W,b;x,y)</math> 和 <math>\textstyle \nabla_{b^{(l)}} J(W,b;x,y)</math>。 |
- | <li>计算 <math>\textstyle \Delta W^{(l)} := \Delta W^{(l)} + \nabla_{W^{(l)}} J(W,b;x,y)</math> 。 | + | <li>计算 <math>\textstyle \Delta W^{(l)} := \Delta W^{(l)} + \nabla_{W^{(l)}} J(W,b;x,y)</math>。 |
- | <li>计算 <math>\textstyle \Delta b^{(l)} := \Delta b^{(l)} + \nabla_{b^{(l)}} J(W,b;x,y)</math> 。 | + | <li>计算 <math>\textstyle \Delta b^{(l)} := \Delta b^{(l)} + \nabla_{b^{(l)}} J(W,b;x,y)</math>。 |
</ol> | </ol> | ||
Line 256: | Line 256: | ||
This cost function above is often used both for classification and for regression problems. For classification, we let <math>y = 0</math> or <math>1</math> represent the two class labels (recall that the sigmoid activation function outputs values in <math>[0,1]</math>; if we were using a tanh activation function, we would instead use -1 and +1 to denote the labels). For regression problems, we first scale our outputs to ensure that they lie in the <math>[0,1]</math> range (or if we were using a tanh activation function, then the <math>[-1,1]</math> range). | This cost function above is often used both for classification and for regression problems. For classification, we let <math>y = 0</math> or <math>1</math> represent the two class labels (recall that the sigmoid activation function outputs values in <math>[0,1]</math>; if we were using a tanh activation function, we would instead use -1 and +1 to denote the labels). For regression problems, we first scale our outputs to ensure that they lie in the <math>[0,1]</math> range (or if we were using a tanh activation function, then the <math>[-1,1]</math> range). | ||
:【初译】: | :【初译】: | ||
- | 以上的代价函数经常被用于分类和回归问题。在分类问题中,我们使得<math>y = 0</math>或<math>1</math> ,来代表两种类型的标签(回忆一下,这是因为S型(sigmoid)激励函数的值域为<math>[0,1]</math>;如果我们使用双曲正切型激励函数,我们应该选用-1和+1作为标签)。对于回归问题,我们首先要对我们的输出值域进行缩放,以保证其范围为<math>[0,1]</math>(同样地,如果我们使用双曲正切型激励函数,使其值域范围为<math>[-1,1]</math>)。 | + | 以上的代价函数经常被用于分类和回归问题。在分类问题中,我们使得<math>y = 0</math>或<math>1</math>,来代表两种类型的标签(回忆一下,这是因为S型(sigmoid)激励函数的值域为<math>[0,1]</math>;如果我们使用双曲正切型激励函数,我们应该选用-1和+1作为标签)。对于回归问题,我们首先要对我们的输出值域进行缩放,以保证其范围为<math>[0,1]</math>(同样地,如果我们使用双曲正切型激励函数,使其值域范围为<math>[-1,1]</math>)。 |
:【一校】: | :【一校】: | ||
- | 以上的代价函数经常被用于分类和回归问题。在分类问题中,我们用<math>y = 0</math>或<math>1</math> ,来代表两种类型的标签(回忆一下,这是因为S型(sigmoid)激活函数的值域为<math>[0,1]</math>;如果我们使用双曲正切型激活函数,我们应该选用-1和+1作为标签)。对于回归问题,我们首先要变换我们的输出值域,以保证其范围为<math>[0,1]</math>(同样地,如果我们使用双曲正切型激励函数,使其值域范围为<math>[-1,1]</math>)。 | + | 以上的代价函数经常被用于分类和回归问题。在分类问题中,我们用<math>y = 0</math>或<math>1</math>,来代表两种类型的标签(回忆一下,这是因为S型(sigmoid)激活函数的值域为<math>[0,1]</math>;如果我们使用双曲正切型激活函数,我们应该选用-1和+1作为标签)。对于回归问题,我们首先要变换我们的输出值域,以保证其范围为<math>[0,1]</math>(同样地,如果我们使用双曲正切型激励函数,使其值域范围为<math>[-1,1]</math>)。 |
[一校注:Activation,这里是一种结果,所以用“激活”合适] | [一校注:Activation,这里是一种结果,所以用“激活”合适] | ||