稀疏自動編碼之自動編碼器和稀疏性


到目前為止,已經敘述了神經網絡的監督學習,即學習的樣本都是有標簽的。現在假設我們有一個沒有標簽的訓練集\textstyle \{x^{(1)}, x^{(2)}, x^{(3)}, \ldots\},其中\textstyle x^{(i)} \in \Re^{n}. 自動編碼器就是一個運用了反向傳播進行無監督學習的神經網絡,學習的目的就是為了讓輸出值和輸入值相等,即\textstyle y^{(i)} = x^{(i)}.下面就是一個自動編碼器:

自動編碼器試圖學習一個函數\textstyle h_{W,b}(x) \approx x. 換句話說,它試圖逼近一個等式函數,使得該函數的輸出 \textstyle \hat{x} 和輸入 \textstyle x 很近似。舉一個具體的例子,假設輸入 \textstyle x 是來自一個 \textstyle 10 \times 10 圖像(共100個像素點)像素點的灰度值,在 \textstyle L_2 層有 \textstyle s_2=50 個隱層節點. 注意輸出 \textstyle y \in \Re^{100}. 由於隱層節點只有50個,所以網絡必須學習出輸入的壓縮表示,即給出以隱層節點激活值作為元素的向量\textstyle a^{(2)} \in \Re^{50},它需要重構出100個像素點灰度值的輸入 \textstyle x. 如果輸入是完全隨機的,那么這種壓縮學習的任務將會很難,但是數據具有一定的結構,例如一些輸入特征彼此關聯,那么這個算法就可以發現這些關聯關系。事實上,自動編碼器往往最終就是學習出一個較低維度的表示。

我們認為,上面討論是依賴於隱層節點數很少。但是,即使隱層節點數很多(也許比輸入的像素點個數還多),通過對網絡加上某些約束,我們仍然能夠發現感興趣的結構。特別是,對隱層節點加上稀疏約束

簡答來說,如果一個神經元的輸出為1,我們認為這個神經元是被激活的,如果某個神經元的輸出是0,就認為這個神經元是抑制的。我們想約束神經元,使得神經元在大多數時候是處於抑制狀態。假設激活函數是sigmoid函數。

在上面的網絡中,\textstyle a^{(2)}_j 表示隱層(第二層)節點 \textstyle j 的激活值。但是這種表示並沒有顯示給出哪一個輸入 \textstyle x 導致了這個激活值。因此,用 \textstyle a^{(2)}_j(x) 去表示當輸入為 \textstyle x 時這個隱層節點的激活值。進一步,令

\begin{align}
\hat\rho_j = \frac{1}{m} \sum_{i=1}^m \left[ a^{(2)}_j(x^{(i)}) \right]
\end{align}

表示隱層單元節點 \textstyle j 的平均激活值(對於每一個輸入樣本,該節點都會輸出一個激活值,所以將該節點對應的所有樣本的激活值求均值)。然后加以約束:

\begin{align}
\hat\rho_j = \rho,
\end{align}

這里,\textstyle \rho 是稀疏參數,通常被設為一個很小的接近於0的值(比如 \textstyle \rho = 0.05)。換句話說,我們想要隱層神經元 \textstyle j 的平均激活值接近 0.05. 為了滿足這個約束,隱層節點的激活值必須大多數都接近0.

為了達到這個目的,我們將在優化目標函數的時候,對那些與 稀疏參數 \textstyle \rho 偏差很大的 \textstyle \hat\rho_j  加以懲罰,我們使用下面的懲罰項:

\begin{align}
\sum_{j=1}^{s_2} \rho \log \frac{\rho}{\hat\rho_j} + (1-\rho) \log \frac{1-\rho}{1-\hat\rho_j}.
\end{align}

 

其中 \textstyle s_2 是隱層神經元的數目。這個約束想也可寫為:

\begin{align}
\sum_{j=1}^{s_2} {\rm KL}(\rho || \hat\rho_j),
\end{align}

其中\textstyle {\rm KL}(\rho || \hat\rho_j)
 = \rho \log \frac{\rho}{\hat\rho_j} + (1-\rho) \log \frac{1-\rho}{1-\hat\rho_j} ,容易驗證,如果\textstyle \hat\rho_j = \rho\textstyle {\rm KL}(\rho || \hat\rho_j) = 0,如果 \textstyle \hat\rho_j 和 \textstyle \rho 差值很大,那么該項也會變大。符合我們想要的懲罰方式。例如我們令 \textstyle \rho = 0.2,畫出

\textstyle {\rm KL}(\rho || \hat\rho_j) 隨 \textstyle \hat\rho_j 變化而變化的情況:

由上圖可以看出,在\textstyle \hat\rho_j = \rho時,函數到達最小值0.但是當\textstyle \hat\rho_j無論從左邊還是右邊遠離\textstyle \rho(0.2)時,函數值顯著增大。

於是,我們總體的代價函數(損失函數)就變為:

\begin{align}
J_{\rm sparse}(W,b) = J(W,b) + \beta \sum_{j=1}^{s_2} {\rm KL}(\rho || \hat\rho_j),
\end{align}

這里的\textstyle J(W,b) 是在前面的博文

稀疏自動編碼之反向傳播算法(BP)

中定義的,\textstyle \beta 是用來控制稀疏懲罰項的權重。\textstyle \hat\rho_j 其實也依賴於\textstyle W,b ,因為\textstyle \hat\rho_j 是隱層節點的平均激活值,而計算平均激活值,首先需要計算該節點所有激活值,激活值是多少是取決於\textstyle W,b的(訓練集一定)。

下面把懲罰項加入代價函數,再計算導數。只需在原來的代碼中作很小的改動,例如在反向傳播的第2層,前面博文中已經計算出:

現在用下面的式子代替:

\begin{align}
\delta^{(2)}_i =
  \left( \left( \sum_{j=1}^{s_{2}} W^{(2)}_{ji} \delta^{(3)}_j \right)
+ \beta \left( - \frac{\rho}{\hat\rho_i} + \frac{1-\rho}{1-\hat\rho_i} \right) \right) f'(z^{(2)}_i) .
\end{align}

稍微需要注意的是,為了計算這一項,需要知道\textstyle \hat\rho_j,因此,在前饋傳播過程中首先把隱層所有神經元的平均激活值計算出來。當訓練集很小的時候,在前饋傳播的時候,把所有神經元的激活值和平均值都存儲在內存里,然后在反向傳播過程中可以利用這些提取計算好的激活值。如果訓練集太大,沒有那么多內存存儲中間結果,可以在前饋傳播過程中先計算每個節點針對所有的樣本的激活值,從而計算出該節點的平均激活值\textstyle \hat\rho_j,在計算下一個節點的平均激活值的時候就可以丟掉前一個節點的針對所有樣本的激活值,值存儲它的平均激活值,這樣之后,在反向傳播之前,就需要再一次前饋傳播得到神經元的激活值,這樣會讓計算效率有些降低,但是保證內存的夠用。

整個用梯度下降求解過程的偽代碼在

稀疏自動編碼之反向傳播算法(BP)

中已經給出,只不過目標函數改為這里給出的\textstyle J_{\rm sparse}(W,b). 然后用

稀疏自動編碼之梯度檢驗

中介紹的導數檢驗的方法,可以驗證代碼的正確與否。

 

學習來源:http://deeplearning.stanford.edu/wiki/index.php/Autoencoders_and_Sparsity

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM