本筆記主要記錄學習《深度學習》的總結體會。如有理解不到位的地方,歡迎大家指出,我會努力改正。
在學習《深度學習》時,我主要是通過Andrew Ng教授在http://deeplearning.stanford.edu/wiki/index.php/UFLDL_Tutorial上提供的UFLDL(Unsupervised Feature Learning and Deep Learning)教程,本文在寫的過程中,多有借鑒這個網站提供的資料。
稀疏自編碼器(Sparse Autoencoder)可以自動從無標注數據中學習特征,可以給出比原始數據更好的特征描述。在實際運用時可以用稀疏編碼器發現的特征取代原始數據,這樣往往能帶來更好的結果。本文將給出稀疏自編碼器的算法描述,並演示說明稀疏編碼器自動提取邊緣特征。
轉載請注明出處:http://blog.csdn.net/u010278305。
稀疏自編碼器是具有一層隱含層的神經網絡,其思路是讓輸出等於輸入,(即,其中表示訓練樣本集合),讓編碼器自己發現輸入數據中隱含的特征,自編碼神經網咯的結果如下圖:
自編碼神經網絡嘗試學習一個 的函數。換句話說,它嘗試逼近一個恆等函數,從而使得輸出 接近於輸入 。這樣往往可以發現輸入數據的一些有趣特征,最終我們會用隱藏層的神經元代替原始數據。當隱藏神經元數目少於輸入的數目時,自編碼神經網絡可以達到數據壓縮的效果(因為最終我們可以用隱藏神經元替代原始輸入,輸入層的n個輸入轉換為隱藏層的m個神經元,其中n>m,之后隱藏層的m個神經元又轉換為輸出層的n個輸出,其輸出等於輸入);當隱藏神經元數目較多時,我們仍然可以對隱藏層的神經元加入稀疏性限制來發現輸入數據的有趣結構。
稀疏性可以被簡單地解釋如下。如果當神經元的輸出接近於1的時候我們認為它被激活,而輸出接近於0的時候認為它被抑制,那么使得神經元大部分的時間都是被抑制的限制則被稱作稀疏性限制。這里我們假設的神經元的激活函數是sigmoid函數(如果你使用tanh作為激活函數的話,當神經元輸出為-1的時候,我們認為神經元是被抑制的)。
我們使用 來表示在給定輸入為 情況下,自編碼神經網絡隱藏神經元 的激活度。並將隱藏神經元 的平均活躍度(在訓練集上取平均)記為:
在此,稀疏性限制可以理解為使隱藏神經元的平均激活度特別小,可以表示為 其中 是稀疏性參數, 通常是一個接近於0的較小的值(比如 ),換句話說,我們想要讓隱藏神經元 的平均活躍度接近0.05。為了滿足這一條件,隱藏神經元的活躍度必須接近於0。為了實現這一限制,我們需要在原始的神經網絡優化目標函數中加入稀疏性限制這一項,作為一項額外的懲罰因子,我們可以選擇具有如下形式的懲罰因子:
其中, 是隱藏層中隱藏神經元的數量,而索引 依次代表隱藏層中的每一個神經元。該表達式也可以描述為 相對熵,記為
其中, 是一個以 為均值和一個以 為均值的兩個伯努利隨機變量之間的相對熵。相對熵是一種標准的用來測量兩個分布之間差異的方法。 這一懲罰因子有如下性質,當 時 , ,並且隨着 與 之間的差異增大而單調遞增。舉例來說,在下圖中,我們設定 並且畫出了相對熵值 隨着 變化的變化。
我們可以看出,相對熵在 時達到它的最小值0,而當 靠近0或者1的時候,相對熵則變得非常大(其實是趨向於 )。所以,最小化這一懲罰因子具有使得 靠近 的效果。現在,我們的總體代價函數可以表示為
其中, 如之前所定義,而 控制稀疏性懲罰因子的權重。 項則也(間接地)取決於 ,因為它是隱藏神經元 的平均激活度,而隱藏層神經元的激活度取決於 。為此,我們需要相應更改第二層的導數,具體來說,就是將原來的導數
換成如下的形式
就可以了。
更新這個導數時,我們需要知道這一項,因此在計算神經元的后向傳播之前,需要對所有的訓練樣本計算一遍前向傳播,從而獲得平均激活度。
按照 http://deeplearning.stanford.edu/wiki/index.php/Exercise:Sparse_Autoencoder 給出的教程,我們可以對稀疏自編碼器進行編寫實現。
下面,給出稀疏自編碼器代價函數及其導數的matlab代碼實現:
function [cost,grad] = sparseAutoencoderCost(theta, visibleSize, hiddenSize, ...
lambda, sparsityParam, beta, data)
% visibleSize: the number of input units (probably 64)
% hiddenSize: the number of hidden units (probably 25)
% lambda: weight decay parameter
% sparsityParam: The desired average activation for the hidden units (denoted in the lecture
% notes by the greek alphabet rho, which looks like a lower-case "p").
% beta: weight of sparsity penalty term
% data: Our 64x10000 matrix containing the training data. So, data(:,i) is the i-th training example.
% The input theta is a vector (because minFunc expects the parameters to be a vector).
% We first convert theta to the (W1, W2, b1, b2) matrix/vector format, so that this
% follows the notation convention of the lecture notes.
W1 = reshape(theta(1:hiddenSize*visibleSize), hiddenSize, visibleSize);
W2 = reshape(theta(hiddenSize*visibleSize+1:2*hiddenSize*visibleSize), visibleSize, hiddenSize);
b1 = theta(2*hiddenSize*visibleSize+1:2*hiddenSize*visibleSize+hiddenSize);
b2 = theta(2*hiddenSize*visibleSize+hiddenSize+1:end);
% Cost and gradient variables (your code needs to compute these values).
% Here, we initialize them to zeros.
cost = 0;
W1grad = zeros(size(W1));
W2grad = zeros(size(W2));
b1grad = zeros(size(b1));
b2grad = zeros(size(b2));
%% ---------- YOUR CODE HERE --------------------------------------
% Instructions: Compute the cost/optimization objective J_sparse(W,b) for the Sparse Autoencoder,
% and the corresponding gradients W1grad, W2grad, b1grad, b2grad.
%
% W1grad, W2grad, b1grad and b2grad should be computed using backpropagation.
% Note that W1grad has the same dimensions as W1, b1grad has the same dimensions
% as b1, etc. Your code should set W1grad to be the partial derivative of J_sparse(W,b) with
% respect to W1. I.e., W1grad(i,j) should be the partial derivative of J_sparse(W,b)
% with respect to the input parameter W1(i,j). Thus, W1grad should be equal to the term
% [(1/m) \Delta W^{(1)} + \lambda W^{(1)}] in the last block of pseudo-code in Section 2.2
% of the lecture notes (and similarly for W2grad, b1grad, b2grad).
%
% Stated differently, if we were using batch gradient descent to optimize the parameters,
% the gradient descent update to W1 would be W1 := W1 - alpha * W1grad, and similarly for W2, b1, b2.
%
m=size(data,2);
x=data;
a1=x;
z2=W1*a1+repmat(b1,1,m);
a2=sigmoid(z2);
z3=W2*a2+repmat(b2,1,m);
a3=sigmoid(z3);
h=a3;
y=x;
squared_error=0.5*sum((h-y).^2,1);
rho=1/m*sum(a2,2);
sparsity_penalty= beta*sum(sparsityParam.*log(sparsityParam./rho)+(1-sparsityParam).*log((1-sparsityParam)./(1-rho)));
cost=1/m*sum(squared_error)+lambda/2*(sum(sum(W1.^2))+sum(sum(W2.^2))) + sparsity_penalty;
grad_z3=a3.*(1-a3);
delta_3=-(y-a3).*grad_z3;
grad_z2=a2.*(1-a2);
delta_2=(W2'*delta_3+repmat(beta*(-sparsityParam./rho+(1-sparsityParam)./(1-rho)),1,m)).*grad_z2;
Delta_W2=delta_3*a2';
Delta_b2=sum(delta_3,2);
Delta_W1=delta_2*a1';
Delta_b1=sum(delta_2,2);
W1grad=1/m*Delta_W1+lambda*W1;
W2grad=1/m*Delta_W2+lambda*W2;
b1grad=1/m*Delta_b1;
b2grad=1/m*Delta_b2;
%-------------------------------------------------------------------
% After computing the cost and gradient, we will convert the gradients back
% to a vector format (suitable for minFunc). Specifically, we will unroll
% your gradient matrices into a vector.
grad = [W1grad(:) ; W2grad(:) ; b1grad(:) ; b2grad(:)];
end
%-------------------------------------------------------------------
% Here's an implementation of the sigmoid function, which you may find useful
% in your computation of the costs and the gradients. This inputs a (row or
% column) vector (say (z1, z2, z3)) and returns (f(z1), f(z2), f(z3)).
function sigm = sigmoid(x)
sigm = 1 ./ (1 + exp(-x));
end
在編碼器的輸入為圖片時,我們對輸入層到隱藏層的權重進行可視化,得到如下圖所示結果:
可以發現,稀疏自編碼器可以自動提取輸入圖片的邊緣特征。
稀疏自編碼器完整的MATLAB實現代碼已經上傳,地址http://download.csdn.net/detail/u010278305/8901005
轉載請注明出處:http://blog.csdn.net/u010278305
————————————————
版權聲明:本文為CSDN博主「chenynCV」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u010278305/article/details/46881443
本筆記主要記錄學習《深度學習》的總結體會。如有理解不到位的地方,歡迎大家指出,我會努力改正。 在學習《深度學習》時,我主要是通過Andrew Ng教授在http://deeplearning.stanford.edu/wiki/index.php/UFLDL_Tutorial上提供的UFLDL(Unsupervised Feature Learning and Deep Learning)教程,本文在寫的過程中,多有借鑒這個網站提供的資料。
稀疏自編碼器(Sparse Autoencoder)可以自動從無標注數據中學習特征,可以給出比原始數據更好的特征描述。在實際運用時可以用稀疏編碼器發現的特征取代原始數據,這樣往往能帶來更好的結果。本文將給出稀疏自編碼器的算法描述,並演示說明稀疏編碼器自動提取邊緣特征。 轉載請注明出處:http://blog.csdn.net/u010278305。
稀疏自編碼器是具有一層隱含層的神經網絡,其思路是讓輸出等於輸入,(即,其中表示訓練樣本集合),讓編碼器自己發現輸入數據中隱含的特征,自編碼神經網咯的結果如下圖:
自編碼神經網絡嘗試學習一個 的函數。換句話說,它嘗試逼近一個恆等函數,從而使得輸出 接近於輸入 。這樣往往可以發現輸入數據的一些有趣特征,最終我們會用隱藏層的神經元代替原始數據。當隱藏神經元數目少於輸入的數目時,自編碼神經網絡可以達到數據壓縮的效果(因為最終我們可以用隱藏神經元替代原始輸入,輸入層的n個輸入轉換為隱藏層的m個神經元,其中n>m,之后隱藏層的m個神經元又轉換為輸出層的n個輸出,其輸出等於輸入);當隱藏神經元數目較多時,我們仍然可以對隱藏層的神經元加入稀疏性限制來發現輸入數據的有趣結構。 稀疏性可以被簡單地解釋如下。如果當神經元的輸出接近於1的時候我們認為它被激活,而輸出接近於0的時候認為它被抑制,那么使得神經元大部分的時間都是被抑制的限制則被稱作稀疏性限制。這里我們假設的神經元的激活函數是sigmoid函數(如果你使用tanh作為激活函數的話,當神經元輸出為-1的時候,我們認為神經元是被抑制的)。
我們使用 來表示在給定輸入為 情況下,自編碼神經網絡隱藏神經元 的激活度。並將隱藏神經元 的平均活躍度(在訓練集上取平均)記為:
在此,稀疏性限制可以理解為使隱藏神經元的平均激活度特別小,可以表示為 其中 是稀疏性參數, 通常是一個接近於0的較小的值(比如 ),換句話說,我們想要讓隱藏神經元 的平均活躍度接近0.05。為了滿足這一條件,隱藏神經元的活躍度必須接近於0。為了實現這一限制,我們需要在原始的神經網絡優化目標函數中加入稀疏性限制這一項,作為一項額外的懲罰因子,我們可以選擇具有如下形式的懲罰因子:
其中, 是隱藏層中隱藏神經元的數量,而索引 依次代表隱藏層中的每一個神經元。該表達式也可以描述為 相對熵,記為
其中, 是一個以 為均值和一個以 為均值的兩個伯努利隨機變量之間的相對熵。相對熵是一種標准的用來測量兩個分布之間差異的方法。 這一懲罰因子有如下性質,當 時 , ,並且隨着 與 之間的差異增大而單調遞增。舉例來說,在下圖中,我們設定 並且畫出了相對熵值 隨着 變化的變化。
我們可以看出,相對熵在 時達到它的最小值0,而當 靠近0或者1的時候,相對熵則變得非常大(其實是趨向於 )。所以,最小化這一懲罰因子具有使得 靠近 的效果。現在,我們的總體代價函數可以表示為
其中, 如之前所定義,而 控制稀疏性懲罰因子的權重。 項則也(間接地)取決於 ,因為它是隱藏神經元 的平均激活度,而隱藏層神經元的激活度取決於 。為此,我們需要相應更改第二層的導數,具體來說,就是將原來的導數
換成如下的形式
就可以了。
更新這個導數時,我們需要知道這一項,因此在計算神經元的后向傳播之前,需要對所有的訓練樣本計算一遍前向傳播,從而獲得平均激活度。
按照 http://deeplearning.stanford.edu/wiki/index.php/Exercise:Sparse_Autoencoder 給出的教程,我們可以對稀疏自編碼器進行編寫實現。
下面,給出稀疏自編碼器代價函數及其導數的matlab代碼實現:
function [cost,grad] = sparseAutoencoderCost(theta, visibleSize, hiddenSize, ... lambda, sparsityParam, beta, data)
% visibleSize: the number of input units (probably 64) % hiddenSize: the number of hidden units (probably 25) % lambda: weight decay parameter% sparsityParam: The desired average activation for the hidden units (denoted in the lecture% notes by the greek alphabet rho, which looks like a lower-case "p").% beta: weight of sparsity penalty term% data: Our 64x10000 matrix containing the training data. So, data(:,i) is the i-th training example. % The input theta is a vector (because minFunc expects the parameters to be a vector). % We first convert theta to the (W1, W2, b1, b2) matrix/vector format, so that this % follows the notation convention of the lecture notes.
W1 = reshape(theta(1:hiddenSize*visibleSize), hiddenSize, visibleSize);W2 = reshape(theta(hiddenSize*visibleSize+1:2*hiddenSize*visibleSize), visibleSize, hiddenSize);b1 = theta(2*hiddenSize*visibleSize+1:2*hiddenSize*visibleSize+hiddenSize);b2 = theta(2*hiddenSize*visibleSize+hiddenSize+1:end);
% Cost and gradient variables (your code needs to compute these values). % Here, we initialize them to zeros. cost = 0;W1grad = zeros(size(W1)); W2grad = zeros(size(W2));b1grad = zeros(size(b1)); b2grad = zeros(size(b2));
%% ---------- YOUR CODE HERE --------------------------------------% Instructions: Compute the cost/optimization objective J_sparse(W,b) for the Sparse Autoencoder,% and the corresponding gradients W1grad, W2grad, b1grad, b2grad.%% W1grad, W2grad, b1grad and b2grad should be computed using backpropagation.% Note that W1grad has the same dimensions as W1, b1grad has the same dimensions% as b1, etc. Your code should set W1grad to be the partial derivative of J_sparse(W,b) with% respect to W1. I.e., W1grad(i,j) should be the partial derivative of J_sparse(W,b) % with respect to the input parameter W1(i,j). Thus, W1grad should be equal to the term % [(1/m) \Delta W^{(1)} + \lambda W^{(1)}] in the last block of pseudo-code in Section 2.2 % of the lecture notes (and similarly for W2grad, b1grad, b2grad).% % Stated differently, if we were using batch gradient descent to optimize the parameters,% the gradient descent update to W1 would be W1 := W1 - alpha * W1grad, and similarly for W2, b1, b2. % m=size(data,2);
x=data;a1=x;z2=W1*a1+repmat(b1,1,m);a2=sigmoid(z2);z3=W2*a2+repmat(b2,1,m);a3=sigmoid(z3);h=a3;y=x;squared_error=0.5*sum((h-y).^2,1);rho=1/m*sum(a2,2);sparsity_penalty= beta*sum(sparsityParam.*log(sparsityParam./rho)+(1-sparsityParam).*log((1-sparsityParam)./(1-rho)));cost=1/m*sum(squared_error)+lambda/2*(sum(sum(W1.^2))+sum(sum(W2.^2))) + sparsity_penalty;
grad_z3=a3.*(1-a3);delta_3=-(y-a3).*grad_z3;grad_z2=a2.*(1-a2);delta_2=(W2'*delta_3+repmat(beta*(-sparsityParam./rho+(1-sparsityParam)./(1-rho)),1,m)).*grad_z2;Delta_W2=delta_3*a2';Delta_b2=sum(delta_3,2);Delta_W1=delta_2*a1';Delta_b1=sum(delta_2,2);W1grad=1/m*Delta_W1+lambda*W1;W2grad=1/m*Delta_W2+lambda*W2;b1grad=1/m*Delta_b1;b2grad=1/m*Delta_b2;
%-------------------------------------------------------------------% After computing the cost and gradient, we will convert the gradients back% to a vector format (suitable for minFunc). Specifically, we will unroll% your gradient matrices into a vector.
grad = [W1grad(:) ; W2grad(:) ; b1grad(:) ; b2grad(:)];
end
%-------------------------------------------------------------------% Here's an implementation of the sigmoid function, which you may find useful% in your computation of the costs and the gradients. This inputs a (row or% column) vector (say (z1, z2, z3)) and returns (f(z1), f(z2), f(z3)).
function sigm = sigmoid(x) sigm = 1 ./ (1 + exp(-x));end
在編碼器的輸入為圖片時,我們對輸入層到隱藏層的權重進行可視化,得到如下圖所示結果:
可以發現,稀疏自編碼器可以自動提取輸入圖片的邊緣特征。
稀疏自編碼器完整的MATLAB實現代碼已經上傳,地址http://download.csdn.net/detail/u010278305/8901005 轉載請注明出處:http://blog.csdn.net/u010278305————————————————版權聲明:本文為CSDN博主「chenynCV」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/u010278305/article/details/46881443