Try   HackMD

類神經網路的 ReLU 及其常數時間實作

資料整理: jserv

類神經網路的激勵函數

ReLU 全名為 Rectified Linear Unit,中譯為「修正線性單元」,是種類神經網路中激勵函數 (activation function,也可翻譯為活化函數)。所謂的激勵函數,用意是增加類神經網路裡頭的非線性特徵。早期尚未發展出深層網路時,時常被拿來做資料預測的演算法是線性回歸法 (linear regression),正如字面上的意義,線性回歸法只能用來預測呈線性分佈的資料,非線性的關係就難以用這樣的函數來描述。但現實生活中大部分的現象都是非線性,例如美國人的收入與年齡之間的關係呈曲線分佈,這樣要給定一個年紀的人,去預測他的收入,就顯然難以利用線性回歸。因此,為解決更複雜的問題,人們就發展出了帶有非線性特徵的 Logistic Regression,開始可解決簡單的二分法問題。

然而一個 Logistic Regression 的能力還是有限,即便是二分法都有無法正確分類的狀況,因此為了得到更強大的函數,數學家嘗試串接多個 Logistic Regression,形成初步的類神經網路。

對照參閱台大電機系李宏毅教授的機器學習線上課程

ReLU 定義如下:

ReLU(x)={xif x00if x<0

ReLU 計算量小,只要判斷輸入是否大於 0,沒有指數運算。

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

常數時間度 ReLU 實作

思路:由於 ReLU 函數要判斷輸入數值的正負,但浮點數的操作成本較高,於是我們可引入 union,讓 float 和 int (有號整數) 共用同一段記憶體空間 (針對 LP64 data model):

float ReLU(float x)
{
    union {
        float f;
        int32_t i;
    } out = { .f = x };
    ...
}

首先我們回顧有號整數的表達方式,為了方便圖解,下列圖示以 8 位元的整數 (即對應到 C 語言的 int8_t,定義於 <stdint.h> 標頭檔)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

sign bit 為 0 時,表示該數值為「正」,數值為

0×20 (最右邊的位元) +
0×21
(右邊數來第二個位元) +
1×22
(右邊數來第三個位元) = 4 (十進位)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

sign bit 為 1 時,表示該數值為「負」,右側 7 個位元表示數值

274=124,這編碼採用二補數

二補數看似不直觀,但可縮減運算的成本。例如十進位的

4
1
相加,透過二補數運作如下:
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

從上圖右方起逐位元進行加法運算,連帶 sign bit 也可運算,超過 8 位元能表達的位元 (即上圖左下的 1) 就直接捨棄,這樣就讓電路設計變得單純。

另外,在二補數系統中,對有號數的位移 (shift) 概念上也跟無號整數相同,但為了確保最終結果的正負號一致,需要額外的運算規則:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

當你將有號整數右移,需要在左側填補一致的 sign bit

知曉二補數系統及有號整數右移的規則後,我們考慮 ~(out.i >> 31) 這個表示方式,其實相當於取參數 x 的 sign bit,分為以下兩種狀況:

  • x<0
    ,則 ~(out.i >> 31) 得到運算結果是 000...00 (32-bits)
  • x>=0
    ,則 ~(out.i >> 31) 得到運算結果是 111...11 (32-bits)

再將 x 和上述 ~(out.i >> 31) 進行 AND 運算,即為 ReLU 函數的定義。

程式碼列表如下:

#include <stdint.h>
// 當輸入 x 大於等於 0 時,回傳 x,否則回傳 0
float ReLU(float x) {
    /* 宣告一個 union,由兩個 field 組成
     * 一個型態為 float,用以儲存原本的資料
     * 一個型態為 int,用以進行位移運算
     * 由於 union 中的所有欄位共用同一份記憶體
     * 且 float 和 int32_t 都佔四個 byte
     * 因此對 i 操作時等同於在變更 f 的值
     */
    union {
        float f;
        int32_t i;
    } out = {.f = x}; /* 將資料存入 union */
    /* 由於 int32_t 是有號數型態,因此位移時是採用算數位移(帶號)
     * 將此數向右位移 31 次,會使 4 個 byte 被 sign 值填滿
     * (若非負則為 0,否則為 1)
     * 將其反相後,即成為 & 運算的遮罩
     * 以此遮罩與原本的資料做 & 運算,若非負則內容不變
     * 否則會全部變成 0
     */
    out.i &= ~(out.i >> 31);
    /* 將處理完的結果以 float 的型態回傳 */
    return out.f;
}

ReLU 與其他激勵函數的比較

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Sigmoid function 作為 Logistic Regression 的激勵函數,是這個算式當中非線性特徵的由來。由於 Logistic Regression 的目的是做分類,其輸出是一個機率值,故其值域會介於

[0,1] 之間。在反向傳播演算法 (Backpropagation) 發明後,人們發現在計算神經網路中每一層結點的參數時,由於 Sigmoid 會把
(,)
的輸入映射到
[0,1]
之間,會造成在反向傳播參數時每一層的數字愈算愈小,到最後幾層的數字全都是 0 的梯度消失 (Gradient Vanishing) 現象。後來出現的 Hyperbolic tangent function (tanh)(長高的 Sigmoid,其值域在
[1,1]
之間)也有類似的問題。

因此,在 Yoshua Bengio 等人的論文〈Deep Sparse Rectifier Neural Networks〉(第 318 頁),提到以 ReLU 取代其它激勵函數的好處:

The rectifier activation function allows a network to easily obtain sparse representations.

Apart from being more biologically plausible, sparsity also leads to mathematical advantages (see previous section).

Computations are also cheaper: there is no need for computing the exponential function in activations, and sparsity can be exploited.

統整論文的描述:

  • ReLU 較容易使得神經網路的結構變得稀疏,因為算出來參數為負的結點被視為沒有貢獻,因此輸出為 0,相當於是從神經網路中被拿掉了
  • ReLU 的行為比較符合生物學當中觀察到的神經活化現象(全有全無律,也就是在刺激不夠大的時候,神經根本不會有反應回饋出現的現象)
  • ReLU 的計算量比較小

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

在神經生理方面,當刺激未達一定的強度時,神經元不會興奮,因此不會產生神經衝動。如果超過某個強度,才會引起神經衝動。ReLU 較好捕捉這個生物神經元的特徵。

因此, ReLU 成為現代訓練類神經網路時,常用的激勵函數之一。

延伸閱讀: