五、手写数字识别
一、实验目的
1.学会用分类算法解决实际问题
二、实验工具
1.Anaconda
2.sklearn
3.matplotlib
4.pandas
三、实验简介
概念介绍
图像识别(Image Recognition)是指利用计算机对图像进行处理、分析和理解,以识别各种不同模式的目标和对像的技术。
图像识别的发展经历了三个阶段:文字识别、数字图像处理与识别、物体识别。机器学习领域一般将此类识别问题转化为分类问题。
手写识别是常见的图像识别任务。计算机通过手写体图片来识别出图片中的字,与印刷字体不同的是,不同人的手写体风格迥异,大小不一,造成了计算机对手写识别任务的一些困难。
数字手写体识别由于其有限的类别(0~9共10个数字)成为了相对简单的手写识别任务。DBRHD和MNIST是常用的两个数字手写识别数据集
数据介绍
MNIST的下载链接:http://yann.1ecun.com/exdb/mnist/。
MNIST是一个包含数字0~9的手写体图片数据集,图片已归一化为以手写数字为中心的28*28规格的图片。
MNIST由训练集与测试集两个部分组成,各部分规模如下:
训练集:60,000个手写体图片及对应标签测试集:10,000个手写体图片及对应标签
![image.png](http://www.graph-
edu.cn:5000/static/2021spr_images/19970746_数据挖掘
_8_1620695811.png)
##四、实验内容
###1.分析采用决策树算法、朴素贝叶斯算法实现手写数字识别。
(1)决策树算法,准确率:0.8467
import numpy as np
from sklearn.datasets
import load digits from sklearn.model selection
import train test split
import pickle as pickle
import matplotlib.pyplot as plt
mnist=load digits()
x,test_x,y,test_y=train_test_split(mnist.data,mnist.target,
test_size=0.25,random_sta te=40)
from sklearn.tree import DecisionTreeclassifier,
export_graphviz
mode1=DecisionTreeClassifier(criterion="entropy")
model.fit(x,y)
z=model.predict(test_x)
print('准确率:',np.sum(z==test_y)/z.size)
#学习后识别99到105六张图片并给出预测
model.predict(mnist.data[99:105])
#实际的99到105代表的数
mnist.target[99:105]
#显示99到105数字图片
plt.subplot(321)
plt.imshow(mnist.images[99],cmap=plt.cm.gray_r,
interpolation='near est')
plt.subplot(322)
plt.imshow(mnist.images[100],cmap=plt.cm.gray_r,
interpolation='nea rest')
plt.subplot(323)
plt.imshow(mnist.images[101],cmap=plt.cm.gray_r,
interpolation='nea rest')
plt.subplot(324)
plt.imshow(mnist.images[102],cmap=plt.cm.gray_r,
interpolation='nea rest')
plt.subplot(325)
plt.imshow(mnist.images[103],cmap=plt.cm.gray_r,
interpolation='nea rest')
plt.subplot(326)
plt.imshow(mnist.images[104],cmap=plt.cm.gray_r,
interpolation='nea rest')
from six import StringIo
import pandas as pd
x=pd.DataFrame(x)
with open("D:/shujukexue/JueCetree.dot",'w')as f:f=
export_graphviz(model,feature_names=x.columns,out_file=f)
(2)朴素贝叶斯算法,准确率:0.8413
import numpy as np
import struct
from collections import defaultdict
def normalize(data): # 将图片像素二值化
m, n = data.shape
for i in range(m):
for j in range(n):
if data[i, j] != 0: # 位置有像素即为1
data[i, j] = 1
else:
data[i, j] = 0
return data
def read_data():
path = [r'C:\Users\19759\Desktop\data\t10k-images-idx3-ubyte',
r'C:\Users\19759\Desktop\data\t10k-labels-idx1-ubyte',
r'C:\Users\19759\Desktop\data\train-images-idx3-ubyte',
r'C:\Users\19759\Desktop\data\train-labels-idx1-ubyte']
# 4个数据集路径
data = defaultdict(dict) # 声明一个空的字典 存放映射结果
for i in range(0, 4):
file = open(path[i], 'rb') # 打开数据集
f = file.read()
file.close()
# 以下进行数据的转化,图片、标签转化为数字信息
if i % 2 == 0: # 图片
img_index = struct.calcsize('>IIII')
_, size, row, column = struct.unpack('>IIII', f[:img_index])
imgs = struct.unpack_from(str(size * row * column) + 'B', f,
img_index)
imgs = np.reshape(imgs,
(size, row * column)).astype(np.float32)
imgs = normalize(imgs)
if i == 0:
key = 'test'
else:
key = 'train'
data[key]['images'] = imgs
else: # 标签
label_index = struct.calcsize('>II')
_, size = struct.unpack('>II', f[:label_index])
labels = struct.unpack_from(str(size) + 'B',
f, label_index)
labels = np.reshape(labels, (size,))
tmp = np.zeros((size, np.max(labels) + 1))
tmp[np.arange(size), labels] = 1
labels = tmp
if i == 1:
key = 'test'
else:
key = 'train'
data[key]['labels'] = labels
return data
def train(data): # 训练模型
imgs = data['train']['images'] # 打开训练集
labels = data['train']['labels']
# n为训练集的训练个数(6W)
#dimsnum为转化后保存图片的所需的0 1位数
#labelnum为标签的个数(10个 0-9)
n, dimsnum = imgs.shape
n, labelnum = labels.shape
# 初始化sum和shape
sum = np.zeros(labelnum)
shape = np.zeros((labelnum, dimsnum))
for i in range(0, n): # n个数据
# 找出第i个中最大的下标
#labels[i][j]=1代表第i张图片为数字j 其余为0
pos = np.argmax(labels[i])
# 该数字出现次数+1
sum[pos] = sum[pos] + 1
for j in range(0, dimsnum): # 图片转化后的n个维度
shape[pos][j] = shape[pos][j] + imgs[i][j]
# shape[pos][j]代表数字pos第j维1的和
for i in range(0, labelnum):
for j in range(0, dimsnum):
shape[i][j] = (shape[i][j] + 1) / (sum[i] + 2)
# 将shape转化为概率
sum = sum / n # 将sum转化为概率
return sum, shape
def test(data, sum, shape): # 测试模型
imgs = data['test']['images'] # 打开测试集
labels = data['test']['labels']
# n为测试集个数 dimsnum为测试图片转化后的位数(维度)
# labelnum标签个数(0-9十个)
n, dimsnum = imgs.shape
n, labelnum = labels.shape
correct = 0 # 测试时根据训练模型准确的个数
for i in range(0, n):
pos = np.argmax(labels[i]) # 图片对应的数字pos
maxx = 0 # 0-9中的最大概率
vpos = -1 # 0-9中的对应最大概率的数字
for k in range(0, labelnum): # 数字0-9
ans = 1
for j in range(0, dimsnum): # dimsnum维
if imgs[i][j] == 1:
# 第i个图片的第j维对应为1 '出现此概率'
ans *= shape[k][j]
else: # 未出现
ans *= (1 - shape[k][j])
ans *= sum[k]
# 乘数字k在训练集中的概率 理想状态下为0.1
if ans > maxx:
maxx = ans
vpos = k
if vpos == pos:
# 当找到的数字和测试集的数字相同 测试成功数+1
correct += 1
return correct, n # 返回成功数和测试集总数
if __name__ == '__main__':
data = read_data()
sum, shape = train(data)
correct, num = test(data, sum, shape)
print("测试正确率为:", correct / num
五、补充
导入训练集和测试集的时候出现错误,将测试集合训练集放入制定位置之后,运行成功