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)