深度学习85—[深度学习] 感知器
感知器
為了理解神經網絡,我們應該先理解神經網絡的組成單元——神經元。神經元也叫做感知器。感知器算法在上個世紀50-70年代很流行,也成功解決了很多問題。并且,感知器算法也是非常簡單的。
感知器的定義
下圖是一個感知器:
可以看到,一個感知器有如下組成部分:
-
輸入權值?一個感知器可以接收多個輸入
?
,每個輸入上有一個權值
?
,此外還有一個偏置項
?
,就是上圖中的 w0。
-
激活函數?感知器的激活函數可以有很多選擇,比如我們可以選擇下面這個階躍函數 f 來作為激活函數:
?
- 輸出?感知器的輸出由下面這個公式來計算
?
?
如果看完上面的公式一下子就暈了,不要緊,我們用一個簡單的例子來幫助理解。
例子:用感知器實現and函數
我們設計一個感知器,讓它來實現and運算。程序員都知道,and是一個二元函數(帶有兩個參數 x1 和 x2),下面是它的真值表:
?
為了計算方便,我們用0表示false,用1表示true。這沒什么難理解的,對于C語言程序員來說,這是天經地義的。
我們令 ,而激活函數 f 就是前面寫出來的階躍函數,這時,感知器就相當于and函數。不明白?我們驗算一下:
輸入上面真值表的第一行,即 x1 = 0, x2 = 0,那么根據公式(1),計算輸出:?
也就是當x1,x2都為0的時候,y為0,這就是真值表的第一行。讀者可以自行驗證上述真值表的第二、三、四行。
例子:用感知器實現or函數
同樣,我們也可以用感知器來實現or運算。僅僅需要把偏置項的值設置為-0.3就可以了。我們驗算一下,下面是or運算的真值表:
我們來驗算第二行,這時的輸入是x1 = 0, x2 = 1,帶入公式(1):
?
也就是當x1 = 0, x2 = 1時,y為1,即or真值表第二行。讀者可以自行驗證其它行。
感知器還能做什么
事實上,感知器不僅僅能實現簡單的布爾運算。它可以擬合任何的線性函數,任何線性分類或線性回歸問題都可以用感知器來解決。前面的布爾運算可以看作是二分類問題,即給定一個輸入,輸出0(屬于分類0)或1(屬于分類1)。如下面所示,and運算是一個線性分類問題,即可以用一條直線把分類0(false,紅叉表示)和分類1(true,綠點表示)分開。
然而,感知器卻不能實現異或運算,如下圖所示,異或運算不是線性的,你無法用一條直線把分類0和分類1分開。
感知器的訓練
現在,你可能困惑前面的權重項和偏置項的值是如何獲得的呢?這就要用到感知器訓練算法:將權重項 wi 和偏置項 b 初始化為0,然后,利用下面的感知器規則迭代的修改和,直到訓練完成。
?
?
其中:?
?
wi 是與輸入 xi 對應的權重項,b是偏置項。事實上,可以把看作是值永遠為1的輸入所對應的權重。是訓練樣本的實際值,一般稱之為label。而是感知器的輸出值,它是根據公式(1)計算得出。η 是一個稱為學習速率的常數,其作用是控制每一步調整權的幅度。每次從訓練數據中取出一個樣本的輸入向量,使用感知器計算其輸出,再根據上面的規則來調整權重。每處理一個樣本就調整一次權重。經過多輪迭代后(即全部的訓練數據被反復處理多輪),就可以訓練出感知器的權重,使之實現目標函數。
編程實戰:實現感知器
完整代碼請參考GitHub:?https://github.com/hanbt/learn_dl/blob/master/perceptron.py?(python2.7)
對于程序員來說,沒有什么比親自動手實現學得更快了,而且,很多時候一行代碼抵得上千言萬語。接下來我們就將實現一個感知器。
下面是一些說明:
- 使用python語言。python在機器學習領域用的很廣泛,而且,寫python程序真的很輕松。
- 面向對象編程。面向對象是特別好的管理復雜度的工具,應對復雜問題時,用面向對象設計方法很容易將復雜問題拆解為多個簡單問題,從而解救我們的大腦。
- 沒有使用numpy。numpy實現了很多基礎算法,對于實現機器學習算法來說是個必備的工具。但為了降低讀者理解的難度,下面的代碼只用到了基本的python(省去您去學習numpy的時間)。
下面是感知器類的實現,非常簡單。去掉注釋只有27行,而且還包括為了美觀(每行不超過60個字符)而增加的很多換行。
?
class Perceptron(object):def __init__(self, input_num, activator):'''初始化感知器,設置輸入參數的個數,以及激活函數。激活函數的類型為double -> double'''self.activator = activator# 權重向量初始化為0self.weights = [0.0 for _ in range(input_num)]# 偏置項初始化為0self.bias = 0.0def __str__(self):'''打印學習到的權重、偏置項'''return 'weights\t:%s\nbias\t:%f\n' % (self.weights, self.bias)def predict(self, input_vec):'''輸入向量,輸出感知器的計算結果'''# 把input_vec[x1,x2,x3...]和weights[w1,w2,w3,...]打包在一起# 變成[(x1,w1),(x2,w2),(x3,w3),...]# 然后利用map函數計算[x1*w1, x2*w2, x3*w3]# 最后利用reduce求和return self.activator(reduce(lambda a, b: a + b,map(lambda (x, w): x * w, zip(input_vec, self.weights)), 0.0) + self.bias)def train(self, input_vecs, labels, iteration, rate):'''輸入訓練數據:一組向量、與每個向量對應的label;以及訓練輪數、學習率'''for i in range(iteration):self._one_iteration(input_vecs, labels, rate)def _one_iteration(self, input_vecs, labels, rate):'''一次迭代,把所有的訓練數據過一遍'''# 把輸入和輸出打包在一起,成為樣本的列表[(input_vec, label), ...]# 而每個訓練樣本是(input_vec, label)samples = zip(input_vecs, labels)# 對每個樣本,按照感知器規則更新權重for (input_vec, label) in samples:# 計算感知器在當前權重下的輸出output = self.predict(input_vec)# 更新權重 self._update_weights(input_vec, output, label, rate)def _update_weights(self, input_vec, output, label, rate):'''按照感知器規則更新權重'''# 把input_vec[x1,x2,x3,...]和weights[w1,w2,w3,...]打包在一起# 變成[(x1,w1),(x2,w2),(x3,w3),...]# 然后利用感知器規則更新權重delta = label - outputself.weights = map(lambda (x, w): w + rate * delta * x,zip(input_vec, self.weights))# 更新biasself.bias += rate * delta接下來,我們利用這個感知器類去實現and函數。
def f(x):'''定義激活函數f'''return 1 if x > 0 else 0 def get_training_dataset():'''基于and真值表構建訓練數據'''# 構建訓練數據# 輸入向量列表input_vecs = [[1,1], [0,0], [1,0], [0,1]]# 期望的輸出列表,注意要與輸入一一對應# [1,1] -> 1, [0,0] -> 0, [1,0] -> 0, [0,1] -> 0labels = [1, 0, 0, 0]return input_vecs, labels def train_and_perceptron():'''使用and真值表訓練感知器'''# 創建感知器,輸入參數個數為2(因為and是二元函數),激活函數為fp = Perceptron(2, f)# 訓練,迭代10輪, 學習速率為0.1input_vecs, labels = get_training_dataset()p.train(input_vecs, labels, 10, 0.1)#返回訓練好的感知器return p if __name__ == '__main__': # 訓練and感知器and_perception = train_and_perceptron()# 打印訓練獲得的權重print and_perception# 測試print '1 and 1 = %d' % and_perception.predict([1, 1])print '0 and 0 = %d' % and_perception.predict([0, 0])print '1 and 0 = %d' % and_perception.predict([1, 0])print '0 and 1 = %d' % and_perception.predict([0, 1])
?
將上述程序保存為perceptron.py文件,通過命令行執行這個程序,其運行結果為:
神奇吧!感知器竟然完全實現了and函數。讀者可以嘗試一下利用感知器實現其它函數。
參考鏈接:https://www.zybuluo.com/hanbingtao/note/433855
轉載于:https://www.cnblogs.com/hechangchun/p/11082898.html
總結
以上是生活随笔為你收集整理的深度学习85—[深度学习] 感知器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: helm istio k8s docke
- 下一篇: JDK1.8中的Stream详解