BP神經網絡Python代碼實現

BP神經網絡模塊bpMoudle.py

#!/usr/bin/env python

import random
import numpy as np

class bpMoudle(object):

    def __init__(self,sizes,trainData,epochs,minTrainNum,eta):
        """
        初始化
        :param sizes: 長度爲神經元層次,元素的值爲該層的神經元數目
        :param trainData: 訓練數據
        :param epochs: 訓練迭代次數
        :param minTrainNum:由於訓練數目太大,所以分割後輪流訓練
        :param eta: 學習率
        """
        self.sizes = sizes
        self.trainData = trainData
        self.epochs = epochs
        self.minTrainNum = minTrainNum
        self.eta = eta
        #神經元層數
        self.layers = len(sizes)
        #初始化偏置和權重,介於0~1
        self.bs = [np.random.randn(i,1) for i in sizes[1:]]
        self.ws = [np.random.randn(i,j) for j,i in zip(sizes[:-1],sizes[1:])]
    #訓練數據
    def train(self):
        """
        訓練模型
        正確率只與權重和偏置有關,故每次訓練其實就是更新權重和偏置,使其更合理以得到更高的正確率
        :return:
        """
        length = len(self.trainData)
        for i in range(self.epochs):
            print("epochs {0}".format(i))
            #爲了讓每次訓練更隨機,打亂訓練集
            random.shuffle(self.trainData)
            trainSmallDatas = [self.trainData[k:k+self.minTrainNum] for k in range(0,length,self.minTrainNum)]
            for trainSmallData in trainSmallDatas:
                #不斷訓練小段數據,更新權重和偏置
                bsTmp,wsTmp = self.countPD(trainSmallData)
                self.ws = [w-(self.eta/len(trainSmallData))*wT
                           for w, wT in zip(self.ws, wsTmp)]
                self.bs = [b-(self.eta/len(trainSmallData))*bT
                               for b, bT in zip(self.bs, bsTmp)]
    #測試數據
    def test(self,testData):

        if testData:
            length = len(testData)
            correctNum = 0
            for (x,y) in testData:
                result = np.argmax(self.forward(x))
                if result == y:
                    correctNum+=1
            print("the accuracy is {0} / {1}".format(correctNum,length))
    #從前往後推
    def forward(self,x):
        for (b,w) in zip(self.bs,self.ws):
            x = self.sigmoid(np.dot(w,x)+b)
        return x

    #求偏導數之和
    def countPD(self,trainSmallData):

        sumBs = [np.zeros(b.shape) for b in self.bs]
        sumWs = [np.zeros(w.shape) for w in self.ws]

        for x,y in trainSmallData:
            bsTmp = [np.zeros(b.shape) for b in self.bs]
            wsTmp = [np.zeros(w.shape) for w in self.ws]
            curValue = x
            curValues = [x]
            values = []
            for b,w in zip(self.bs,self.ws):
                value = np.dot(w,curValue)+b
                values.append(value)
                curValue = self.sigmoid(value)
                curValues.append(curValue)
            delta = (curValues[-1]-y) * self.sigmoidP(values[-1])
            bsTmp[-1] = delta
            wsTmp[-1] = np.dot(delta,curValues[-2].transpose())
            for i in range(2,self.layers):
                value = values[-i]
                sp = self.sigmoidP(value)
                delta = np.dot(self.ws[-i+1].transpose(),delta) * sp
                bsTmp[-i] = delta
                wsTmp[-i] = np.dot(delta,curValues[-i-1].transpose())
            sumBs = [bs+bsT for bs,bsT in zip(sumBs,bsTmp)]
            sumWs = [ws+wsT for ws,wsT in zip(sumWs,wsTmp)]
        return (sumBs,sumWs)

    #激活函數
    def sigmoid(self,value):
        return 1.0/(1.0+np.exp(-value))
    #激活函數求導
    def sigmoidP(self,value):
        return self.sigmoid(value)*(1-self.sigmoid(value))

測試test.py

import pickle
import numpy as np
from netCode import bpMoudle



def translate(num):
    array = np.zeros((10,1))
    array[num] = 1
    return array

if __name__ == '__main__':
    file = open("./data/mnist.pkl","rb")
    trainData,confirmData,testData = pickle.load(file,encoding="bytes")
    file.close()
    training_inputs = [np.reshape(x, (784, 1)) for x in trainData[0]]
    training_results = [translate(y) for y in trainData[1]]
    training_data = list(zip(training_inputs, training_results))

    validation_inputs = [np.reshape(x, (784, 1)) for x in confirmData[0]]
    validation_data = list(zip(validation_inputs, confirmData[1]))

    test_inputs = [np.reshape(x, (784, 1)) for x in testData[0]]
    test_data = list(zip(test_inputs, testData[1]))

    bp = bpMoudle.bpMoudle([784,30,10],training_data,30,10,2.0)
    bp.train()
    bp.test(test_data)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章