python神经网络编程之手写数字识别

写在之前

首先是写在之前的一些建议:

首先是关于这本书,我真的认为他是将神经网络里非常棒的一本书,但你也需要注意,如果你真的想自己动手去实现,那么你一定需要有一定的python基础,并且还需要有一些python数据科学处理能力

然后希望大家在看这边博客的时候对于神经网络已经有一些了解了,知道什么是输入层,什么是输出层,并且明白他们的一些理论,在这篇博客中我们仅仅是展开一下代码;

然后介绍一下本篇博客的环境等:

语言:Python3.8.5

环境:jupyter

库文件: numpy | matplotlib | scipy

一、代码框架

我们即将设计一个神经网络对象,它可以帮我们去做数据的训练,以及数据的预测,所以我们将具有以下的三个方法:

首先我们需要初始化这个函数,我们希望这个神经网络仅有三层,因为再多也不过是在隐藏层去做文章,所以先做一个简单的。那么我们需要知道我们输入层、隐藏层和输出层的节点个数;训练函数,我们需要去做训练,得到我们需要的权重。通过我们已有的权重,将给定的输入去做输出。

二、准备工作

现在我们需要准备一下:

1.将我们需要的库导入

123import numpy as npimport scipy.special as speimport matplotlib.pyplot as plt

2.构建一个类

12345678910111213class neuralnetwork:# 我们需要去初始化一个神经网络 def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):pass  def train(self, inputs_list, targets_list):pass  def query(self, inputs_list):pass

3.我们的主函数

1234567input_nodes = 784    # 输入层的节点数hidden_nodes = 88    # 隐藏层的节点数output_nodes = 10    # 输出层的节点数 learn_rate = 0.05    # 学习率 n = neuralnetwork(input_nodes, hidden_nodes, output_nodes, learn_rate)

4.导入文件

123456data_file = open("E:\sklearn_data\神经网络数字识别\mnist_train.csv", 'r')data_list = data_file.readlines()data_file.close()file2 = open("E:\sklearn_data\神经网络数字识别\mnist_test.csv")answer_data = file2.readlines()file2.close()

这里需要介绍以下这个数据集,训练集在这里,测试集在这里

三、框架的开始

1234567891011def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate): self.inodes = inputnodes   # 输入层节点设定self.hnodes = hiddennodes  # 影藏层节点设定self.onodes = outputnodes  # 输出层节点设定 self.lr = learningrate     # 学习率设定,这里可以改进的 self.wih = (np.random.normal(0.0, pow(self.hnodes, -0.5),(self.hnodes, self.inodes))) # 这里是输入层与隐藏层之间的连接self.who = (np.random.normal(0.0, pow(self.onodes, -0.5),(self.onodes, self.hnodes))) # 这里是隐藏层与输出层之间的连接self.activation_function = lambda x: spe.expit(x)           # 返回sigmoid函数

Δw j,k ​ =α∗E k ​ ∗ sigmoid (O k ​ )∗(1−sigmoid(O k ​ ))⋅O j ⊤

123456789def query(self, inputs_list):inputs = np.array(inputs_list, ndmin=2).T # 输入进来的二维图像数据 hidden_inputs = np.dot(self.wih, inputs)  # 隐藏层计算,说白了就是线性代数中的矩阵的点积hidden_outputs = self.activation_function(hidden_inputs) # 将隐藏层的输出是经过sigmoid函数处理final_inputs = np.dot(self.who, hidden_outputs) # 原理同hidden_inputsfinal_outputs = self.activation_function(final_inputs) # 原理同hidden_outputs  return final_outputs # 最终的输出结果就是我们预测的数据

这里我们对预测这一部分做一个简单的解释:我们之前的定义输出的节点是10个,对应的是十个数字。
而为什么会通过神经网络能达到这个亚子,我推荐这本书深度学习的数学 这本书的理论讲解非常不错!!!

python客栈送红包、纸质书

四、训练模型构建

之前的部分相对而言还是比较简单的,那么接下来就是如何去构建训练模型了。

1234567891011121314151617181920def train(self, inputs_list, targets_list):# 前期和识别过程是一样的,说白了我们与要先看看现在的预测结果如何,只有根据这次的预期结果才能去修改之前的权重inputs = np.array(inputs_list, ndmin=2).T hidden_inputs = np.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = np.dot(self.who, hidden_outputs)final_outputs = self.activation_function(final_inputs) # 接下来将标签拿迟来targets = np.array(targets_list, ndmin=2).T # 得到我们的数据预测的误差,这个误差将是向前反馈的基础output_errors = targets - final_outputs# 这部分是根据公式得到的反向传播参数hidden_errors = np.dot(self.who.T, output_errors) # 根据我们的反馈参数去修改两个权重self.who += self.lr * np.dot((output_errors * final_outputs * ( 1.0-final_outputs)), np.transpose(hidden_outputs))self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0-hidden_outputs)), np.transpose(inputs))

如此我们的基础神经网络构建完成了。

五、手写数字的识别

接下来神经网络是完成的,那么我们究竟该如何去将数据输入呢?
csv文件我们并不陌生【或许陌生?】,他是逗号分割文件,顾名思义,它是通过逗号分隔的,所以我们可以打开看一下:

在这里插入图片描述

眼花缭乱!!

但是细心的我们可以发现他的第一个数字都是0~9,说明是我们的标签,那么后面的应该就是图像了,通过了解我们知道这个后面的数据是一个28*28的图像。

