1. 程式人生 > >機器學習與神經網路(四):BP神經網路的介紹和Python程式碼實現

機器學習與神經網路(四):BP神經網路的介紹和Python程式碼實現

前言:本篇博文主要介紹BP神經網路的相關知識,採用理論+程式碼實踐的方式,進行BP神經網路的學習。本文首先介紹BP神經網路的模型,然後介紹BP學習演算法,推導相關的數學公式,最後通過Python程式碼實現BP演算法,從而給讀者一個更加直觀的認識。

1.BP網路模型

為了將理論知識描述更加清晰,這裡還是引用《人工神經網路理論、設計及應用_第二版》相關的介紹。特別提醒一點:理解BP神經網路,最好提前閱讀“感知器”的相關知識,相關資料可以檢視前面的博文介紹。


以上公式都極其重要,因為我們將會在程式碼中用到他們,所以請理解並且牢記他們。

2.BP學習演算法

BP學習演算法是理解BP神經網路的核心內容,他解釋了神經網路如何有效的去進行學習和權值調整。有興趣的同學我希望可以認真閱讀以下公式的推導(雖然看著嚇人,但是並不是很難),這樣能夠更加深入的理解。當然,如果你想偷個懶,那你只要記住公式3.21a和3.21b、3.22a和3.22b

及其含義就可以用程式碼實現它了,當然,千萬別忘了前面剛剛學習的公式3.6-3.11




3.BP神經網路的Python程式碼實現

以下程式碼的編寫語言採用Python2.7版本,編譯環境建議採用Anaconda,因為他自帶了很多Python相關的包,非常方便。

下面的程式實現了一個圖片上數字的識別功能:

首先我們看一下相關資料集的內容:

#! /usr/bin/env python
#coding=utf-8
from sklearn.datasets import load_digits#資料集
from sklearn.preprocessing import LabelBinarizer#標籤二值化
from sklearn.cross_validation import train_test_split#資料集分割
import numpy as np
import pylab as pl#資料視覺化
digits = load_digits()#載入資料
print digits.data.shape#列印資料集大小(1797L, 64L)

pl.gray()#灰度化圖片
pl.matshow(digits.images[0])#顯示第1張圖片,上面的數字是0
pl.show()

執行結果如下:


這裡做一下說明,這個資料集大小為(1797,64),表示的是有1797張圖片樣本,其中的64,表示的是每一個樣本包含64個特徵,也就是上述圖片所示,將8*8的矩陣排成一行,即64列。

接下來我們實現BP神經網路:

#! /usr/bin/env python
#coding=utf-8
from sklearn.datasets import load_digits#資料集
from sklearn.preprocessing import LabelBinarizer#標籤二值化
from sklearn.cross_validation import train_test_split#資料集分割
import numpy as np

import pylab as pl#資料視覺化

def sigmoid(x):#啟用函式
    return 1/(1+np.exp(-x))

def dsigmoid(x):#sigmoid的倒數
    return x*(1-x)


class NeuralNetwork:
    def __init__(self,layers):#這裡是三層網路,列表[64,100,10]表示輸入,隱藏,輸出層的單元個數
        #初始化權值,範圍1~-1
        self.V=np.random.random((layers[0]+1,layers[1]))*2-1#隱藏層權值(65,100),之所以是65,因為有偏置W0
        self.W=np.random.random((layers[1],layers[2]))*2-1#(100,10)
        
    def train(self,X,y,lr=0.1,epochs=10000):
	#lr為學習率,epochs為迭代的次數
        #為資料集新增偏置
        temp=np.ones([X.shape[0],X.shape[1]+1])
        temp[:,0:-1]=X
        X=temp#這裡最後一列為偏置
        
        #進行權值訓練更新
        for n in range(epochs+1):
            i=np.random.randint(X.shape[0])#隨機選取一行資料(一個樣本)進行更新
            x=X[i]
            x=np.atleast_2d(x)#轉為二維資料
            
            L1=sigmoid(np.dot(x,self.V))#隱層輸出(1,100)
            L2=sigmoid(np.dot(L1,self.W))#輸出層輸出(1,10)
            
            #delta
            L2_delta=(y[i]-L2)*dsigmoid(L2)#(1,10)
            L1_delta=L2_delta.dot(self.W.T)*dsigmoid(L1)#(1,100),這裡是陣列的乘法,對應元素相乘
            
            #更新
            self.W+=lr*L1.T.dot(L2_delta)#(100,10)
            self.V+=lr*x.T.dot(L1_delta)#
            
            #每訓練1000次預測準確率
            if n%1000==0: 
                predictions=[]
                for j in range(X_test.shape[0]):
                    out=self.predict(X_test[j])#用驗證集去測試
                    predictions.append(np.argmax(out))#返回預測結果
                accuracy=np.mean(np.equal(predictions,y_test))#求平均值
                print('epoch:',n,'accuracy:',accuracy)
    
    def predict(self,x):
        #新增轉置,這裡是一維的
        temp=np.ones(x.shape[0]+1)
        temp[0:-1]=x
        x=temp
        x=np.atleast_2d(x)
        
        L1=sigmoid(np.dot(x,self.V))#隱層輸出
        L2=sigmoid(np.dot(L1,self.W))#輸出層輸出
        return L2


digits=load_digits()#載入資料
X=digits.data#資料

y=digits.target#標籤
#print y[0:10]

#資料歸一化,一般是x=(x-x.min)/x.max-x.min
X-=X.min()
X/=X.max()

#建立神經網路
nm=NeuralNetwork([64,100,10])

X_train,X_test,y_train,y_test=train_test_split(X,y)#預設分割:3:1

#標籤二值化
labels_train=LabelBinarizer().fit_transform(y_train)
#print labels_train[0:10]
labels_test=LabelBinarizer().fit_transform(y_test)

print 'start'

nm.train(X_train,labels_train,epochs=20000)

print 'end'

執行結果:

總結:本博文首先介紹了BP神經網路模型(3層神經網路為例),然後介紹BP學習演算法以及公式推導,最後通過Python程式碼實現演算法原理。當然,網上有一個非常典型的BP神經網路實現的例子:一個11行Python程式碼實現的神經網路,有興趣的可以學習一下。

ps:如有錯誤之處,還請指正。