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


Posted in Python onMay 08, 2021

写在之前

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

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

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

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

语言:Python3.8.5

环境:jupyter

库文件: numpy | matplotlib | scipy

一、代码框架

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

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

二、准备工作

现在我们需要准备一下:

1.将我们需要的库导入

import numpy as np
import scipy.special as spe
import matplotlib.pyplot as plt

2.构建一个类

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

3.我们的主函数

input_nodes = 784    # 输入层的节点数
hidden_nodes = 88    # 隐藏层的节点数
output_nodes = 10    # 输出层的节点数

learn_rate = 0.05    # 学习率

n = neuralnetwork(input_nodes, hidden_nodes, output_nodes, learn_rate)

4.导入文件

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()

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

三、框架的开始

def __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 ⊤

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) # 将隐藏层的输出是经过sigmoid函数处理
        final_inputs = np.dot(self.who, hidden_outputs) # 原理同hidden_inputs
        final_outputs = self.activation_function(final_inputs) # 原理同hidden_outputs 
        
        return final_outputs # 最终的输出结果就是我们预测的数据

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

四、训练模型构建

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

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).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文件我们并不陌生【或许陌生?】,他是逗号分割文件,顾名思义,它是通过逗号分隔的,所以我们可以打开看一下:

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

眼花缭乱!!

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

all_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') # 展示一下

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

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

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

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

data = []     # 用来保存训练过程的数据
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 += 1
    sum_count += count
    string = "训练进度 %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)
    ```
接下来我们将结果图片展示以下吧~

```python
data = np.array(data)
plt.plot(range(len(data)), data[:, 1:])

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

六、源码

把源码整理一下贴出来

import numpy as np
import scipy.special as spe
import matplotlib.pyplot as plt

class neuralnetwork:
    # 我们需要去初始化一个神经网络
    
    def __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函数
        
        
    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).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))
        
    
    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 = 784
hidden_nodes = 88
output_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 = 0
for i in range(15):
    count = 0
    for j in range(len(data_list)):
        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)
    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 += 1
    sum_count += count
    string = "训练进度 %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手写数字识别内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python实现爬虫下载漫画示例
Feb 16 Python
Python线程中对join方法的运用的教程
Apr 09 Python
Python操作SQLite数据库的方法详解
Jun 16 Python
基于MTCNN/TensorFlow实现人脸检测
May 24 Python
Python基于pandas实现json格式转换成dataframe的方法
Jun 22 Python
Pyqt QImage 与 np array 转换方法
Jun 27 Python
python 命令行传入参数实现解析
Aug 30 Python
python打印直角三角形与等腰三角形实例代码
Oct 20 Python
OpenCV 表盘指针自动读数的示例代码
Apr 10 Python
基于Python第三方插件实现西游记章节标注汉语拼音的方法
May 22 Python
Jupyter安装拓展nbextensions及解决官网下载慢的问题
Mar 03 Python
常用的Python代码调试工具总结
Jun 23 Python
利用Selenium添加cookie实现自动登录的示例代码(fofa)
Python基础之教你怎么在M1系统上使用pandas
python文件目录操作之os模块
May 08 #Python
Python进阶学习之带你探寻Python类的鼻祖-元类
May 08 #Python
python实战之用emoji表情生成文字
May 08 #Python
python实现过滤敏感词
Django中的JWT身份验证的实现
May 07 #Python
You might like
德生S2000南麂列岛台湾FM收听记录
2021/03/02 无线电
PHP header函数分析详解
2011/08/06 PHP
使用Apache的htaccess防止图片被盗链的解决方法
2013/04/27 PHP
基于PHP静态类的原罪详解
2013/05/06 PHP
php 广告点击统计代码(php+mysql)
2018/02/21 PHP
一次失败的jQuery优化尝试小结
2011/02/06 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
2015/09/01 Javascript
JS实现可点击展开与关闭的左侧广告代码
2015/09/02 Javascript
node.js require() 源码解读
2015/12/13 Javascript
BootStrap modal模态弹窗使用小结
2016/10/26 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
2016/11/22 Javascript
jQuery删除当前节点元素
2016/12/07 Javascript
微信小程序 动态绑定事件并实现事件修改样式
2017/04/13 Javascript
微信小程序商品详情页的底部弹出框效果
2020/11/16 Javascript
自定义Vue中的v-module双向绑定的实现
2019/04/17 Javascript
Python实现将DOC文档转换为PDF的方法
2015/07/25 Python
使用Python脚本将文字转换为图片的实例分享
2015/08/29 Python
Android应用开发中Action bar编写的入门教程
2016/02/26 Python
Python实现 多进程导入CSV数据到 MySQL
2017/02/26 Python
virtualenv实现多个版本Python共存
2017/08/21 Python
Python中的is和==比较两个对象的两种方法
2017/09/06 Python
Pandas 同元素多列去重的实例
2018/07/03 Python
python提取log文件内容并画出图表
2019/07/08 Python
vim自动补全插件YouCompleteMe(YCM)安装过程解析
2019/10/21 Python
澳大利亚珠宝商:Shiels
2019/10/06 全球购物
这段代码难道不该打印出56吗
2013/02/27 面试题
《跨越百年的美丽》教学反思
2014/02/11 职场文书
ktv总经理岗位职责
2014/02/17 职场文书
应届大专毕业生自我鉴定
2014/04/08 职场文书
高三霸气励志标语
2014/06/24 职场文书
安全在我心中演讲稿
2014/09/01 职场文书
2014离婚协议书范文两篇
2014/09/15 职场文书
行政复议答复书
2015/07/01 职场文书
2016十一国庆节慰问信
2015/12/01 职场文书
2019年特色火锅店的创业计划书模板
2019/08/28 职场文书
CSS3 菱形拼图实现只旋转div 背景图片不旋转功能
2021/03/30 HTML / CSS