123all_value = data_list[0].split(',') # split分割成列表image_array = np.asfarray(all_value[1:]).reshape((28,28)) # 将数据reshape成28*28的矩阵plt.imshow(image_array, cmap='Greys', interpolation='None') # 展示一下

通过这段代码,我们可以简单的看一下每个数字是什么:

在这里插入图片描述

很好,知道这里就足够了,那么我们接下来就是将这些数据传入了!

我们在训练的时候,需要将他们都转化成数字列表,方便处理

12345678910111213141516171819202122232425data = []     # 用来保存训练过程的数据sum_count = 0 # 统计总识别的正确的个数for i in range(15): # 训练的轮数count = 0         # 单次训练识别正确的个数for j in range(len(data_list)):   # 对60000张图片开始训练, 没有划分数据集的过程主要是别人直接给了,我也懒得自己去做了,主要就是展示一下神经网络嘛~target = np.zeros(10)+0.01 # 生成初始标签集合,用来和结果对比line_ = data_list[j].split(',')    # 对每一行的数据处理切割imagearray = np.asfarray(line_)  # 将切割完成的数据转换成数字列表target[int(imagearray[0])] = 1.0    # 将正确答案挑出来n.train(imagearray[1:]/255*0.99+0.01, target) # 丢入训练,丢入的时候注意将数据转换成0.01~1.0之间的结果for line in answer_data: # 对10000组测试集测试all_values = line.split(',')answer = n.query((np.asfarray(all_values[1:])/255*0.99)+0.01)if answer[int(all_values[0])] > 0.85# 查看对应位置是否达到自定义的阈值?count += 1sum_count += countstring = "训练进度 %05f\n本轮准确度 %05f\n总准确度 %05f\n\n"%(i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1)))data.append([i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1))])  # 将数据保存方便生成训练曲线print(string)```接下来我们将结果图片展示以下吧~ ```pythondata = np.array(data)plt.plot(range(len(data)), data[:, 1:])
在这里插入图片描述

六、源码

把源码整理一下贴出来

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687import numpy as npimport scipy.special as speimport matplotlib.pyplot as plt class neuralnetwork:# 我们需要去初始化一个神经网络 def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate): self.inodes = inputnodesself.hnodes = hiddennodesself.onodes = outputnodes self.lr = learningrate self.wih = (np.random.normal(0.0, pow(self.hnodes, -0.5),(self.hnodes, self.inodes)))self.who = (np.random.normal(0.0, pow(self.onodes, -0.5),(self.onodes, self.hnodes)))self.activation_function = lambda x: spe.expit(x)           # 返回sigmoid函数  def train(self, inputs_list, targets_list):inputs = np.array(inputs_list, ndmin=2).T hidden_inputs = np.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = np.dot(self.who, hidden_outputs)final_outputs = self.activation_function(final_inputs) targets = np.array(targets_list, ndmin=2).Toutput_errors = targets - final_outputshidden_errors = np.dot(self.who.T, output_errors) self.who += self.lr * np.dot((output_errors * final_outputs * ( 1.0-final_outputs)), np.transpose(hidden_outputs))self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0-hidden_outputs)), np.transpose(inputs))  def query(self, inputs_list):inputs = np.array(inputs_list, ndmin=2).T hidden_inputs = np.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = np.dot(self.who, hidden_outputs)final_outputs = self.activation_function(final_inputs) return final_outputs  input_nodes = 784hidden_nodes = 88output_nodes = 10 learn_rate = 0.05 n = neuralnetwork(input_nodes, hidden_nodes, output_nodes, learn_rate) data_file = open("E:\sklearn_data\神经网络数字识别\mnist_train.csv", 'r')data_list = data_file.readlines()data_file.close()file2 = open("E:\sklearn_data\神经网络数字识别\mnist_test.csv")answer_data = file2.readlines()file2.close() data = [] sum_count = 0for i in range(15):count = 0for j in range(len(data_list)):target = np.zeros(10)+0.01line_ = data_list[j].split(',')imagearray = np.asfarray(line_)target[int(imagearray[0])] = 1.0n.train(imagearray[1:]/255*0.99+0.01, target)for line in answer_data:all_values = line.split(',')answer = n.query((np.asfarray(all_values[1:])/255*0.99)+0.01)if answer[int(all_values[0])] > 0.85:count += 1sum_count += countstring = "训练进度 %05f\n本轮准确度 %05f\n总准确度 %05f\n\n"%(i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1)))data.append([i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1))])print(string)  data = np.array(data) plt.plot(range(len(data)), data[:, 1:])

可以说是相对简单的一个程序,但却是包含着神经网络最基础的思想!值得好好康康~

七、思考

如何识别其他手写字体等?

我的想法:通过图像处理,将像素规定到相近大小【尺度放缩】

图像大小运行速度问题

我的想法:如何快速的矩阵运算,通过C语言是否可以加速?相较于darknet这个神经网络仅有三层,运算速度并不是十分理想。当然cuda编程对于GPU加速肯定是最好的选择之一。

到此这篇关于python神经网络编程之手写数字识别的文章就介绍到这了,更多相关python手写数字识别内容请搜索kinponet家以前的文章或继续浏览下面的相关文章希望大家以后多多支持kinponet!

原创文章,作者:Zhu, Yuanyuan,如若转载,请注明出处:https://www.yidc.net/archives/16799