神经网络向量化

From Ufldl

Jump to: navigation, search
 
Line 1: Line 1:
在本节,我们将引入神经网络的向量化版本。在前面关于[[神经网络]]介绍的章节中,我们已经给出了一个部分向量化的实现,它在一次输入一个训练样本时是非常有效率的。下边我们看看如何实现同时处理多个训练样本的算法。具体来讲,我们将把正向传播、反向传播这两个步骤以及稀疏特征集学习扩展为多训练样本版本。
在本节,我们将引入神经网络的向量化版本。在前面关于[[神经网络]]介绍的章节中,我们已经给出了一个部分向量化的实现,它在一次输入一个训练样本时是非常有效率的。下边我们看看如何实现同时处理多个训练样本的算法。具体来讲,我们将把正向传播、反向传播这两个步骤以及稀疏特征集学习扩展为多训练样本版本。
 +
==正向传播==
==正向传播==
考虑一个三层网络(一个输入层、一个隐含层、以及一个输出层),并且假定x是包含一个单一训练样本<math>x^{(i)} \in \Re^{n}</math> 的列向量。则向量化的正向传播步骤如下:
考虑一个三层网络(一个输入层、一个隐含层、以及一个输出层),并且假定x是包含一个单一训练样本<math>x^{(i)} \in \Re^{n}</math> 的列向量。则向量化的正向传播步骤如下:
 +
:<math>\begin{align}
:<math>\begin{align}
Line 12: Line 14:
\end{align}</math>
\end{align}</math>
-
这对于单一训练样本而言是非常有效的一种实现,但是当我们需要处理<tt>m</tt>个训练样本时,则需要把如上步骤包装进一个<tt>for</tt>循环中。
+
 
 +
这对于单一训练样本而言是非常有效的一种实现,但是当我们需要处理<tt>m</tt>个训练样本时,则需要把如上步骤放入一个<tt>for</tt>循环中。
 +
 
更具体点来说,参照逻辑回归向量化的例子,我们用Matlab/Octave风格变量<tt>x</tt>表示包含输入训练样本的矩阵,<tt>x(:,i)</tt>代表第<math>\textstyle i</math>个训练样本。则x正向传播步骤可如下实现:
更具体点来说,参照逻辑回归向量化的例子,我们用Matlab/Octave风格变量<tt>x</tt>表示包含输入训练样本的矩阵,<tt>x(:,i)</tt>代表第<math>\textstyle i</math>个训练样本。则x正向传播步骤可如下实现:
-
<syntaxhighlight>  
+
 
 +
<syntaxhighlight>
% 非向量化实现
% 非向量化实现
for i=1:m,  
for i=1:m,  
Line 26: Line 31:
</syntaxhighlight>  
</syntaxhighlight>  
-
这个<tt>for</tt>循环能否去掉呢?对于很多算法而言,我们使用向量来表示计算过程中的中间结果。例如在前面的非向量化实现(9-2)中,<tt>z2</tt>,<tt>a2</tt>,<tt>z3</tt>都是列向量,分别用来计算隐层和输出层的激励结果。为了充分利用并行化和高效矩阵运算的优势,我们希望算法能同时处理多个训练样本。让我们先暂时忽略前面公式中的<tt>b1</tt>和<tt>b2</tt>(把它们设置为0),那么可以实现如下:
 
-
<syntaxhighlight>  
+
这个<tt>for</tt>循环能否去掉呢?对于很多算法而言,我们使用向量来表示计算过程中的中间结果。例如在前面的非向量化实现中,<tt>z2</tt>,<tt>a2</tt>,<tt>z3</tt>都是列向量,分别用来计算隐层和输出层的激励结果。为了充分利用并行化和高效矩阵运算的优势,我们希望算法能同时处理多个训练样本。让我们先暂时忽略前面公式中的<tt>b1</tt>和<tt>b2</tt>(把它们设置为0),那么可以实现如下:
 +
 
 +
 
 +
