每個人都知道神經網絡中的偏置(bias)是什麼,而且從人類實現第一個感知器開始,每個人都知道神經元需要添加偏置項。但你是否考慮過我們為什麼要使用偏置項呢?就我而言,直到不久前我才弄清楚這個問題。當時我和一個本科生討論了一些神經網絡模型,但不知何故她把「偏置輸入」(bias input)和「統計基差」( statistical bias)搞混了。對我來說,向她解釋這些概念當然很容易,但我卻很難進一步地告訴她我們為什麼要使用偏置項。過了一段時間,我決定嘗試寫代碼來研究這一問題。
讓我們先從一些簡單的概念開始。
感知器是多層感知器(MLP)和人工神經網絡的前身。眾所周知,感知器是一種用於監督學習的仿生算法。它本質上是一個線性分類器,如圖所示:
下面讓我們考察一下這個模型的數學方程:
你可能會注意到它與線性函數的標準形式是相似的。如果我們不適用激活函數,或將激活函數替換為恆等映射,這些公式將是相同的(在這裡為了方便描述,我們只考慮單一輸入):
比較這兩個公式,很明顯我們的偏置項就對應了線性函數中的b。現在的問題就轉化為,線性函數中的b為什麼那麼重要?如果你過去幾年沒有上過任何線性代數課程(就像我一樣),可能對一些概念不夠了解。但是下面的內容是很容易理解的:
我們很容易就注意到,當b=0時,函數總是通過原點[0,0]。當我們保持a不變的情況下引入b時,新的函數總是相互平行的。那麼,我們能從中得到什麼信息呢?
我們可以說,係數a決定了函數的角度,而分量b決定了函數與x軸的交點。
此時我想你已經注意到了一些問題,對吧?如果沒有b,函數將會失去很多靈活性。只不過對一些分布進行分類時偏置項可能有用,但不是對所有情況都有用。怎樣測試它的實際效果呢?讓我們使用一個簡單的例子:OR函數。讓我們先來看看它的分布:
繪製在笛卡爾坐標系中的OR函數:
我想你已經想明白了這個問題。圖中兩個點([0,0]和[1,0])是兩個不同的類,但任何一條過[0,0]的直線都沒有辦法將這兩個點分開。那麼感知機如何對它分類呢?有偏置項和無偏置項的結果分別是怎樣的呢?讓我們通過編程,看看將會發生什麼!下面是用Python實現的感知器神經元:
class Perceptron():def __init__ (self, n_input, alpha=0.01, has_bias=True):self.has_bias = has_bias self.bias_weight = random.uniform(-1,1) self.alpha = alpha self.weights = [] for i in range(n_input): self.weights.append(random.uniform(-1,1))def classify(self, input): summation = 0 if(self.has_bias): summation += self.bias_weight * 1 for i in range(len(self.weights)): summation += self.weights[i] * input[i] return self.activation(summation)def activation(self, value): if(value < 0): return 0 else: return 1def train(self, input, target): guess = self.classify(input) error = target - guess if(self.has_bias): self.bias_weight += 1 * error * self.alpha for i in range(len(self.weights)): self.weights[i] += input[i] * error * self.alpha
首先,讓我們訓練無偏置項的感知器。我們知道,分類器(在本例中是我們的函數)總是通過[0,0]的。正如我們之前所說的那樣,分類器無法分開這兩類。在這種情況下儘管一直在向分離平面逼近,但它還是不能將[0,0]和[1,0]分開,
現在我們來看一下有偏置項的感知器。首先,注意分類器的靈活性。如前所述,在這種情況下感知器具有更大的靈活性。此外我們可以注意到,它正在尋找與上一個實例相同的判別平面,但是現在它能夠找到分離數據的最佳位置。
所以,偏置項的重要性現在已經很清楚了。我知道你現在可能在思考激活函數,我們在python例子中使用了一個階躍函數作為激活函數,如果我們使用sigmoid作為激活函數,它的效果可能會更好?相信我:不會的。讓我們看看當我們將sigmoid函數作為線性函數的激活函數(σ(f (x)))會發生什麼:
你是否注意到這裡的例子和線性函數的例子很相似?sigmoid函數雖然改變了輸出的形狀,但是我們仍然遇到同樣的問題:如果沒有偏置項,所有的函數都會經過原點。當我們試圖用曲線分離OR函數中時,它仍然得不到滿意的結果。如果您想嘗試一下,看看它是如何工作的,您只需要對python代碼做一些小小的修改。
我真誠地感謝你對這個主題感興趣。如果你有任何建議、意見,或者只是想和我打個招呼,請給我留言!我將很樂意和你討論這個問題。
作者:Caio Davi
deephub翻譯組:zhangzc