本文将用Numpy实现简单BP神经网络完成对手写数字图片的识别,数据集为42000张带标签的28x28像素手写数字图像。在计算机完成对手写数字图片的识别过程中,代表图片的28x28=764个像素的特征数据值将会被作为神经网络的输入,经过网络的正向传播,得到可以粗略作为0~9每个数字的概率的输出(输出层第一个神经元节点的输出看成是图片数字是0的概率,其余9个神经元节点以此类推),取概率最大的数字即为识别结果。神经网络的输出神经元节点有10个,假设待识别数字为1,就可以定义label为[0,1,0,0,0,0,0,0,0,0],将网络的10个节点的输出组成的向量(预测值)与label(真实值)进行对比,定义均方误差损失E,根据梯度下降法完成对网络权值和阈值的参数更新,即对网络的训练。在对模型的评估中,简单地使用测试样本中预测正确的样本数占全部测试样本总数的比例作为模型的识别正确率。

网络隐层的层数以及神经元的个数是可以人为设置的,但需注意合理设置。文中设置的隐层有两层,每层神经元的节点数都设置为50,在对数据集进行训练集、测试集约为1:1划分,训练轮数为5轮的情况下,达到了92%以上不错的正确预测率。需要提醒的是,训练轮数过大以及隐层节点数设置过大,极有可能发生过拟合的情况,导致正确率不如人意。
       数据集地址:
       链接:https://pan.baidu.com/s/1XzexzXGYhUdFpM4UaIb3yA
       提取码:9wjm

实现代码如下:

import numpy as np
import csv
from tqdm import trange

def sigmoid(x):
return 1.0 / (1.0 + np.exp(-x))

def sigmoid_derivative(x):
return sigmoid(x) * (1 - sigmoid(x))

class Net:

def __init__(self, layers):
self.active = sigmoid # 激活函数
self.active_d = sigmoid_derivative # 激活函数的求导
self.weights = [] # 权值参数
self.bias = [] # 阈值参数
for i in range(1, len(layers)): # 参数初始化
self.weights.append(np.random.randn(layers[i - 1], layers[i]))
self.bias.append(np.random.randn(layers[i]))

def core(self, x, label, learning_rate):
y = [x] # 保存每层激活后的输出值

# 正向传播
for i in range(len(self.weights)):
y.append(self.active(np.dot(y[-1], self.weights[i]) + self.bias[i]))

# 反向传播
e = y[-1] - label
deltas = [e * y[-1] * (1 - y[-1])] # 输出层Delta值
# 各隐藏层Delta值
for i in range(1, len(self.weights)):
deltas.append(np.dot(deltas[-1], self.weights[-i].T) * y[-i - 1] * (1 - y[-i - 1]))
# 误差项倒置
deltas.reverse()
# 更新参数w和b
for i in range(len(self.weights)):
y_2d = np.atleast_2d(y[i])
deltas_2d = np.atleast_2d(deltas[i])
self.weights[i] -= learning_rate * np.dot(y_2d.T, deltas_2d)
self.bias[i] -= learning_rate * deltas[i]

def predict(self, x):

# 正向传播预测输出值
y = x
for i in range(len(self.weights)):
y = self.active(np.dot(y, self.weights[i]) + self.bias[i])
_ = [str(round((i / y.sum()) * 100, 2)) + "%" for i in y] # 将输出结果以概率的形式展现
out = list(y)
result = out.index(max(out))
return result, _

if __name__ == '__main__':

Net = Net([784, 50, 50, 10])
# 读取数据
file_name = "data/train.csv" # 数据集为42000张带标签的28x28手写数字图像
x_train = [] # 训练集样本数据特征
y_train = [] # 训练集样本标签
'''
测试集用来测试模型质量必不可少。
验证集用来调节超参数,如神经网络层数,各层神经节点数、学习率等人为设置而不是模型通过学习得到的参数,可省略,仅用训练集即可
'''
x_test = [] # 测试集样本数据特征
y_test = [] # 测试集样本数据标签
with open(file_name, 'r') as f:
reader = csv.reader(f)
header_row = next(reader)
for row in reader:
data = np.array(row[1:], dtype=np.float_)
if np.random.random() < 0.5: # 划分数据集 训练集:测试集 ≈ 1:1
x_train.append(data / ((data ** 2).sum() ** 0.5)) # 每个样本对应的784个特征数值归一化
y_train.append(int(row[0]))
else:
x_test.append(data / ((data ** 2).sum() ** 0.5))
y_test.append(int(row[0]))

print("训练样本数:{},测试样本数:{}".format(len(y_train), len(y_test)))

# 训练
learning_rate = 0.5 # 初始学习率
epochs = 5 # 训练轮数
for i in trange(len(y_train) * epochs):
if (i + 1) % len(y_test) == 0:
learning_rate *= 0.5 # 每训练一轮 学习率减半
label = np.zeros(10)
label[y_train[i % len(y_train)]] = 1 # 设置label
Net.core(x_train[i % len(y_train)], label, learning_rate) # 更新网络参数

