UFLDL作業記錄

UFLDL-Sparse Autoencoder

稀疏自編碼的作業,在這裏

1. 實現sampleIMAGES

IMAGES.mat是一個512x512x10的10張已將白化過的圖片。
sampleIMAGES,故名思議,就是採樣IMAGES。

imagesc(IMAGES(:,:,4)), colormap gray

可以看到圖像的灰度的樣子,比如第四張圖片:

pic_4

我們想要採的樣本是10000個8x8的樣本,因爲sampleIMAGES裏已經這麼初始化了。

patchsize = 8;  % we'll use 8x8 patches 
numpatches = 10000; 
patches = zeros(patchsize*patchsize, numpatches);

patches被初始化程成了一個64x10000的矩陣。


Idea很簡單:
隨機從10張圖片裏選一張,隨機從x座標裏選8個像素,隨機從y座標裏選8個像素。

其實我們只要定下10000個隨機的點,作爲8x8的樣本的左上角就可以了。
設,左上角的點的座標是(a,b,c),顯然(a+8-1,b+8-1,c)要不大於(512,512,10)

先選x座標的值:

  a = randi(512-8+1,1,10000);

在選y座標的值:

  b = randi(512-8+1,1,10000);

最後選圖片到底是第幾張:

  c = randi(10,1,10000);

於是,10000張8x8的圖像,其實就是:

d = IMAGES(a:a+8-1,b:b+8-1,c)

所以patches就是:

 for i = 1:10000
     pathces(:,i) = reshape(d(:,:,i),1,64);
 end

綜合起來,就是:

tic
image_size = size(IMAGES);
a = randi(image_size(1) - patchsize + 1, 1, numpatches);
b = randi(image_size(2) - patchsize + 1, 1, numpatches);
c = randi(image_size(3), 1, numpatches);
d = IMAGES(a:a+8-1, b:b+8-1, c)
for num = 1 : numpatches
   patches(:,num)=reshape(d(:,:,num),1,patchsize*patchsize);
end
toc

2. 構建Sparse autoencoder objective

可以看到,train.m裏,已經設定了hiddenSize = 25,所以這個網絡結構其實是:64x25x64,隱層有25個單元。

先按正常的神經網絡的訓練順序來

2.1 前向傳播

Θ 已經在initializeParameters裏定義好了,所以 W~1~(25x64),W~2~(64x25)和b~1~(25x1),b~2~(64x1) 已經有了,可以直接開始算前向傳播:

  B_1 = repmat(b_1,1,10000);%截距
  Z_2 = (W_1*patches) + B_1;%輸入
  A_2 = sigmoid(Z_2);%隱層輸出
  B_2 = repmat(b_2,1,10000);%截距
  Z_3 = (W_2*A_2) + B_2;%輸入
  A_3 = sigmoid(Z_3);%結果

2.2 稀疏性保證

接着要計算ρ^ ,號稱是隱層的平均輸出,文中給的公式是:
ρ^j=1mmi=1[a(2)j(x(i))]
它說,這裏取的平均,是在測試集上的平均(averaged over the training set),我覺得很奇怪。

我們知道A_2是一個25x10000的矩陣,那這個m,到底是25還是10000?我怎麼感覺都是25,不是說是隱層的平均輸出麼?

我們想讓ρ^ 儘量的小,最好是某個挺小的值ρ ,這個ρ 也叫稀疏性參數

爲了完成上述要求,我們要把ρ^ρ 的相對熵算一下:
KL(ρ||ρ^j)=ρlogρρ^j+(1ρ)log1ρ1ρ^j
把下面這個東西放進代價函數裏,來實現稀疏性的控制:
s2j=1KL(ρ||ρ^j)
文中說,說這裏的S~2~是隱層節點數,也就是25。這裏的ρ 又是個標量,顯然上面的那個ρ^ 裏的m是10000了。

那麼,代碼這麼寫:

  mean_A_2 = sum(A_2,2)./10000;
  rho = sparsityParam
  KL = sum(rho.*log(rho./mean_A_2)+(1-rho).*log((1-v)/(1.-mean_A_2));

2.3 代價函數

代價函數J:
Jsparse(W,b)=J(W,b)+βs2j=1KL(ρ||ρ^j)
其中,J(W,b) ,按照反向傳播來算是:

J(W,b)=[1mmi=1(12hW,b(x(i))y(i)2)]+λ2nl1l=1sli=1sl+1j=1(W(l)ji)2

所以,

  J=(1/2*10000)*sum(sum((A_3-patches).^2))+lambda/2*(sum(sum(W_1.^2))+sum(sum(W_2.^2)))+beta*KL;

2.4梯度下降

  daoshu_Z_3 = sigmoid(A_3).*(1-sigmoid(A_3);
  delta_3 = -(patches-A_3).*daoshu_Z_3;

對於delta_2,文中說:
δ(2)i=((s2j=1W(2)jiδ(3)j)+β(ρρ^i+1ρ1ρ^i))f(z(2)i)
這麼寫比較省事。所以:

  sparity_penalty = (-rho./mean_A_2+(1-rho)./(1-mean_A_2));
  daoshu_Z_2 = sigmoid(A_2).*(1-sigmoid(A_2);
  delta_2=(W_2'*delta_3+repmat(beta*sparity_penalty,1,mm)).*daoshu_Z_2;

則,W偏導,b偏導爲:
W(l)J(W,b;x,y)=δ(l+1)(a(l))T

b(l)J(W,b;x,y)=δ(l+1)

所以W,和b的偏導代碼是:

 W1_pd = delta_2 * pathces';
 W2_pd = delta_3 * A_2';
 b1_pd = sum(delta_2,2);
 b2_pd = sum(delta_3,2);

W,b的梯度:

ΔW(l):=ΔW(l)+W(l)J(W,b;x,y)

Δb(l):=Δb(l)+b(l)J(W,b;x,y)

 W1grad = W1grad + W1_pd;
 W2grad = W2grad + W2_pd;
 b1grad = b1grad + b1_pd;
 b2grad = b2grad + b2_pd;

最終更新權重:

  b1grad=b1grad/10000;
  b2grad=b2grad/10000;
  W1grad=W1grad/10000+lambda*W_1;
  W2grad=W2grad/10000+lambda*W_2;

至此,代價函數就寫完了。

3.檢驗梯度

最後,還要保證梯度算的沒錯。。。。
文中提到了這樣的檢測方法:
g(θ)J(θ+EPSILON)J(θEPSILON)2×EPSILON.
那麼,我們就要對代價函數做上述的檢測:

eps = 1e-4;  
m = size(theta,1);  
for i=1:m  
    theta_p = theta;  
    theta_p(i,:) = theta_p(i,:) + eps;  
    theta_m = theta;  
    theta_m(i,:) = theta_m(i,:) - eps;  
    numgrad(i,:) = (J(theta_p) - J(theta_m))/(eps*2.0);  
end 

其實有向量化的方法:

eps = 1e-4;
m = size(theta,1);
E = eye(m);
for i = 1:m
    delta = E(:,i)*eps;
    numgrad(i) = (J(theta+delta)-J(theta-delta))/(eps*2.0);
end

m一大,eye就超出了matlab的限制了,所以,我用的上一個。
這一步句,巨慢無比,因爲要進行mx2次的J函數的運算。。。。

4.結果

result

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章