天天看点

UFLDL练习(Sparse Autoencoder)

最近开始学习UFLDL,一个deep learning的教程

这个练习的地址:http://deeplearning.stanford.edu/wiki/index.php/Exercise:Sparse_Autoencoder

Sparse Autoencoder是用神经网络进行feature learning的一个算法,详细的就见教程,我只是贴贴代码

从早上十点多一直debug到下午四点多,问题多多,究其原因还是对算法理解不够深刻,虽然以前还写过一个nn

所以收获还是有的,理解算法嘛

最主要的部分就是sparseAutoencoderCost.m了

[python]  view plain  copy

  1. mm=size(data,2);  
  2. z2=(W1*data)+repmat(b1,1,mm);  
  3. a2=sigmoid(z2);  
  4. z3=(W2*a2)+repmat(b2,1,mm);  
  5. a3=sigmoid(z3);  
  6. rho=sum(a2,2)./mm;  
  7. cost=1/2/mm*sum(sum((a3-data).^2))+lambda/2*(sum(sum(W1.^2))+sum(sum(W2.^2)))+beta*sum(kldiverge(rho,sparsityParam));  
  8. for i=1:mm  
  9.  x=data(:,i);  
  10.  delta3=-(x-a3(:,i)).*sigmoidGradient(z3(:,i));  
  11.  delta2=(W2'*delta3+beta*(-sparsityParam./rho+(1-sparsityParam)./(1-rho))).*sigmoidGradient(z2(:,i));  
  12.  W1grad=W1grad+delta2*x';  
  13.  W2grad=W2grad+delta3*a2(:,i)';  
  14.  b1grad=b1grad+delta2;  
  15.  b2grad=b2grad+delta3;  
  16. end  
  17. b1grad=b1grad/mm;  
  18. b2grad=b2grad/mm;  
  19. W1grad=W1grad/mm+lambda*W1;  
  20. W2grad=W2grad/mm+lambda*W2;  

下面是完全vectorization后的代码:

[python]  view plain  copy

  1. mm=size(data,2);  
  2. z2=(W1*data)+repmat(b1,1,mm);  
  3. a2=sigmoid(z2);  
  4. z3=(W2*a2)+repmat(b2,1,mm);  
  5. a3=sigmoid(z3);  
  6. rho=sum(a2,2)./mm;  
  7. cost=1/2/mm*sum(sum((a3-data).^2))+lambda/2*(sum(sum(W1.^2))+sum(sum(W2.^2)))+beta*sum(kldiverge(rho,sparsityParam));  
  8. sparityy=(-sparsityParam./rho+(1-sparsityParam)./(1-rho));  
  9.  x=data();  
  10.  delta3=-(x-a3).*sigmoidGradient(z3);  
  11.  delta2=(W2'*delta3+repmat(beta*sparityy,1,mm)).*a2.*(1-a2);  
  12.  W1grad=W1grad+delta2*x';  
  13.  W2grad=W2grad+delta3*a2';  
  14.  b1grad=b1grad+sum(delta2,2);  
  15.  b2grad=b2grad+sum(delta3,2);  
  16. b1grad=b1grad/mm;  
  17. b2grad=b2grad/mm;  
  18. W1grad=W1grad/mm+lambda*W1;  
  19. W2grad=W2grad/mm+lambda*W2;  

出错这么久的主要原因就是我按照文档给的步骤计算:

UFLDL练习(Sparse Autoencoder)

但实际上这个步骤计算的是J(W,b;x,y),是针对某个训练数据来的,即使你把所有的累积起来,并没有满足要求

因为真正的梯度计算式子是:

UFLDL练习(Sparse Autoencoder)

我们算的不过是求和符号的那一坨,还需要加入外面的部分

看起来不止我一个人犯了这样的错误,因为微博上一人帖的代码也有问题

训练结果:

UFLDL练习(Sparse Autoencoder)

嗯嗯,就这样了,话说matlab 2012挺好用的

继续阅读