<syntaxhighlight>
% 向量化实现 (忽略 b1, b2)
% 向量化实现 (忽略 b1, b2)
z2 = W1 * x;
z2 = W1 * x;
Line 36: Line 43:
</syntaxhighlight>  
</syntaxhighlight>  
-
在这个实现中,<tt>z2</tt>,<tt>a2</tt>,<tt>z3</tt>都是矩阵,每个训练样本对应矩阵的一列。在对多个训练样本实现向量化时常用的设计模式是,虽然前面每个样本对应一个列向量(比如<tt>z2</tt>),但我们可把这些列向量堆叠成一个矩阵以充分享受矩阵运算带来的好处。这样,在这个例子中,<tt>a2</tt>就成了一个<math>s_2</math>X<math>m</math>的矩阵(<math>s_2</math>是网络第二层中的神经元数,<math>m</math>是训练样本个数)。矩阵<tt>a2</tt>的物理含义是,当第<math>i</math>个训练样本<tt>x(:i)</tt>输入到网络中时,它的第<math>i</math>列就表示这个输入信号对隐神经元 (网络第二层)的激励结果。
 
-
在上面的实现中,我们假定激活函数 <tt>f(z)</tt>接受矩阵形式的输入<tt>z</tt>,并对输入矩阵按列分别施以激活函数。需要注意的是,你在实现<tt>f(z)</tt>的时候要尽量多用Matlab/Octave的矩阵操作,并尽量避免使用for循环。假定激活函数采用Sigmoid函数,则实现代码如下所示:
+
在这个实现中,<tt>z2</tt>,<tt>a2</tt>,<tt>z3</tt>都是矩阵,每个训练样本对应矩阵的一列。在对多个训练样本实现向量化时常用的设计模式是,虽然前面每个样本对应一个列向量(比如<tt>z2</tt>),但我们可把这些列向量堆叠成一个矩阵以充分享受矩阵运算带来的好处。这样,在这个例子中,<tt>a2</tt>就成了一个<math>s_2</math> X <math>m</math>的矩阵(<math>s_2</math>是网络第二层中的神经元数,<math>m</math>是训练样本个数)。矩阵<tt>a2</tt>的物理含义是,当第<math>i</math>个训练样本<tt>x(:i)</tt>输入到网络中时,它的第<math>i</math>列就表示这个输入信号对隐神经元 (网络第二层)的激励结果。
 +
 
 +
 
 +
在上面的实现中,我们假定激活函数<tt>f(z)</tt>接受矩阵形式的输入<tt>z</tt>,并对输入矩阵按列分别施以激活函数。需要注意的是,你在实现<tt>f(z)</tt>的时候要尽量多用Matlab/Octave的矩阵操作,并尽量避免使用for循环。假定激活函数采用Sigmoid函数,则实现代码如下所示:
 +
 
<syntaxhighlight>
<syntaxhighlight>
Line 50: Line 60:
end;
end;
end
end
 +
% 高效的、向量化激活函数实现
% 高效的、向量化激活函数实现
function output = vectorized_f(z)
function output = vectorized_f(z)
-
output = 1./(1+exp(-z));    % "./" is Matlab/Octave's element-wise division operator.
+
output = 1./(1+exp(-z));    % "./" 在Matlab或Octave中表示对矩阵的每个元素分别进行除法操作
end
end
</syntaxhighlight>
</syntaxhighlight>
-
最后,我们上面的正向传播向量化实现中忽略了<tt>b1</tt>和<tt>b2</tt>,现在要把他们包含进来,我们需要用到Matlab/Octave的内建函数<tt>repmat</tt>:
+
 
 +
最后,我们上面的正向传播向量化实现中忽略了<tt>b1</tt>和<tt>b2</tt>,现在要把他们包含进来,为此我们需要用到Matlab/Octave的内建函数<tt>repmat</tt>:
 +
 
