原創宣告:本文為 SIGAI 原創文章,僅供個人學習使用,未經允許,不能用於商業目的。

其它機器學習、深度學習演算法的全面系統講解可以閱讀

《機器學習-原理、演算法與應用》

,清華大學出版社,

雷明著

,由SIGAI公眾號作者傾力打造。

書的購買連結

書的勘誤,最佳化,原始碼資源

在SIGAI之前的公眾號文章“反向傳播演算法推導-全連線神經網路”中,我們推導了全連線神經網路的反向傳播演算法。其核心是定義誤差項,以及確定誤差項的遞推公式,再根據誤差項得到對權重矩陣、偏置向量的梯度。最後用梯度下降法更新。卷積神經網路由於引入了卷積層和池化層,因此情況有所不同。在今天這篇文章中,我們將詳細為大家推導卷積神經網路的反向傳播演算法。對於卷積層,我們將按兩條路線進行推導,分別是標準的卷積運算實現,以及將卷積轉化成矩陣乘法的實現。在文章的最後一節,我們將介紹具體的工程實現,即卷積神經網路的卷積層,池化層,啟用函式層,損失層怎樣完成反向傳播功能。

回顧

首先回顧一下全連線神經網路反向傳播演算法的誤差項遞推計算公式。根據第l層的誤差項計算第l-1層的誤差項的遞推公式為:

反向傳播演算法推導-卷積神經網路

其中W為權重矩陣,u為臨時變數,f為啟用函式。根據誤差項計算權重梯度的公式為:

反向傳播演算法推導-卷積神經網路

其中x為本層的輸入向量。這幾組公式具有普遍意義,對於卷積神經網路的全連線層依然適用。如果你對這些公式的推導還不清楚,請先去閱讀我們之前的文章“反向傳播演算法推導-全連線神經網路”。

卷積層

首先推導卷積層的反向傳播計算公式。正向傳播時,卷積層實現的對映為:

反向傳播演算法推導-卷積神經網路

我們用前面的這個例子來進行計算:

卷積輸出影象的任意一個元素都與卷積核矩陣的任意一個元素都有關,因為輸出影象的每一個畫素值都共用了一個卷積核模板。反向傳播時需要計算損失函式對卷積核以及偏置項的偏導數,和全連線網路不同的是,卷積核要作用於同一個影象的多個不同位置。

上面的描述有些抽象,下面我們用一個具體的例子來說明。假設卷積核矩陣為:

反向傳播演算法推導-卷積神經網路

輸入影象是:

反向傳播演算法推導-卷積神經網路

卷積之後產生的輸出影象是U,注意這裡只進行了卷積、加偏置項操作,沒有使用啟用函式:

反向傳播演算法推導-卷積神經網路

正向傳播時的卷積操作為:

反向傳播演算法推導-卷積神經網路

反向傳播時需要計算損失函式對卷積核以及偏置項的偏導數,和全連線網路不同的是,卷積核要反覆作用於同一個影象的多個不同位置。根據鏈式法則,損失函式對第l層的卷積核的偏導數為:

反向傳播演算法推導-卷積神經網路

在這裡i和j是卷積輸出影象的行和列下標,這是因為輸出影象的每一個元素都與卷積核的元素

k_{pq}

相關。首先我們看上式最右邊求和項的第二個乘積項:

反向傳播演算法推導-卷積神經網路

這是啟用函式對輸入值的導數,啟用函式作用於每一個元素,產生同尺寸的輸出影象,和全連線網路相同。第三個乘積項為:

反向傳播演算法推導-卷積神經網路

假設

\frac{\partial L}{\partial x_{ij}^{(l)}}

已經求出,我們根據它就可以算出

\frac{\partial L}{\partial k_{pq}^{(l)}}

的值:

反向傳播演算法推導-卷積神經網路

偏置項的偏導數更簡單:

反向傳播演算法推導-卷積神經網路

這和全連線層的計算方式類似。同樣的定義誤差項為:

反向傳播演算法推導-卷積神經網路

這是損失函式對臨時變數的偏導數。和全連線型不同的是這是一個矩陣:

反向傳播演算法推導-卷積神經網路

