9行Python代碼搭建神經網路

原文:How to build a simple neural network in 9 lines of Python code

作者:Milo Spencer-Harper

翻譯:Kaiser(王司圖)

代碼可調版本:9行Python代碼搭建神經網路 - 集智專欄

前言

在上一篇文章中,Milo給自己定下了兩個小目標:

  1. 學習層次隱式馬爾可夫模型
  2. 用Python搭建神經網路

本文講的就是他如何實現第二個目標。當然,這裡的「用Python」指的就是不用那些現成的神經網路庫比如Keras、Tensorflow等,否則連9行都不用了。

正文

(Kaiser: 程序的輸出結果可在集智專欄文章中點擊運行按鈕在線執行,也可以自由編輯代碼,重新定義神經網路。)

本文我會解釋這個神經網路是怎樣煉成的,所以你也可以搭建你自己的神經網路。也會提供一個加長版、但是也更漂亮的源代碼。

不過首先,什麼是神經網路?人腦總共有超過千億個神經元細胞,通過神經突觸相互連接。如果一個神經元被足夠強的輸入所激活,那麼它也會激活其他神經元,這個過程就叫「思考」。

我們可以在計算機上創建神經網路,來對這個過程進行建模,且並不需要模擬分子級的生物複雜性,只要觀其大略即可。為了簡化起見,我們只模擬一個神經元,含有三個輸入和一個輸出。

我們將訓練這個神經元來解決下面這個問題,前四個樣本叫作「訓練集」,你能求解出模式嗎?"?"處應該是0還是1呢?

或許你已經發現了,輸出總是與第一列的輸入相等,所以?應該是1。

訓練過程

問題雖然很簡單,但是如何教會神經元來正確的回答這個問題呢?我們要給每個輸入賦予一個權重,權重可能為正也可能為負。權重的絕對值,代表了輸入對輸出的決定權。在開始之前,我們先把權重設為隨機數,再開始訓練過程:

  1. 從訓練集樣本讀取輸入,根據權重進行調整,再代入某個特殊的方程計算神經元的輸出。

  2. 計算誤差,也就是神經元的實際輸出和訓練樣本的期望輸出之差。

  3. 根據誤差的方向,微調權重。

  4. 重複10000次。

最終神經元的權重會達到訓練集的最優值。如果我們讓神經元去思考一個新的形勢,遵循相同過程,應該會得到一個不錯的預測。

計算神經元輸出的方程

你可能會好奇,計算神經元輸出的人「特殊方程」是什麼?首先我們取神經元輸入的加權總和:

sum weight_i cdot input_i = weight_1 cdot input_1 + weight_2 cdot input_2 + weight_3 cdot input_3

接下來我們進行正規化,將結果限制在0和1之間。這裡用到一個很方便的函數,叫Sigmoid函數:

frac{1}{1+e^{-x}}

如果繪出圖像,Sigmoid函數是S形的曲線:

將第一個公式代入第二個,即得最終的神經元輸出方程:

Output of neuron = frac{1}{1 + e^{-(sum weight_i cdot input_i)}}

調整權重的方程

在訓練進程中,我們需要調整權重,但是具體如何調整呢?就要用到「誤差加權導數」方程:

Adjust weights by = error cdot input cdot SigmoidCurveGradient(output)

為什麼是這個方程?首先我們希望調整量與誤差量成正比,然後再乘以輸入(0-1)。如果輸入為0,那麼權重就不會被調整。最後乘以Sigmoid曲線的梯度,為便於理解,請考慮:

  1. 我們使用Sigmoid曲線計算神經元輸出。

  2. 如果輸出絕對值很大,這就表示該神經元是很確定的(有正反兩種可能)。

  3. Sigmoid曲線在絕對值較大處的梯度較小。

  4. 如果神經元確信當前權重值是正確的,那麼就不需要太大調整。乘以Sigmoid曲線的梯度可以實現。

Sigmoid曲線的梯度可由導數獲得:

SigmoidCurveGradient(output) = output cdot (1 - output)

代入公式可的最終的權重調整方程:

Adjust weights by = error cdot input cdot output cdot (1 - output)

實際上也有其他讓神經元學習更快的方程,這裡主要是取其相對簡單的優勢。

構建Python代碼

儘管我們不直接用神經網路庫,但還是要從Python數學庫Numpy中導入4種方法:

  • exp: 自然對常數
  • array: 創建矩陣
  • dot:矩陣乘法
  • random: 隨機數

比如我們用array()方法代表訓練集:

training_set_inputs = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]])training_set_outputs = array([[0, 1, 1, 0]]).T

.T函數就是矩陣轉置。我想現在可以來看看美化版的源代碼了,最後我還會提出自己的終極思考。源代碼中已經添加了注釋逐行解釋。注意每次迭代我們都一併處理了整個訓練集,以下為完整的Python示例:

終極思考

(Kaiser:原文講的是將代碼寫入本地main.py文件,再在終端中運行python main.py,這裡只需點擊運行即可。)

我們用Python打造了一個簡單的神經網路。

首先神經網路給自己賦予隨機的權重值,然後用訓練集訓練自己,最後去思考新的形勢[1 0 0]並預測了0.99993704,這與正確答案非常接近。

傳統的計算機程序無法學習,神經網路的最大魅力就在於學習能力,可以自主適應新形勢,就像人的心智一樣。當然,僅僅一個神經元只能完成特別簡單的人物,但如果我們把上百萬個如此的神經元連接起來呢?能否有朝一日製造出具有自我意識的東西?

下一篇文章中,我將繼續加入第二層神經元,來拓展神經網路。

QQ群:557373801

投稿或加入微信群:請聯繫客服,微信ID: jizhi_im


推薦閱讀:

M.1.0 神經網路的數學基礎-前言
神經網路反向傳播的數學原理

TAG:Python | 神经网络 | 深度学习DeepLearning |