<syntaxhighlight>
<syntaxhighlight>
-
% 正向传导的向量化实现
+
% 正向传播的向量化实现
z2 = W1 * x + repmat(b1,1,m);
z2 = W1 * x + repmat(b1,1,m);
a2 = f(z2);
a2 = f(z2);
Line 66: Line 79:
h = f(z3)
h = f(z3)
</syntaxhighlight>
</syntaxhighlight>
 +
<tt>repmat(b1,1,m)</tt>的运算效果是,它把列向量<tt>b1</tt>拷贝<math>m</math>份,然后堆叠成如下矩阵:
<tt>repmat(b1,1,m)</tt>的运算效果是,它把列向量<tt>b1</tt>拷贝<math>m</math>份,然后堆叠成如下矩阵:
 +
::<math>
::<math>
Line 77: Line 92:
</math>
</math>
-
这就构成一个<math>s_2</math> X <math>m</math>的矩阵。它和<tt>W1 * x</tt>相加,就等于是把<tt>W1 * x</tt>矩阵(译者注:这里<tt>x</tt>是训练矩阵而非向量, 所以<tt>W1 * x</tt>代表两个矩阵相乘,结果还是一个矩阵)的每一列加上<tt>b1</tt>。如果不熟悉的话,可以参考Matlab/Octave的帮助文档获取更多信息(输入 “<tt>help repmat</tt>”)。<tt>rampat</tt>作为Matlab/Octave的内建函数,运行起来是相当高效的,远远快过我们自己用<tt>for</tt>循环实现的效果。
 
-
现在我们来描述反向传播向量化的思路。在阅读这一节之前,强烈建议各位仔细阅读前面介绍的正向传播的例子代码,确保你已经完全理解。下边我们只会给出反向传播向量化实现的大致纲要,而由你来完成具体细节的推导(见 [[Exercise:Vectorization]])。
+
这就构成一个<math>s_2</math> X <math>m</math>的矩阵。它和<tt>W1 * x</tt>相加,就等于是把<tt>W1 * x</tt>矩阵(译者注:这里<tt>x</tt>是训练矩阵而非向量, 所以<tt>W1 * x</tt>代表两个矩阵相乘,结果还是一个矩阵)的每一列加上<tt>b1</tt>。如果不熟悉的话,可以参考Matlab/Octave的帮助文档获取更多信息(输入“<tt>help repmat</tt>”)。<tt>rampat</tt>作为Matlab/Octave的内建函数,运行起来是相当高效的,远远快过我们自己用<tt>for</tt>循环实现的效果。
-
这是监督学习,所以我们会有一个含<math>m</math>个带标号训练样本的训练集合<math>\{ (x^{(1)}, y^{(1)}), \ldots, (x^{(m)}, y^{(m)}) \}</math>。
 
-
(对于自编码网络,我们只需令<math>y^{(i)} = x^{(i)}</math>即可,  但这里考虑的是更一般的情况。)
 
 +
==反向传播==
-
Suppose we have <math>s_3</math> dimensional outputs, so that our target labels are <math>y^{(i)} \in \Re^{s_3}</math>.  In our Matlab/Octave datastructure, we will stack these in columns to form a Matlab/Octave variable <tt>y</tt>, so that the <math>i</math>-th column <tt>y(:,i)</tt> is <math>y^{(i)}</math>.
 
-
假定每个样本的输出有<math>s_3</math>维,因而每个样本的类别标号向量就记为<math>y^{(i)} \in \Re^{s_3}</math> 。在我们的Matlab/Octave数据结构实现中,把这些输出按列合在一起形成一个Matlab/Octave风格变量<tt>y</tt>,其中第<tt>i</tt>列<tt>y(:,i)</tt>就是y(i) 。
+
现在我们来描述反向传播向量化的思路。在阅读这一节之前,强烈建议各位仔细阅读前面介绍的正向传播的例子代码,确保你已经完全理解。下边我们只会给出反向传播向量化实现的大致纲要,而由你来完成具体细节的推导(见[[Exercise:Vectorization|向量化练习]])。
-
We now want to compute the gradient terms
 
