自编码算法与稀疏性
From Ufldl
Line 338: | Line 338: | ||
\end{align}</math> | \end{align}</math> | ||
就可以了。 | 就可以了。 | ||
+ | |||
+ | 【原文】 | ||
+ | |||
+ | One subtlety is that you'll need to know <math>\textstyle \hat\rho_i</math> to compute this term. Thus, you'll need | ||
+ | to compute a forward pass on all the training examples first to compute the average | ||
+ | activations on the training set, before computing backpropagation on any example. If your | ||
+ | training set is small enough to fit comfortably in computer memory (this will be the case for the programming | ||
+ | assignment), you can compute forward passes on all your examples and keep the resulting activations | ||
+ | in memory and compute the <math>\textstyle \hat\rho_i</math>s. Then you can use your precomputed activations to | ||
+ | perform backpropagation on all your examples. If your data is too large to fit in memory, you | ||
+ | may have to scan through your examples computing a forward pass on each to accumulate (sum up) the | ||
+ | activations and compute <math>\textstyle \hat\rho_i</math> (discarding the result of each forward pass after you | ||
+ | have taken its activations <math>\textstyle a^{(2)}_i</math> into account for computing <math>\textstyle \hat\rho_i</math>). Then after | ||
+ | having computed <math>\textstyle \hat\rho_i</math>, you'd have to redo the forward pass for each example so that you | ||
+ | can do backpropagation on that example. In this latter case, you would end up computing a forward | ||
+ | pass twice on each example in your training set, making it computationally less efficient. | ||
+ | |||
+ | |||
+ | The full derivation showing that the algorithm above results in gradient descent is beyond the scope | ||
+ | of these notes. But if you implement the autoencoder using backpropagation modified this way, | ||
+ | you will be performing gradient descent exactly on the objective | ||
+ | <math>\textstyle J_{\rm sparse}(W,b)</math>. Using the derivative checking method, you will be able to verify | ||
+ | this for yourself as well. | ||
+ | |||
+ | 【初译】 | ||
+ | |||
+ | 有一个需要注意的地方就是我们需要知道 <math>\textstyle \hat\rho_i</math> 来计算这一项更新。所以在计算任何神经元的后向传播之前,你需要对所有的训练样本计算一遍前向传播,从而获取平均激活度。如果你的训练样本可以小到被整个存到内存之中(对于编程作业来说,通常如此),你可以方便地在你所有的样本上计算前向传播并将得到的激活度存入内存并且计算平均激活度。然后你就可以使用事先计算好的激活度来对所有的训练样本进行后向传播的计算。如果你的数据量太大,无法全部存入内存,你就可以扫过你的训练样本并计算一次前向传播,然后将获得的结果累积起来并计算平均激活度 <math>\textstyle \hat\rho_i</math> (当你将某一个前向传播的结果激活度 <math>\textstyle a^{(2)}_i</math> 用于计算平均激活度 <math>\textstyle \hat\rho_i</math> 之后就可以将其删除)。然后当你完成平均激活度 <math>\textstyle \hat\rho_i</math> 的计算之后,你需要重新对每一个训练样本做一次前向传播从而可以对其进行后向传播的计算。对于后一种情况,你对每一个训练样本需要计算两次前向传播,所以在计算上的效率会稍低一些。 | ||
+ | |||
+ | 如何从上面算法得出梯度下降表达式的具体推导过程不再本教程的范围之内。不过如果你想要使用经过以上修改的后向传播来实现自编码神经网络,那么你就需要做以 <math>\textstyle J_{\rm sparse}(W,b)</math> 为目标函数的梯度下降。使用梯度验证方法,你可以自己确认自己的推导是否正确。 | ||
+ | |||
+ | 【一审】 | ||
+ | |||
+ | 其中细微的变化就是你要先知道 <math>\textstyle \hat\rho_i</math> 的值再来计算这个等式。因此,在对样本进行反向传播运算之前,你就要对所有的样本先进行前向传播计算,从而计算得到样本的平均激活值。如果你的样本很小从而可以存储在计算机内存中(编程中的内存分配通常如此),你就可以对所有的样本进行前向传播运算,并把所有激活值放在内存中并计算得出所有的 。然后,你就可以用你预先计算好的激活值来对所有的样本进行反向传播运算。如果你的样本数据太过庞大而不能全部放入内存,那么你就必须从头到尾对你的样本数据逐个进行向前传播运算,逐项累积激活值(相加)再计算 <math>\textstyle \hat\rho_i</math> (在将激活值 <math>\textstyle a^{(2)}_i</math> 计算进 <math>\textstyle \hat\rho_i</math> 之后,即将这个激活值删除)。在计算出 <math>\textstyle \hat\rho_i</math> 之后,你必须对每个样本再次进行前向运算,这样你才可以对这个样本作反向传播运算。对于后一种情况,你对每一个样本需要计算两次前向传播,所以在计算上的效率会稍低一些。 | ||
+ | |||
+ | 以上整个求导等式可以看出,本算法的梯度下降算法超出了本教程的范围,但是,如果你使用按以上方式调整过的反向传播算法运算自编码算法,你就需要以 <math>\textstyle J_{\rm sparse}(W,b)</math> 为目标函数执行梯度下降算法。使用梯度检验法,你可以自己来验证梯度下降算法是否正确。 | ||
+ | |||
+ | 【二审】 | ||
+ | |||
+ | 有一个需要注意的地方就是我们需要知道 <math>\textstyle \hat\rho_i</math> 来计算这一项更新。所以在计算任何神经元的后向传播之前,你需要对所有的训练样本计算一遍前向传播,从而获取平均激活度。如果你的训练样本可以小到被整个存到内存之中(对于编程作业来说,通常如此),你可以方便地在你所有的样本上计算前向传播并将得到的激活度存入内存并且计算平均激活度 。然后你就可以使用事先计算好的激活度来对所有的训练样本进行后向传播的计算。如果你的数据量太大,无法全部存入内存,你就可以扫过你的训练样本并计算一次前向传播,然后将获得的结果累积起来并计算平均激活度 <math>\textstyle \hat\rho_i</math> (当某一个前向传播的结果中的激活度 <math>\textstyle a^{(2)}_i</math> 被用于计算平均激活度 <math>\textstyle \hat\rho_i</math> 之后就可以将此结果删除)。然后当你完成平均激活度 <math>\textstyle \hat\rho_i</math> 的计算之后,你需要重新对每一个训练样本做一次前向传播从而可以对其进行后向传播的计算。对于后一种情况,你对每一个训练样本需要计算两次前向传播,所以在计算上的效率会稍低一些。 | ||
+ | |||
+ | 证明上面算法能达到梯度下降效果的完整推导过程不再本教程的范围之内。不过如果你想要使用经过以上修改的后向传播来实现自编码神经网络,那么你就会对目标函数 <math>\textstyle J_{\rm sparse}(W,b)</math> 做梯度下降。使用导数验证方法,你可以自己确认此说法。 |