python實現神經網絡
聲明:本文是 A Neural Network in 11 lines of Python 學習總結而來,關于更詳細的神經網絡的介紹可以參考從感知機到人工神經網絡。
如果你讀懂了下面的文章,你會對神經網絡有跟深刻的認識,有任何問題,請多多請教
Very simple Neural Network
首先確定我們要實現的任務:
輸出的為樣本為
為4*3,有4個樣本3個屬性,每一個樣本對于這一個真實值y,為4*1的向量,我們要根據input的值輸出與y值損失最小的輸出。
Two Layer Neural Network:
首先考慮最簡單的神經網絡,如下圖所示:
輸入層有3個神經元(因為有3個屬性),輸出為一個值,w1,w2,w3為其權重。輸出為:
( w 1 ? x 1 + w 2 ? x 2 + w 3 ? x 3 )
這里的f為sigmoid函數:
( x ) = 1 1 + e ? x
一個重要的公式:
( x ) x = ( x ) ( 1 ? ( x ) )
神經網絡的優化過程是:
1. 前向傳播求損失
2. 反向傳播更新w
簡單是實現過程如下所示:
import numpy as np # sigmoid function # deriv=ture 是求的是導數 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], [1,1,1], [1,0,1], [0,1,1] ]) # output dataset y = np.array([[0,1,1,0]]).T # seed random numbers to make calculation 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也就是輸入層 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
注意這里整體計算了損失,X(4*3) dot w(3*1) = 4*1為輸出的4個值,所以
l1_error = y - l1 同樣為一個4*1的向量。
重點理解:
# slope of the sigmoid at the values in l1 #nonlin(l1,True),這里是對sigmoid求導 #前向計算,反向求導 l1_delta = l1_error * nonlin(l1,True) # update weights syn0 += np.dot(l0.T,l1_delta)
下面看一個單獨的訓練樣本的情況,真實值y==1,訓練出來的為0.99已經非常的接近于正確的值了,因此這時應非常小的改動 syn0 的值,因此:
w e i h t _ u p a t e = i n p u t _ v a l u e ? l 1 _ e l t a
運行輸出結果為,可以看到其訓練的不錯:
Output After Training: Output After Training: [[ 0.00966449] [ 0.99211957] [ 0.99358898] [ 0.00786506]]
Three Layer Neural Network:
我們知道,兩層的神經網絡即為一個小的感知機(參考:感知機到人工神經網絡),它只能出來線性可分的數據,如果線性不可分,則其出來的效果較差,如下圖所示的數據:
如果仍用上述的代碼(2層的神經網絡)則其結果為:
Output After Training: [[ 0.5] [ 0.5] [ 0.5] [ 0.5]]
因為數據并不是線性可分的,因此它是一個非線性的問題,神經網絡的強大之處就是其可以搭建更多的層來對非線性的問題進行處理。
下面我將搭建一個含有5個神經元的隱含層,其圖形如下,(自己畫的,略丑),這來要說下神經網絡其實很簡單,只要你把層次的結果想清楚。
要搞清楚w的維度:第一層到第二層的w為3*5,第二層到第三層的W為5*1,因此還是同樣的兩個步驟,前向計算誤差,然后反向求導更新w。
完整的代碼如下:
import numpy as np def nonlin(x,deriv=False): if(deriv==True): return x*(1-x) return 1/(1+np.exp(-x)) X = np.array([[0,0,1], [0,1,1], [1,0,1], [1,1,1]]) y = np.array([[0], [1], [1], [0]]) np.random.seed(1) # randomly initialize our weights with mean 0 syn0 = 2*np.random.random((3,5)) - 1 syn1 = 2*np.random.random((5,1)) - 1 for j in xrange(60000): # Feed forward through layers 0, 1, and 2 l0 = X l1 = nonlin(np.dot(l0,syn0)) l2 = nonlin(np.dot(l1,syn1)) # how much did we miss the target value? l2_error = y - l2 if (j% 10000) == 0: print "Error:" + str(np.mean(np.abs(l2_error))) # in what direction is the target value? # were we really sure? if so, don't change too much. l2_delta = l2_error*nonlin(l2,deriv=True) # how much did each l1 value contribute to the l2 error (according to the weights)? l1_error = l2_delta.dot(syn1.T) # in what direction is the target l1? # were we really sure? if so, don't change too much. l1_delta = l1_error * nonlin(l1,deriv=True) syn1 += l1.T.dot(l2_delta) syn0 += l0.T.dot(l1_delta) print l2
運行的結果為:
Error:0.500628229093 Error:0.00899024507125 Error:0.0060486255435 Error:0.00482794013965 Error:0.00412270116481 Error:0.00365084766242 # 這一部分是最后的輸出結果 [[ 0.00225305] [ 0.99723356] [ 0.99635205] [ 0.00456238]]
如果上面的代碼看懂了,那么你就可以自己搭建自己的神經網絡了,無論他是多少層,或者每個層有多少個神經元,都能很輕松的完成。當然上面搭建的神經網絡只是一個很簡單的網絡,同樣還有許多的細節需要學習,比如說反向傳回來的誤差我們可以用 隨機梯度下降的方法去更新W ,同時還可以加上 偏置項b ,還有 學習率 α
等問題。
來自:http://blog.csdn.net/taoyanqi8932/article/details/54575405