-
<math>\nabla_{W^{(l)}} J(W,b)</math> and <math>\nabla_{b^{(l)}} J(W,b)</math>.  Consider the first of
 
-
these terms.  Following our earlier description of the [[Backpropagation Algorithm]], we had that for a single training example <math>(x,y)</math>, we can compute the derivatives as
 
-
'''初译:'''
+
对于监督学习,我们有一个包含<math>m</math>个带类别标号样本的训练集<math>\{ (x^{(1)}, y^{(1)}), \ldots, (x^{(m)}, y^{(m)}) \}</math>。
-
现在我们需要计算梯度项<math>\nabla_{W^{(l)}} J(W,b)</math>和<math>\nabla_{b^{(l)}} J(W,b)</math>。对于第一个梯度,按照我们过去在[[反向传导算法]]中所描述的,对于一个单一的训练样本<math>(x,y)</math>,我们可以计算导数:
+
(对于自编码网络,我们只需令<math>y^{(i)} = x^{(i)}</math>即可,  但这里考虑的是更一般的情况。)
 +
 
 +
 
 +
假定网络的输出有<math>s_3</math>维,因而每个样本的类别标号向量就记为<math>y^{(i)} \in \Re^{s_3}</math>。在我们的Matlab/Octave数据结构实现中,把这些输出按列合在一起形成一个Matlab/Octave风格变量<tt>y</tt>,其中第<tt>i</tt>列<tt>y(:,i)</tt>就是<math>y^{(i)}</math>。
 +
 
 +
 
 +
现在我们要计算梯度项<math>\nabla_{W^{(l)}} J(W,b)</math>和<math>\nabla_{b^{(l)}} J(W,b)</math>。对于梯度中的第一项,就像过去在反向传播算法中所描述的那样,对于每个训练样本<math>(x,y)</math>,我们可以这样来计算:
-
'''一审:'''
 
-
现在我们要计算梯度项<math>\nabla_{W^{(l)}} J(W,b)</math>和<math>\nabla_{b^{(l)}} J(W,b)</math>。对于头一个梯度项,就像过去在反向传导算法中所描述的那样,对于每个训练样本<math>(x,y)</math>,我们可以这样来计算:
 
::<math>
::<math>
Line 109: Line 122:
-
Here, <math>\bullet</math> denotes element-wise product.  For simplicity, our description here will ignore the derivatives with respect to <math>b^{(l)}</math>, though your implementation of backpropagation will have to compute those derivatives too.
+
在这里<math>\bullet</math>表示对两个向量按对应元素相乘的运算(译者注:其结果还是一个向量)。为了描述简单起见,我们这里暂时忽略对参数<math>b^{(l)}</math>的求导,不过在你真正实现反向传播时,还是需要计算关于它们的导数的。
-
'''初译:'''
 
-
在这里,<math>\bullet</math> 表示元素级别的积。为了简化,我们这里的描述将要忽略b(l) . 不过在你真正实现反向传导时,你仍旧需要计算它们的导数。
 
-
<math>b^{(l)}</math>
 
-
'''一审:'''
+
假定我们已经实现了向量化的正向传播方法,如前面那样计算了矩阵形式的变量<tt>z2</tt>, <tt>a2</tt>, <tt>z3</tt>和<tt>h</tt>,那么反向传播的非向量化版本可如下实现:
-
在这里 <math>\bullet</math>代表对两个向量按对应元素相乘的运算(其结果还是一个向量—译注)。为了描述简单起见,我们这里暂时忽略对参数<math>b^{(l)}</math>.的求导, 不过在你真正实现反向传导时,还是需要计算关于它们的导数。
+
-
Suppose we have already implemented the vectorized forward propagation method, so that the matrix-valued <tt>z2</tt>, <tt>a2</tt>,  <tt>z3</tt> and <tt>h</tt> are computed as described above. We can then implement an ''unvectorized'' version of backpropagation as follows:
 
-
 
-
'''初译:'''
 
-
假定我们已经实现了正向传导方法的向量化,<tt>z2</tt>, <tt>a2</tt>,  <tt>z3</tt>和<tt>h</tt>的矩阵值就如我们前面描述的那样去计算。于是我们可以实现一个反向传导的非向量化版本如下:
 
-
 
-
'''一审:'''
 
-
假定我们已经实现了正向传导步骤的向量化,如前面9-5那样去计算了矩阵值变量<tt>z2</tt>, <tt>a2</tt>,  <tt>z3</tt>和<tt>h</tt>的值,那么反向传导的非向量化版本实现就如下所示:
 
<syntaxhighlight>
<syntaxhighlight>
Line 138: Line 140:
</syntaxhighlight>  
</syntaxhighlight>  
-
This implementation has a <tt>for</tt> loop.  We would like to come up with an implementation that simultaneously performs backpropagation on all the examples, and eliminates this <tt>for</tt> loop.
 
-
'''初译:'''
+
在这个实现中,有一个<tt>for</tt>循环。而我们想要一个能同时处理所有样本、且去除这个<tt>for</tt>循环的向量化版本。
-
在这个实现中有一个<tt>for</tt>循环。我们需要一个能够在所有样本上并发执行的实现从而去掉<tt>for</tt>循环。
+
-
'''一审:'''
 
-
在这个实现中,有一个<tt>for</tt>循环,而我们想要一个能同时处理所有样本的向量化实现版本,要去除这个<tt>for</tt>循环。
 
-
To do so, we will replace the vectors <tt>delta3</tt> and <tt>delta2</tt> with matrices, where one column of each matrix corresponds to each training example.  We will also implement a function <tt>fprime(z)</tt> that takes as input a matrix <tt>z</tt>, and applies <math>f'(\cdot)</math> element-wise.  Each of the four lines of Matlab in the <tt>for</tt> loop above can then be vectorized and replaced with a single line of Matlab code (without a surrounding <tt>for</tt> loop).
+
为做到这一点,我们先把向量<tt>delta3</tt><tt>delta2</tt>替换为矩阵,其中每列对应一个训练样本。我们还要实现一个函数<tt>fprime(z)</tt>,该函数接受矩阵形式的输入<tt>z</tt>,并且对矩阵的按元素分别执行<math>f'(\cdot)</math>。这样,上面<tt>for</tt>循环中的4行Matlab代码中每行都可单独向量化,以一行新的(向量化的)Matlab代码替换它(不再需要外层的<tt>for</tt>循环)。
-
'''初译:'''
 
-
为了实现它,我们将要把向量<tt>delta3</tt>和<tt>delta2</tt>替换为矩阵,矩阵中的每一列代表一个训练样本。我们将要实现一个方法<tt>fprime(z)</tt>,这个方法把矩阵<tt>z</tt>作为输入,并且对矩阵元素执行 。在上边的实现中的<tt>for</tt>循环中的4行中每一行都可以被向量化并且替换为1行Matlab代码(不需要被一个<tt>for</tt>循环所包围)
 
-
'''一审:'''
+
在[[Exercise:Vectorization|向量化练习]]中,我们要求你自己去推导出这个算法的向量化版本。如果你已经能从上面的描述中了解如何去做,那么我们强烈建议你去实践一下。虽然我们已经为你准备了[[Backpropagation vectorization hints|反向传播的向量化实现提示]],但还是鼓励你在不看提示的情况下自己去推导一下。
-
为做到这一点,我们先把向量<tt>delta3</tt>和<tt>delta2</tt>替换为矩阵,其中每列代表一个训练样本。我们还要实现一个函数<tt>fprime(z)</tt>,该函数接受矩阵形式的输入<tt>z</tt>,并且按其矩阵元素分别执行 。这样,上面<tt>for</tt>循环中的4行Matlab代码中每行都可单独向量化,而分别替之以一行新的(向量化的)Matlab代码(不再需要外层的<tt>for</tt>循环).
+
-
In the [[Exercise:Vectorization|Vectorization exercise]], we ask you to derive the vectorized version of this algorithm by yourself.  If you are able to do it from this description, we strongly encourage you to do so.  Here also are some [[Backpropagation vectorization hints]]; however, we encourage you to try to carry out the vectorization yourself without looking at the hints.
 
-
'''初译:'''
+
==稀疏自编码网络==
-
在[[向量化练习]]中,我们要求你自己去推导出这个算法的向量化版本。如果你能够按照描述去实现,我们强烈你去亲手实现它。我们给出了[[反向传导向量化提示]],但是我们鼓励你自己去导出向量化而不是求助于提示。
+
-
'''一审:'''
 
-
在[[向量化练习]]中,我们要求你自己去导出这个算法的向量化版本。如果你已经能从上面的描述中了解如何去做,那么我们强烈建议你去亲手实现它。虽然我们已经为你准备了[[反向传导的向量化实现提示]],但还是鼓励你自己去导出它,而不是求助于提示。
 
-
 
-
== Sparse autoencoder ==
 
-
 
-
The [[Autoencoders_and_Sparsity|sparse autoencoder]] neural network has an additional sparsity penalty that constrains neurons' average firing rate to be close to some target activation <math>\rho</math>.  When performing backpropagation on a single training example, we had taken into the account the sparsity penalty by computing the following:
 
-
 
-
==稀疏自编码网络==
 
-
'''初译:'''
+
[[自编码算法与稀疏性|稀疏自编码]]网络中包含一个额外的稀疏惩罚项,目的是限制神经元的平均激活率,使其接近某个(预设的)目标激活率<math>\rho</math>。其实在对单个训练样本上执行反向传播时,我们已经考虑了如何计算这个稀疏惩罚项,如下所示:
-
[[稀疏自动编码]]神经网络有一个额外的稀疏惩罚去限制神经元的平均激活率使它接近目标激活<math>\rho</math>。 当在一个单一训练样本上执行反向传导时,我们在下边的算法中考虑了稀疏惩罚:
+
-
'''一审:'''
 
-
[[稀疏自编码]]网络中包含一个额外的稀疏惩罚项,目的是限制神经元的平均激活率,使其接近某个(预设的)目标激活率<math>\rho</math>。 其实在对单个训练样本上执行反向传导时,我们已经考虑了如何计算这个稀疏惩罚项,如下所示:
 
:<math>\begin{align}
:<math>\begin{align}
Line 180: Line 162:
\end{align}</math>
\end{align}</math>
-
In the ''unvectorized'' case, this was computed as:
 
-
'''初译:'''
 
在非向量化的实现中,计算代码如下:
在非向量化的实现中,计算代码如下:
-
'''一审:'''
 
-
在非向量化的实现中,计算代码如下:
 
<syntaxhighlight>
<syntaxhighlight>
-
% Sparsity Penalty Delta 稀疏惩罚Delta
+
% 稀疏惩罚Delta
sparsity_delta = - rho ./ rho_hat + (1 - rho) ./ (1 - rho_hat);
sparsity_delta = - rho ./ rho_hat + (1 - rho) ./ (1 - rho_hat);
for i=1:m,
for i=1:m,
Line 198: Line 176:
</syntaxhighlight>
</syntaxhighlight>
-
The code above still had a <tt>for</tt> loop over the training set, and <tt>delta2</tt> was a column vector.
 
