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

作者:神仙盼盼 时间:2022-01-12 20:50:04 

写在之前

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

首先是关于这本书,我真的认为他是将神经网络里非常棒的一本书,但你也需要注意,如果你真的想自己动手去实现,那么你一定需要有一定的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加速肯定是最好的选择之一。

来源:https://blog.csdn.net/qq_44961028/article/details/116429010

标签:python,手写数字识别,神经网络编程
0
投稿

猜你喜欢

  • python 函数定位参数+关键字参数+inspect模块

    2023-07-05 23:04:37
  • Python读取HTML中的canvas并且以图片形式存入Word文档

    2022-09-03 04:50:33
  • Python全局变量与局部变量区别及用法分析

    2021-01-24 07:35:21
  • vue项目中使用axios遇到的相对路径和绝对路径问题

    2024-05-13 09:37:40
  • MySQL5.6解压版服务无法启动之系统错误1067问题

    2024-01-14 18:20:46
  • python正则表达式的使用

    2023-07-21 07:42:15
  • { hide_text } CSS文字隐藏总结报告

    2010-06-13 17:19:00
  • Oracle 多行记录合并/连接/聚合字符串的几种方法

    2009-11-17 08:53:00
  • MySQL Slave 触发 oom-killer解决方法

    2024-01-20 14:44:35
  • 跨浏览器实现float:center,No CSS hacks

    2008-08-22 12:59:00
  • Python针对给定列表中元素进行翻转操作的方法分析

    2022-04-19 18:37:07
  • 详解python opencv、scikit-image和PIL图像处理库比较

    2021-11-10 02:24:13
  • 用Python制作一个可以聊天的皮卡丘版桌面宠物

    2021-12-05 10:44:41
  • 小xiao说说创意图标设计心得

    2009-11-18 12:27:00
  • numpy中的converters和usecols用法详解

    2021-01-23 18:29:29
  • GitHub上值得推荐的8个python 项目

    2021-01-11 22:40:12
  • Python分析微信好友性别比例和省份城市分布比例的方法示例【基于itchat模块】

    2022-01-04 08:14:09
  • MySQL8.0+版本1045错误的问题及解决办法

    2024-01-16 23:19:33
  • Win10下为VSCode配置LaTex编辑器的方法

    2023-08-27 17:20:07
  • 对Python3中bytes和HexStr之间的转换详解

    2022-12-10 22:15:36
  • asp之家 网络编程 m.aspxhome.com