尺寸和卷積輸出影象相同,而全連線層的誤差向量和該層的神經元個數相等。這樣有:

反向傳播演算法推導-卷積神經網路

這也是一個卷積操作,

\delta^{(l)}

充當卷積核,

x^{(l-1)}

則充當輸入影象。

卷積輸出影象對應的誤差項矩陣

\delta

為:

反向傳播演算法推導-卷積神經網路

下面計算損失函式對卷積核各個元素的偏導數,根據鏈式法則有:

反向傳播演算法推導-卷積神經網路

這是因為產生輸出

u_{11}

時卷積核元素

k_{11}

在輸入影象中對應的元素是

x_{11}

。產生輸出

u_{12}

時卷積核元素

k_{11}

在輸入影象中對應的元素是

x_{12}

。其他的依次類推。同樣的有:

反向傳播演算法推導-卷積神經網路

其他的以此類推。從上面幾個偏導數的值我們可以總結出這個規律:損失函式對卷積核的偏導數實際上就是輸入影象矩陣與誤差矩陣的卷積:

反向傳播演算法推導-卷積神經網路

其中

\ast

為卷積運算。寫成矩陣形式為:

反向傳播演算法推導-卷積神經網路

在這裡conv為卷積運算,卷積輸出影象的尺寸剛好和卷積核矩陣的尺寸相同。現在的問題是

\delta_{pq}^{(l)}

怎麼得到。如果卷積層後面是全連線層,按照全連線層的方式可以從後面的層的誤差得到

\delta_{pq}^{(l)}

。如果後面跟的是池化層,處理的方法在下一節中介紹。

接下來要解決的問題是怎樣將誤差項傳播到前一層。卷積層從後一層接收到的誤差為

\delta^{(l)}

,尺寸和卷積輸出影象相同,傳播到前一層的誤差為

\delta^{(1-l)}

,尺寸和卷積輸入影象相同。同樣的,我們用上面的例子。假設已經得到了

\delta^{(l)}

,現在要做的是根據這個值計算出

\delta^{(1-l)}

。根據定義:

反向傳播演算法推導-卷積神經網路

正向傳播時的卷積操作為:

反向傳播演算法推導-卷積神經網路

根據定義:

反向傳播演算法推導-卷積神經網路

由於:

反向傳播演算法推導-卷積神經網路

因此有:

反向傳播演算法推導-卷積神經網路

類似的可以得到:

反向傳播演算法推導-卷積神經網路

從而有:

反向傳播演算法推導-卷積神經網路

類似的有:

反向傳播演算法推導-卷積神經網路

剩下的以此類推。從上面的過程我們可以看到,實際上是將

\delta^{(1-l)}

進行擴充(上下左右各擴充2個0)之後的矩陣和卷積核矩陣K進行順時針180度旋轉的矩陣的卷積,即:

反向傳播演算法推導-卷積神經網路

將上面的結論推廣到一般情況,我們得到誤差項的遞推公式為:

反向傳播演算法推導-卷積神經網路

其中rot180表示矩陣順時針旋轉180度操作。至此根據誤差項得到了卷積層的權重,偏置項的偏導數;並且把誤差項透過卷積層傳播到了前一層。推導卷積層反向傳播演算法計算公式的另外一種思路是把卷積運算轉換成矩陣乘法,這種做法更容易理解,在後面將會介紹。

池化層

池化層沒有權重和偏置項,因此無需對本層進行引數求導以及梯度下降更新,所要做的是將誤差項傳播到前一層。假設池化層的輸入影象是

X^{(l-1)}

,輸出影象為

X^{(l)}

,這種變換定義為:

反向傳播演算法推導-卷積神經網路

其中down為下采樣操作,在正向傳播時,對輸入資料進行了壓縮。在反向傳播時,接受的誤差是

\delta^{(l)}

,尺寸和

X^{(l)}

相同,傳遞出去的誤差是

\delta^{(l-1)}

,尺寸和

X^{(l-1)}

相同。和下采樣相反,我們用上取樣來計算誤差項:

反向傳播演算法推導-卷積神經網路

其中up為上取樣操作。如果是對s×s的塊進行的池化,在反向傳播時要將

\delta^{(l)}

的一個誤差項值擴充套件為

\delta^{(l-1)}

的對應位置的s×s個誤差項值。下面分別對均值池化和max池化進行討論。均值池化的變換函式為:

反向傳播演算法推導-卷積神經網路

其中

x_{i}

為池化的s×s子影象塊的畫素,y是池化輸出畫素值。假設損失函式對輸出畫素的偏導數為

\delta

,則對輸入畫素的偏導數為:

反向傳播演算法推導-卷積神經網路

因此由

\delta^{(l)}

得到

\delta^{(l-1)}

的方法為,將

\delta^{(l)}

的每一個元素都擴充為s×s個元素:

反向傳播演算法推導-卷積神經網路

再看第二種情況。如果是max池化,在進行正向傳播時,需要記住最大值的位置。在反向傳播時,對於擴充的s×s塊,最大值位置處的元素設為,其他位置全部置為0:

反向傳播演算法推導-卷積神經網路

同樣的,我們給出推導過程。假設池化函式為:

反向傳播演算法推導-卷積神經網路

損失函式對

x_{i}

的偏導數為:

反向傳播演算法推導-卷積神經網路

在這裡分兩種情況,如果i=t,則有:

反向傳播演算法推導-卷積神經網路

否則有:

反向傳播演算法推導-卷積神經網路

至此我們得到了卷積層和池化層的反向傳播實現。全連線層的反向傳播計算方法和全連線神經網路相同,組合起來我們就得到了整個卷積網路的反向傳播演算法計算公式。

將卷積轉化成矩陣乘法

如果用標準的形式實現卷積,則要用迴圈實現,依次執行乘法和加法運算。為了加速,可以將卷積操作轉化成矩陣乘法實現,以充分利用GPU的平行計算能力。

​整個過程分為以下3步:

1。將待卷積影象、卷積核轉換成矩陣

2。呼叫通用矩陣乘法GEMM函式對兩個矩陣進行乘積

3。將結果矩陣轉換回影象

在反捲積的原理介紹中,我們也介紹了這種用矩陣乘法實現卷積運算的思路。在Caffe的實現中和前面的思路略有不同,不是將卷積核的元素複製多份,而是將待卷積影象的元素複製多份。

首先將輸入影象每個卷積位置處的子影象按照行拼接起來轉換成一個列向量。假設子影象的尺寸為s×s,和卷積核大小一樣,列向量的尺寸就是s×s;如果一共有

n_{conv}

個卷積子影象,列向量的個數就是

n_{conv}

,接下來將這些列向量組合起來形成矩陣。假設有一個m×n的輸入影象:

反向傳播演算法推導-卷積神經網路

對於第一個卷積位置的s×s子影象,轉換成列向量之後變為:

反向傳播演算法推導-卷積神經網路

對於單通道影象,將所有位置的子矩陣都像這樣轉換成列向量,最後將

n_{conv}

個列向量組成矩陣,矩陣的行數為s×s,列數為

n_{conv}

反向傳播演算法推導-卷積神經網路

對於多通道影象,還要將上面的這種單通道影象轉換成的矩陣在垂直方向依次拼接起來。最後形成的矩陣的行數為c×s×s,其中c是影象的通道數。

接下來,將卷積核矩陣也轉換成向量。具體做法是,將卷積核矩陣的所有行拼接起來形成一個行向量。每個卷積核形成一個行向量,有

n_{kernel}

個卷積核,就有

n_{kernel}

個行向量。假設有一個s×s的卷積核矩陣:

反向傳播演算法推導-卷積神經網路

轉換之後變成這樣的列向量:

反向傳播演算法推導-卷積神經網路

如果卷積核有多個通道,就將這多個通道拼接起來,形成一個更大的行向量。由於卷積層有多個卷積核,因此這樣的行向量有多個,將這些行向量合併在一起,形成一個矩陣:

反向傳播演算法推導-卷積神經網路

有了上面這些矩陣,最後就將卷積操作轉換成如下的矩陣乘積:

反向傳播演算法推導-卷積神經網路