-
'''初译:'''
+
但在上面的代码中,仍旧含有一个需要在整个训练集上运行的<tt>for</tt>循环,这里<tt>delta2</tt>是一个列向量。
-
在上边的代码中仍旧包含对训练集的<tt>for</tt>循环,以及一个列向量<tt>delta2</tt>
+
 
 +
 
 +
作为对照,回想一下在向量化的情况下,<tt>delta2</tt>现在应该是一个有m列的矩阵,分别对应着<math>m</math>个训练样本。还要注意,稀疏惩罚项<tt>sparsity_delta</tt>对所有的训练样本一视同仁。这意味着要向量化实现上面的计算,只需在构造<tt>delta2</tt>时,往矩阵的每一列上分别加上相同的值即可。因此,要向量化上面的代码,我们只需简单的用<tt>repmat</tt>命令把<tt>sparsity_delta</tt>加到<tt>delta2</tt>的每一列上即可(译者注:这里原文描述得不是很清楚,看似应加到上面代码中<tt>delta2</tt>行等号右边第一项,即<tt>W2'*delta3</tt>上)。
 +
 
 +
 
 +
 
 +
==中英文对照==
 +
 
 +
:向量化         vectorization
 +
:正向传播 forward propagation
 +
:反向传播 backpropagation
 +
:训练样本 training examples
 +
:激活函数 activation function
 +
:稀疏自编码网络 sparse autoencoder
 +
:稀疏惩罚 sparsity penalty
 +
:平均激活率    average firing rate
 +
 
 +
==中文译者==
 +
 
 +
阎志涛(zhitao.yan@gmail.com), 谭晓阳(x.tan@nuaa.edu.cn), 邓亚峰(dengyafeng@gmail.com)
 +
 
-
'''一审:'''
 
-
但在上边的代码中,仍旧含有一个需要在整个训练集上运行的<tt>for</tt>循环,这里<tt>delta2</tt>是一个列向量。
 
-
In contrast, recall that in the vectorized case, <tt>delta2</tt> is now a matrix with <math>m</math> columns corresponding to the <math>m</math> training examples.  Now, notice that the <tt>sparsity_delta</tt> term is the same regardless of what training example we are processing.  This suggests that vectorizing the computation above can be done by simply adding the same value to each column when constructing the <tt>delta2</tt> matrix. Thus, to vectorize the above computation, we can simply add <tt>sparsity_delta</tt> (e.g., using <tt>repmat</tt>) to each column of <tt>delta2</tt>.
+
{{矢量化编程实现}}
-
'''初译:'''做为对照,回想一下我们在向量化的示例中,对于<tt>m</tt>个训练样本,<tt>delta2</tt>变成了一个有<math>m</math>列的矩阵。在这里,<tt>Sparsity_delta</tt>项和我们正在处理的所有训练样本是一样的。这意味着上面的向量化计算可以通过对<tt>delta2</tt>矩阵的每一列添加一个相同的值来实现。因此对上面的向量化计算,我们可以简单的把<tt>Sparsity_delta</tt>增加到<tt>delta2</tt>的每一列上(使用<tt>repmat</tt>)。
 
-
'''一审:'''
+
{{Languages|Neural_Network_Vectorization|English}}
-
作为对照,回想一下在向量化的情况下, <tt>delta2</tt>现在应该是一个有m列的矩阵,分别对应着<math>m</math>个训练样本。还要注意, <tt>Sparsity_delta</tt>稀疏惩罚项对所有的训练样本一视同仁。这意味着要向量化实现上面的计算,只需在构造<tt>delta2</tt>时,往矩阵的每一列上分别加上相同的值即可。因此,要向量化上面的代码,我们只需简单的用<tt>repmat</tt>命令把<tt>sparsity_delta</tt>加到<tt>delta2</tt>的每一列上即可(这里原文描述得不是很清楚, 看似应加到上面代码中<tt>delta2</tt>行等号右边第一项,即<tt>W2'*delta3</tt>上—译者注)。
+

Latest revision as of 05:02, 8 April 2013

Personal tools