1. 程式人生 > >自編碼演算法與稀疏性

自編碼演算法與稀疏性

目前為止,我們已經討論了神經網路在有監督學習中的應用。在有監督學習中,訓練樣本是有類別標籤的。現在假設我們只有一個沒有帶類別標籤的訓練樣本集合 \textstyle \{x^{(1)}, x^{(2)}, x^{(3)}, \ldots\} ,其中 \textstyle x^{(i)} \in \Re^{n} 。自編碼神經網路是一種無監督學習演算法,它使用了反向傳播演算法,並讓目標值等於輸入值,比如 \textstyle y^{(i)} = x^{(i)} 。下圖是一個自編碼神經網路的示例。

Autoencoder636.png

自編碼神經網路嘗試學習一個 \textstyle h_{W,b}(x) \approx x 的函式。換句話說,它嘗試逼近一個恆等函式,從而使得輸出 \textstyle \hat{x} 接近於輸入 \textstyle x 。恆等函式雖然看上去不太有學習的意義,但是當我們為自編碼神經網路加入某些限制,比如限定隱藏神經元的數量,我們就可以從輸入資料中發現一些有趣的結構。舉例來說,假設某個自編碼神經網路的輸入 \textstyle x

是一張 \textstyle 10 \times 10 影象(共100個畫素)的畫素灰度值,於是 \textstyle n=100 ,其隱藏層 \textstyle L_2 中有50個隱藏神經元。注意,輸出也是100維的 \textstyle y \in \Re^{100} 。由於只有50個隱藏神經元,我們迫使自編碼神經網路去學習輸入資料的壓縮表示,也就是說,它必須從50維的隱藏神經元啟用度向量 \textstyle a^{(2)} \in \Re^{50}重構出100維的畫素灰度值輸入 \textstyle x 。如果網路的輸入資料是完全隨機的,比如每一個輸入 \textstyle x_i 都是一個跟其它特徵完全無關的獨立同分布高斯隨機變數,那麼這一壓縮表示將會非常難學習。但是如果輸入資料中隱含著一些特定的結構,比如某些輸入特徵是彼此相關的,那麼這一演算法就可以發現輸入資料中的這些相關性。事實上,這一簡單的自編碼神經網路通常可以學習出一個跟主元分析(PCA)結果非常相似的輸入資料的低維表示


我們剛才的論述是基於隱藏神經元數量較小的假設。但是即使隱藏神經元的數量較大(可能比輸入畫素的個數還要多),我們仍然通過給自編碼神經網路施加一些其他的限制條件來發現輸入資料中的結構。具體來說,如果我們給隱藏神經元加入稀疏性限制,那麼自編碼神經網路即使在隱藏神經元數量較多的情況下仍然可以發現輸入資料中一些有趣的結構。

稀疏性可以被簡單地解釋如下。如果當神經元的輸出接近於1的時候我們認為它被啟用,而輸出接近於0的時候認為它被抑制,那麼使得神經元大部分的時間都是被抑制的限制則被稱作稀疏性限制。這裡我們假設的神經元的啟用函式是sigmoid函式。如果你使用tanh作為啟用函式的話,當神經元輸出為-1的時候,我們認為神經元是被抑制的。

注意到 \textstyle a^{(2)}_j 表示隱藏神經元 \textstyle j 的啟用度,但是這一表示方法中並未明確指出哪一個輸入 \textstyle x 帶來了這一啟用度。所以我們將使用 \textstyle a^{(2)}_j(x) 來表示在給定輸入為 \textstyle x 情況下,自編碼神經網路隱藏神經元 \textstyle j 的啟用度。進一步,讓

\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 \hat\rho_j\textstyle \rho 有顯著不同的情況從而使得隱藏神經元的平均活躍度保持在較小範圍內。懲罰因子的具體形式有很多種合理的選擇,我們將會選擇以下這一種:

\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 是隱藏層中隱藏神經元的數量,而索引 \textstyle j 依次代表隱藏層中的每一個神經元。如果你對相對熵(KL divergence)比較熟悉,這一懲罰因子實際上是基於它的。於是懲罰因子也可以被表示為

\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 \rho 為均值和一個以 \textstyle \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 變化的變化。

KLPenaltyExample.png


我們可以看出,相對熵在 \textstyle \hat\rho_j = \rho 時達到它的最小值0,而當 \textstyle \hat\rho_j 靠近0或者1的時候,相對熵則變得非常大(其實是趨向於\textstyle \infty)。所以,最小化這一懲罰因子具有使得 \textstyle \hat\rho_j 靠近 \textstyle \rho 的效果。現在,我們的總體代價函式可以表示為

\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) 如之前所定義,而 \textstyle \beta 控制稀疏性懲罰因子的權重。 \textstyle \hat\rho_j 項則也(間接地)取決於 \textstyle W,b ,因為它是隱藏神經元 \textstyle j 的平均啟用度,而隱藏層神經元的啟用度取決於 \textstyle W,b


為了對相對熵進行導數計算,我們可以使用一個易於實現的技巧,這隻需要在你的程式中稍作改動即可。具體來說,前面在反向傳播演算法中計算第二層( \textstyle l=2 )更新的時候我們已經計算了

\begin{align}\delta^{(2)}_i = \left( \sum_{j=1}^{s_{2}} W^{(2)}_{ji} \delta^{(3)}_j \right) f'(z^{(2)}_i),\end{align}

現在我們將其換成

\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_i 來計算這一項更新。所以在計算任何神經元的反向傳播之前,你需要對所有的訓練樣本計算一遍前向傳播,從而獲取平均啟用度。如果你的訓練樣本可以小到被整個存到記憶體之中(對於程式設計作業來說,通常如此),你可以方便地在你所有的樣本上計算前向傳播並將得到的啟用度存入記憶體並且計算平均啟用度 。然後你就可以使用事先計算好的啟用度來對所有的訓練樣本進行反向傳播的計算。如果你的資料量太大,無法全部存入記憶體,你就可以掃過你的訓練樣本並計算一次前向傳播,然後將獲得的結果累積起來並計算平均啟用度 \textstyle \hat\rho_i (當某一個前向傳播的結果中的啟用度 \textstyle a^{(2)}_i 被用於計算平均啟用度 \textstyle \hat\rho_i 之後就可以將此結果刪除)。然後當你完成平均啟用度 \textstyle \hat\rho_i 的計算之後,你需要重新對每一個訓練樣本做一次前向傳播從而可以對其進行反向傳播的計算。對於後一種情況,你對每一個訓練樣本需要計算兩次前向傳播,所以在計算上的效率會稍低一些。

如果想要使用經過以上修改的反向傳播來實現自編碼神經網路,那麼就要對目標函式 \textstyle J_{\rm sparse}(W,b) 做梯度下降。使用梯度驗證方法來驗證梯度下降演算法是否正確。