# 预测
count = 0
for i in trange(len(y_test)):
print("-------第{}个测试样本-----------".format(i + 1))
predict, _ = Net.predict(x_test[i])
print("预测值:{},真实值:{}".format(predict, y_test[i]))
if predict == y_test[i]:
count += 1
print("正确率:{}".format(count / len(y_test)))

运行结果:

Numpy实现简单BP神经网络识别手写数字的更多相关文章

  1. 用BP人工神经网络识别手写数字

    http://wenku.baidu.com/link?url=HQ-5tZCXBQ3uwPZQECHkMCtursKIpglboBHq416N-q2WZupkNNH3Gv4vtEHyPULezDb5 ...

  2. 利用c++编写bp神经网络实现手写数字识别详解

    利用c++编写bp神经网络实现手写数字识别 写在前面 从大一入学开始,本菜菜就一直想学习一下神经网络算法,但由于时间和资源所限,一直未展开比较透彻的学习.大二下人工智能课的修习,给了我一个学习的契机. ...

  3. BP神经网络的手写数字识别

    BP神经网络的手写数字识别 ANN 人工神经网络算法在实践中往往给人难以琢磨的印象,有句老话叫“出来混总是要还的”,大概是由于具有很强的非线性模拟和处理能力,因此作为代价上帝让它“黑盒”化了.作为一种 ...

  4. 【机器学习】BP神经网络实现手写数字识别

    最近用python写了一个实现手写数字识别的BP神经网络,BP的推导到处都是,但是一动手才知道,会理论推导跟实现它是两回事.关于BP神经网络的实现网上有一些代码,可惜或多或少都有各种问题,在下手写了一 ...

  5. BP神经网络(手写数字识别)

    1实验环境 实验环境:CPU i7-3770@3.40GHz,内存8G,windows10 64位操作系统 实现语言:python 实验数据:Mnist数据集 程序使用的数据库是mnist手写数字数据 ...

  6. PyTorch基础——使用卷积神经网络识别手写数字

    一.介绍 实验内容 内容包括用 PyTorch 来实现一个卷积神经网络,从而实现手写数字识别任务. 除此之外,还对卷积神经网络的卷积核.特征图等进行了分析,引出了过滤器的概念,并简单示了卷积神经网络的 ...

  7. 使用TensorFlow的卷积神经网络识别手写数字(2)-训练篇

    import numpy as np import tensorflow as tf import matplotlib import matplotlib.pyplot as plt import ...

  8. 使用TensorFlow的卷积神经网络识别手写数字(3)-识别篇

    from PIL import Image import numpy as np import tensorflow as tf import time bShowAccuracy = True # ...

  9. 使用TensorFlow的卷积神经网络识别手写数字(1)-预处理篇

    功能: 将文件夹下的20*20像素黑白图片,根据重心位置绘制到28*28图片上,然后保存.经过预处理的图片有利于数字的准确识别.参见MNIST对图片的要求. 此处可下载已处理好的图片: https:/ ...

随机推荐

  1. HDD深圳站:全生命周期赋能开发者,华为引领应用生态升级

    12月14日,由华为开发者联盟主办的HDD(HUAWEI Developer Day)于深圳举行.此次HDD主论坛,围绕打造应用全生命周期服务,介绍了华为在创新孵化.开发测试.应用分发和运营增长阶段的 ...

  2. how2heap学习(一)

    接下来的时间会通过how2heap学习堆的知识,这个系列可能会更新很多篇,因为每天学习到的东西要保证吸收消化,所以一天不会学习很多,但是又想每天记录一下.所以开个系列. first_fit 此题的源码 ...

  3. 1、学习算法和刷题的框架思维——Go版

    前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...

  4. java 多线程 读写互斥锁ReentrantReadWriteLock:读读不互斥,读写互斥,写写互斥

    ReentrantReadWriteLock: 类ReentrantLock具有相互互斥的排他效果,也就是说,同一时间,只有一个线程执行lock()方法后面的任务.这样做虽然可以解决问题,但是效率非常 ...

  5. 第二周Python笔记之 变量的三元运算

    如果变量a小于b,则d的值取a变量的值,否则取c变量的值

  6. 使用yml简化多行sql语句案例

    task:sql:# 将某个值插入到报表- insert into report_app_detail(curr_date,key_name,key_value) values(:curr_date, ...

  7. P7990-[USACO21DEC]Closest Cow Wins S【堆,贪心】

    正题 题目链接:https://www.luogu.com.cn/problem/P7990 题目大意 数轴上有\(k\)个点是草地,每个草地有不同收益,\(m\)个点是地方的点,现在你要放置\(n\ ...

  8. 【九度OJ】题目1174:查找第K小数 解题报告

    [九度OJ]题目1174:查找第K小数 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1174 题目描述: 查找一个数组的第 ...

  9. 【LeetCode】551. Student Attendance Record I 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 正则表达式 统计 日期 题目地址:https://l ...

  10. 【LeetCode】228. Summary Ranges 解题报告(Python)

    [LeetCode]228. Summary Ranges 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/sum ...