乘積結果矩陣的每一行是一個卷積結果影象。下面用一個實際的例子來說明。假設輸入影象為:

反向傳播演算法推導-卷積神經網路

卷積核為:

反向傳播演算法推導-卷積神經網路

則輸入影象的第一個卷積位置的子影象為:

反向傳播演算法推導-卷積神經網路

轉化為列向量後為:

反向傳播演算法推導-卷積神經網路

第二個卷積位置的子影象為:

反向傳播演算法推導-卷積神經網路

轉化成列向量為:

反向傳播演算法推導-卷積神經網路

總共有4個卷積子影象,這樣整個影象轉換成矩陣之後為:

反向傳播演算法推導-卷積神經網路

卷積核轉換成矩陣之後為:

反向傳播演算法推導-卷積神經網路

讀者可以驗證,矩陣乘法:

反向傳播演算法推導-卷積神經網路

即為卷積的結果。

採用這種矩陣乘法之後,反向傳播求導可以很方面的透過矩陣乘法實現,和全連線神經網路類似。假設卷積輸出影象為Y,即:

Y=KX

則我們可以很方便的根據損失函式對Y的梯度計算出對卷積核的梯度,根據之前的文章“反向傳播演算法推導-全連線神經網路”中證明過的結論,有:

反向傳播演算法推導-卷積神經網路

而誤差項傳播到前一層的計算公式為:

反向傳播演算法推導-卷積神經網路

工程實現

下面我們介紹全連線層,卷積層,池化層,啟用函層,損失層的工程實現細節。核心是正向傳播和反向傳播的實現。

在實現時,由於啟用函式對全連線層,卷積層,以後要講述的迴圈神經網路的迴圈層都是一樣的,因此為了程式碼複用,靈活組合,一般將啟用函式單獨拆分成一層來實現。

下面我們將各種層抽象成統一的實現方式。在正向傳播時,每一層根據輸入資料

x^{(l-1)}

計算輸出資料

x^{(l)}

,本層可能還有需要訓練得到的引數

w^{(l)}

。正向傳播時的計算為:

反向傳播演算法推導-卷積神經網路

其中h是本層的對映函式。

無論是哪一種層,反向傳播時要做的事情是:

如果本層有需要透過訓練得到的引數,根據後一層傳入的誤差項

\delta^{(l)}

計算本層引數的梯度值

▽_{w^{(l)}}L

,而這個誤差項是損失函式對本層輸出值的梯度:

反向傳播演算法推導-卷積神經網路

將誤差傳播到前一層,即根據

\delta^{(l)}

計算

\delta^{(l-1)}

是損失函式對本層輸入資料的梯度:

反向傳播演算法推導-卷積神經網路

在之前的文章“反向傳播演算法推導-全連線神經網路”中已經介紹過,啟用函式實現的是向量到向量的逐元素對映,對輸入向量的每個分量進行啟用函式變換。正向傳播時接受前一層的輸入,透過啟用函式作用於輸入資料的每個元素之後產生輸出。反向傳播時接受後一層傳入的誤差項,計算本層的誤差項並把誤差項傳播到前一層,計算公式為:

反向傳播演算法推導-卷積神經網路

由於啟用層沒有需要訓練得到的引數,因此無需根據誤差項計算本層的梯度值,只需要將誤差傳播到前一層即可。

拆出啟用函式之後,全連線層的輸入資料是一個向量,計算該向量與權重矩陣的乘積,如果需要還要加上偏置,最後產生輸出。正向傳播的計算公式為:

反向傳播演算法推導-卷積神經網路

反向傳播時計算本層權重與偏置的導數:

反向傳播演算法推導-卷積神經網路

另外還要將誤差傳播到前一層:

反向傳播演算法推導-卷積神經網路

卷積層和池化層的反向傳播實現已經在前面介紹了,因此在這裡不再重複。

損失層實現各種型別的損失函式,它們僅在訓練階段使用,是神經網路的最後一層,也是反向傳播過程的起點。損失層的功能是在正向傳播時根據傳入的資料以及函式的引數計算損失函式的值,送入到求解器中使用;在反向傳播時計算損失函式對輸入資料的導數值,傳入前一層