运行环境:python3.6
以下是定义一个神经网络类,其中包含神经网络的初始化函数,训练神经网络函数和利用神经网络输出结果的函数
import numpy
import scipy.special
import matplotlib.pyplot
# 定义神经网络类
class neuralNetwork:
# 初始化函数,设定输入层节点,隐藏层节点和输出层节点数量
def __init__(self,inputNodes,hiddenNodes,outputNodes,learningRate):
# 依次设置输入,隐藏,输出节点的值
self.iNodes = inputNodes
self.hNodes = hiddenNodes
self.oNodes = outputNodes
# 设置学习率
self.lr = learningRate
# 设置神经网络的权重矩阵
# rand(行数,列数),权重矩阵中,行数:后者决定,列数:前者决定,如果计算inputNodes和hiddenNodes的权重矩阵,那么i为前者,h为后者
# 以下是简单的随机初始化权重矩阵
#self.weights_ih = numpy.random.rand(self.hNodes,self.iNodes) - 0.5
#self.weights_ho = numpy.random.rand(self.oNodes,self.oNodes) - 0.5
# 以下是正态分布的随机初始化权重矩阵
self.weights_ih = numpy.random.normal(0.0,pow(self.hNodes, -0.5),(self.hNodes,self.iNodes))
self.weights_ho = numpy.random.normal(0.0,pow(self.oNodes, -0.5),(self.oNodes,self.hNodes))
# 定义激活函数(S函数)
self.activation_function = lambda x: scipy.special.expit(x)
pass
# 网络训练函数,学习给定训练集样本后,优化权重
def train(self,inputs_list,targets_list):
# 将输入数据的list和目标数据的list转换为矩阵
inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list,ndmin=2).T
# hidden层的输入数据
hidden_inputs = numpy.dot(self.weights_ih, inputs)
# hidden层的输出数据
hidden_outputs = self.activation_function(hidden_inputs)
# 最后输出层的输入数据
final_inputs = numpy.dot(self.weights_ho, hidden_outputs)
# 最后输出层的输出数据
final_outputs = self.activation_function(final_inputs)
# 计算输出结果的误差,(目标数据-实际输出数据)
output_errors = targets - final_outputs
# 将输出结果的误差反向传播到hidden层,weights_hidden_output(反转)×errors_output
hidden_errors = numpy.dot(self.weights_ho.T,output_errors)
# 这样就会得到2个误差矩阵(hidden_errors和output_errors),2个权重矩阵(weights_ih和weights_ho),然后根据公式计算每个权重需要调节的量
# 调节量公式: W_j_k =(学习率 × E_k * sigmoid(O_k) * (1-sigmoid(O_k)) ) * O_j(矩阵反转)
self.weights_ho += self.lr * numpy.dot((output_errors * final_outputs * (1 - final_outputs)),numpy.transpose(hidden_outputs))
self.weights_ih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1 - hidden_outputs)),numpy.transpose(inputs))
pass
# 查询函数,给定输入,从输出节点给出答案
def query(self,inputs_list):
# 将传入的list转换成矩阵
inputs = numpy.array(inputs_list,ndmin=2).T
# hidden层的输入数据
hidden_inputs = numpy.dot(self.weights_ih,inputs)
# hidden层的输出数据
hidden_outputs = self.activation_function(hidden_inputs)
# 最后输出层的输入数据
final_inputs = numpy.dot(self.weights_ho,hidden_outputs)
# 最后输出层的输出数据
final_outputs = self.activation_function(final_inputs)
return final_outputs
以下是主函数中的一些初始化参数的设定
input_nodes是输入节点数,因为本次是识别28×28的图像,所以使用了784个节点,也就是784个像素作为输入参数
hidden_nodes是中间层的节点数,该节点数可以根据不同的目的调节参数值,以达到最优解
output_nodes是输出节点,因为本次是识别图像中的数字,所以0-9一共10个数字,设置了10个节点数,最终输出结果会在这10个节点中正确结果的权重
# 设置输入,隐藏,输出层节点数
input_nodes = 784
hidden_nodes = 500
output_nodes = 10
# 设置学习率
learning_rate = 0.1
# 创建神经网络实例
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes,learning_rate)
# 训练神经网络
# 读取训练数据文件中的数据,并保存到列表中
training_data_file = open("E://mnist_train_100.csv",'r')
training_data_list = training_data_file.readlines()
training_data_file.close()
以下是主函数中训练神经网络的代码
for records in training_data_list:
# 将训练数据列表中的第一个数据切割并转换成列表
all_values = records.split(',')
# 将训练数据的数值按比例缩小到0-1的范围内,经过乘以0.99后加0.01的处理后,编程0.01-0.99的数据
inputs = (numpy.asfarray(all_values[1:]) / 255 * 0.99) + 0.01
# 使用0填充长度为target_nodes的数组,并将其中所有值+0.01
targets = numpy.zeros(output_nodes) + 0.01
# 将训练数据中第一个值(训练数据的正确结果)对应的位置的值改为0.99
targets[int(all_values[0])] = 0.99
# 训练
n.train(inputs, targets)
以下是主函数中测试神经网络的代码
# 测试神经网络
# 读取测试数据
test_data_file = open("E://mnist_test_10.csv",'r')
test_data_list = test_data_file.readlines()
test_data_file.close()
# 单个实例与图片对比
all_values = test_data_list[2].split(',')
# 正确的数字
correct_label = all_values[0]
# 整理格式化输入列表
inputs = (numpy.asfarray(all_values[1:]) / 255 * 0.99) +0.01
# 获取输出结果
outputs = n.query(inputs)
# 从输出结果中获取标记出来的数字
label = numpy.argmax(outputs)
print(outputs)
print("图像中的数字是:",label)
#绘制手写数字的图像
image_array = numpy.asfarray(all_values[1:]).reshape(28,28)
matplotlib.pyplot.imshow(image_array,cmap='Greys',interpolation='None')
matplotlib.pyplot.show()
以下为最终的结果,可以看到,神经网络输出的结果集(从0开始,9是最后一个数)中,第二个数的权重(0.01-0.99)最大,所以最后结果是数字1
备注:所有的训练数据和测试数据都是已经转换好的由像素数值组成的列表,如果要直接用图像去测试的话,需要导入scipy.misc模块中的imread()方法来获取图像中的像素列表,使用方法如下:
img_array = scipy.misc.imread(image_file_name , flatten = True)
img_data = 255.0 - img_array.reshape(784)
训练数据和测试数据可以从以下网址获取:(如果打开后直接显示具体数据,可以右键点击然后另存为文件)
https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_test_10.csv 该链接是10条测试数据的记录
https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_train_100.csv 该链接是100条训练数据的记录
http://www.pjreddie.com/media/files/mnist_test.csv 该链接是完整测试数据 约10000个标记样本
http://www.pjreddie.com/media/files/mnist_train.csv 该链接是完整训练数据 约60000个标记样本