卷積神經網絡玩游戲?
【前言】直接上代碼是最有效的學習方式。
這篇教程通過由一段簡短的 python 代碼實現的非常簡單的實例來講解 BP 反向傳播算法。
代碼如下:
X = np.array([ [0,0,1],[0,1,1],[1,0,1],[1,1,1] ])
y = np.array([[0,1,1,0]]).T
syn0 = 2*np.random.random((3,4)) - 1
syn1 = 2*np.random.random((4,1)) - 1
for j in xrange(60000):
l1 = 1/(1+np.exp(-(np.dot(X,syn0))))
l2 = 1/(1+np.exp(-(np.dot(l1,syn1))))
l2_delta = (y - l2)*(l2*(1-l2))
l1_delta = l2_delta.dot(syn1.T) * (l1 * (1-l1))
syn1 += l1.T.dot(l2_delta)
syn0 += X.T.dot(l1_delta)
當然,上述程序可能過于簡練了。下面我會將其簡要分解成幾個部分進行探討。
2 層神經網絡:
import numpy as np
# sigmoid function
def nonlin(x,deriv=False):
if(deriv==True):
return x*(1-x)
return 1/(1+np.exp(-x))
# input dataset
X = np.array([ [0,0,1],
[0,1,1],
[1,0,1],
[1,1,1] ])
# output dataset
y = np.array([[0,0,1,1]]).T
# seed random numbers to make calculation
# deterministic (just a good practice)
np.random.seed(1)
# initialize weights randomly with mean 0
syn0 = 2*np.random.random((3,1)) - 1
for iter in xrange(10000):
# forward propagation
l0 = X
l1 = nonlin(np.dot(l0,syn0))
# how much did we miss?
l1_error = y - l1
# multiply how much we missed by the
# slope of the sigmoid at the values in l1
l1_delta = l1_error * nonlin(l1,True)
# update weights
syn0 += np.dot(l0.T,l1_delta)
print "Output After Training:"
print l1
Output After Training:
[[ 0.00966449]
[ 0.00786506]
[ 0.99358898]
[ 0.99211957]]
變量 定義說明
X 輸入數據集,形式為矩陣,每 1 行代表 1 個訓練樣本。
y 輸出數據集,形式為矩陣,每 1 行代表 1 個訓練樣本。
l0 網絡第 1 層,即網絡輸入層。
l1 網絡第 2 層,常稱作隱藏層。
syn0 第一層權值,突觸 0 ,連接 l0 層與 l1 層。
* 逐元素相乘,故兩等長向量相乘等同于其對等元素分別相乘,結果為同等長度的向量。
- 元素相減,故兩等長向量相減等同于其對等元素分別相減,結果為同等長度的向量。
x.dot(y) 若 x 和 y 為向量,則進行點積操作;若均為矩陣,則進行矩陣相乘操作;若其中之一為矩陣,則進行向量與矩陣相乘操作。
正如在“訓練后結果輸出”中看到的,程序正確執行!在描述具體過程之前,我建議讀者事先去嘗試理解并運行下代碼,對算法程序的工作方式有一個直觀的感受。最好能夠在 ipython notebook 中原封不動地跑通以上程序(或者你想自己寫個腳本也行,但我還是強烈推薦 notebook )。下面是對理解程序有幫助的幾個關鍵地方:
對比 l1 層在首次迭代和最后一次迭代時的狀態。
仔細察看 “nonlin” 函數,正是它將一個概率值作為輸出提供給我們。
仔細觀察在迭代過程中,l1_error 是如何變化的。
將第 36 行中的表達式拆開來分析,大部分秘密武器就在這里面。
仔細理解第 39 行代碼,網絡中所有操作都是在為這步運算做準備。有一款軟件做的不錯 阿卡索口語秀 推薦給大家