训练自己的神经网络
首先定义一个神经网络:
代码如下:
import numpy
import scipy.special
class neuralNetwork:
#类似于java的构造方法,所有方法都有一个self参数,相当于class内部方法都带有this指
#指针一样,指向当前对象
def __init__(self,inodes,hnodes,onodes,learningRate):
self.inode = inodes
self.hnode = hnodes
self.onode = onodes
self.lr = learningRate
#weight link matrice 输入连接数目的根号分之1,均差是0,方差是输入连接数目的
##根号分之1 ,科学家的经验所得,是个正太分布,从概率分布中进行采样,
## 其次是,输入的权重不能相等。因为如果相等,通过误差反向传播之后,权重还##是一样,但是我们训练网络其实是为了每一个神经元逼近事物的各个特征,当然每个##特征不一样的
self.wih = numpy.random.normal(0.0,pow(self.hnode,-0.5),(self.hnode,self.inode))
self.who = numpy.random.normal(0.0,pow(self.onode,-0.5),(self.onode,self.hnode))
## 激活函数采用sigmoid函数,但是这个不是zero-centered,收敛速度慢。
## 激活函数 S(x)就是这个expit(x)
self.activateFunc = lambda x:scipy.special.expit(x)
pass
##训练网络
def train(self,inputList,targetList):
#1 先得到输入数组的转置矩阵
inputs = numpy.array(inputList,ndmin=2).T
# 隐藏层的输入是对ih的矩阵和输入矩阵点乘
hiddenInputs = numpy.dot(self.wih,inputs)
# 隐藏层的输出是经过激活函数非线性化
hiddenOutputs = self.activateFunc(hiddenInputs)
# 隐藏层的输出就是相当于前面的输入信号,最后输出层的输入 是ho权重矩阵和隐藏层的输出做点乘
finalInputs = numpy.dot(self.who,hiddenOutputs)
finalOutputs = self.activateFunc(finalInputs)
## 最后 targetOutputs 是样本值
targetOutputs = numpy.array(targetList,ndmin=2).T
## 输出层的误差
outputErrors = targetOutputs-finalOutputs
## 隐藏层的误差反向传播,是权重矩阵的转置,和输出层的误差矩阵点乘
hiddenErrors = numpy.dot(self.who.T,outputErrors)
##update weight matrice 更新权重矩阵参数
self.wih += self.lr*numpy.dot(hiddenErrors*hiddenOutputs*(1-hiddenOutputs),numpy.transpose(inputs))
self.who += self.lr*numpy.dot(outputErrors*finalOutputs*(1-finalOutputs),numpy.transpose(hiddenOutputs))
pass
## 测试网络
def query(self,inputList):
inputs = numpy.array(inputList,ndmin=2).T
hiddenInputs = numpy.dot(self.wih,inputs)
hiddenOutputs = self.activateFunc(hiddenInputs)
finalInputs = numpy.dot(self.who,hiddenOutputs)
finalOutputs = self.activateFunc(finalInputs)
return finalOutputs
##测试
inputNodes=784
hiddenNodes=100
outputNodes =10
learningRate =0.3
##实例化神经网络
n = neuralNetwork(inputNodes,hiddenNodes,outputNodes,learningRate)
##读取训练数据
trainDataFile =open('E:/neuralNetwork/mnist_train_100.csv',"r")
trainDataList = trainDataFile.readlines()
trainDataFile.close()
##train the data
#go through all data in train set
for record in trainDataList:
allValues = record.split(',')
##scale and shift input data
## 训练数据的归一化,是数据在0.01到1变化
## allValues[0]是标签值,也就是样本值。后面的二进制数据是图片转成二进制的
scaledInputs = (numpy.asfarray(allValues[1:])/255*0.99)+0.01
## create the target output values
##期望输出,其他是0.01 ,样本值对应的索引,是0.99
targets = numpy.zeros(outputNodes)+0.01
targets[int(allValues[0])] =0.99
##每条数据都调用一次训练方法
n.train(scaledInputs,targets)
print("has trained successfully")
##load test data
#
testDataFile =open('E:/neuralNetwork/mnist_test_10.csv',"r")
testDataList = testDataFile.readlines()
testDataFile.close()
firstTestLine = testDataList[0]
testallValues = firstTestLine.split(',')
result = n.query(numpy.asfarray(testallValues[1:])/255*0.99+0.01)
print(result)
scorecard=[]
for record in testDataList:
testAllValues =record.split(',')
correctLabel=int(testAllValues[0])
print(correctLabel,"correct label :")
testInputs = numpy.asfarray(testAllValues[1:])/255*0.99+0.01
testOutputs = n.query(testInputs)
#get the highest value correspond to label
label =numpy.argmax(testOutputs)
print(label,"neuralNetwork answer is ")
if(label ==correctLabel):
scorecard.append(1)
else:
scorecard.append(0)
print(scorecard)
输出结果:数组输出第8位也就是索引7 ,是最大的,那这个图片就是数字
has trained successfully
[[ 0.0439157 ]
[ 0.01209635]
[ 0.00872318]
[ 0.11759458]
[ 0.07145463]
[ 0.01963777]
[ 0.01497414]
[ 0.91942315]
[ 0.03667926]
[ 0.03500161]]
7 correct label :
7 neuralNetwork answer is
2 correct label :
2 neuralNetwork answer is
1 correct label :
1 neuralNetwork answer is
0 correct label :
0 neuralNetwork answer is
4 correct label :
4 neuralNetwork answer is
1 correct label :
1 neuralNetwork answer is
4 correct label :
4 neuralNetwork answer is
9 correct label :
4 neuralNetwork answer is
5 correct label :
1 neuralNetwork answer is
9 correct label :
7 neuralNetwork answer is
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
不管怎么样,后面虽然有错误的,但是我们训练集小才100 条记录。下面我们用60000条记录的训练集训练。
前面神经网络定义都一样,下面的测试不太一样
inputNodes=784
hiddenNodes=100
outputNodes =10
learningRate =0.1
n = neuralNetwork(inputNodes,hiddenNodes,outputNodes,learningRate)
trainDataFile =open('E:/neuralNetwork/mnist_train.csv',"r")
trainDataList = trainDataFile.readlines()
trainDataFile.close()
##train the data
#go through all data in train set
for record in trainDataList:
allValues = record.split(',')
##scale and shift input data
scaledInputs = (numpy.asfarray(allValues[1:])/255*0.99)+0.01
## create the target output values
targets = numpy.zeros(outputNodes)+0.01
targets[int(allValues[0])] =0.99
n.train(scaledInputs,targets)
print("has trained successfully")
##load test data
#
testDataFile =open('E:/neuralNetwork/mnist_test.csv',"r")
testDataList = testDataFile.readlines()
testDataFile.close()
firstTestLine = testDataList[0]
testallValues = firstTestLine.split(',')
result = n.query(numpy.asfarray(testallValues[1:])/255*0.99+0.01)
print(result)
scorecard=[]
for record in testDataList:
testAllValues =record.split(',')
correctLabel=int(testAllValues[0])
testInputs = numpy.asfarray(testAllValues[1:])/255*0.99+0.01
testOutputs = n.query(testInputs)
#get the highest value correspond to label
label =numpy.argmax(testOutputs)
if(label ==correctLabel):
scorecard.append(1)
else:
scorecard.append(0)
scorearray = numpy.asarray(scorecard)
print("records length :",scorearray.size)
print("performance= ",scorearray.sum()/scorearray.size)
最后输出有95%的正确率:
has trained successfully
[[ 0.01576339]
[ 0.00644632]
[ 0.00516604]
[ 0.01209309]
[ 0.00353169]
[ 0.00112428]
[ 0.00835384]
[ 0.98973284]
[ 0.00217241]
[ 0.00417368]]
records length : 10000
performance= 0.95
接下来我们改变学习率,看一下对正确率有什么变化
import matplotlib.pylab as pyl
import numpy as np
## 定义画散点图的函数
def draw_scatter():
x1=[]
y1=[]
dataFile =open('E:/neuralNetwork/lr.csv',"r")
dataList = dataFile.readlines()
dataFile.close()
for record in dataList:
allValues = record.split(',')
x1.append(allValues[0])
y1.append(allValues[1])
print(x1)
print(y1)
pyl.plot(x1,y1,'ob')
pyl.title("learningRate--->precision")
pyl.xlabel("learningRate")
pyl.ylabel("precision")
pyl.ylim(0.9100,0.9500)
pyl.xlim(0.00,0.70)
pyl.show()
draw_scatter()
输出结果:
['0.3', '0.4', '0.5', '0.6', '0.2', '0.1', '0.05', '0.01']
['0.9463\n', '0.9363\n', '0.9229\n', '0.9135\n', '0.9472\n', '0.9498\n', '0.9487\n', '0.9209\n']
当学习率在0.1的时候有个峰值。随着学习率的 增加,准确率反而下降了。