五、数据挖掘之手写数字识别

五、手写数字识别

一、实验目的

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

五、补充

导入训练集和测试集的时候出现错误,将测试集合训练集放入制定位置之后,运行成功

上一篇:dgl使用ogb包导入OGB数据集


下一篇:【优化算法】粒子群优化算法(PSO)【含Matlab源码 1073期】