机器学习之手写数字图片数据处理及识别

背景

1.手写数字识别技术的含义
手写数字识别(Handwritten Digit Recognition)是光学字符识别技术的一个分支,是模式识别学科的一个传统研究领域。主要研究如何利用电子计算机自动辨认手写在纸张上的阿拉伯数字。手写数字识别分为脱机手写数字识别和联机手写数字识别。本文主要讨论脱机手写数字的识别。 随着信息化的发展,手写数字识别的应用日益广泛,研究高识别率、零误识率和低拒识率的高速识别算法具有重要意义。

2.手写数字识别技术的理论价值

由于手写数字识别本身的特点,对它的研究有重要的理论价值:

(1)阿拉伯数字是唯一被世界各国通用的符号,对手写体数字识别的研究基本上与文化背景无关,各地的研究工作者基于同一平台开展工作,有利于研究的比较和探讨。

(2) 手写数字识别应用广泛,如邮政编码自动识别,税表系统和银行支票自动处理等。这些工作以前需要大量的手工录入,投入的人力物力较多,劳动强度较大。手写数字识别的研究适应了无纸化办公的需要,能大大提高工作效率。

⑶由于数字类别只有 10 个,较其他字符识别率较高,可用于验证新的理论和做深入的分析研究。许多机器学习和模式识别领域的新理论和算法都是先用手写数字识别进行检验,验证理论的有效性,然后才应用到更复杂的领域当中。这方面的典型例子就是人工神经网络和支持向量机(Support Vector Machine)。

⑷手写数字的识别方法很容易推广到其它一些相关问题,如对英文之类拼音文字的识别。事实上,很多学者就是把数字和英文字母的识别放在一起研究的。

3.数字识别技术的难点

数字的类别只有 10
种,笔划简单,其识别问题似乎不是很困难。但事实上,一些测试结果表明,数字的正确识别率并不如印刷体汉字识别率高,甚至也不如联机手写体汉字识别率高,而只仅仅优于脱机手写体汉字识别。这其中的主要原因是:

⑴数字笔划简单,其笔划差别相对较小,字形相差不大,使得准确区分某些数字相当困难;

⑵数字虽然只有 10 种,且笔划简单,但同一数字写法千差万别,全世界各个国家各个地区的人都在用,其书写上带有明显的区域特性,很难做出可以兼顾世界各种写法的、识别率极高的通用性数字识别系统。

虽然目前国内外对脱机手写数字识别的研究已经取得了很大的成就,但是仍然存在两大难点:

一是识别精度需要达到更高的水平。手写数字识别没有上下文,数据中的每一个数据都至关重要。而数字识别经常涉及金融、财会领域,其严格性更是不言而喻。因此,国内外众多的学者都在为提高手写数字的识别率,降低误识率而努力。

二是识别的速度要达到很高的水平。数字识别的输入通常是很大量的数据,而高精度与高速度是相互矛盾的,因此对识别算法提出了更高的要求。

实现过程简说

首先,我们拿到了两个文件夹。

一个文件夹里的图片同来训练出一个分类器/模型
另一个文件夹的图片对训练出的分类器/模型性能进行评估

图片预处理
  1. 读取图片并打开
  2. 图片灰度化,将其降噪转化为黑白两色
  3. 保存新得到的图片
  4. 创建数组存入图片和标签

图片预处理我没有采用二值化的方法,因为我的数字图片比较清晰吧,我觉得对于这些数字没有必要,根据实际情况吧,但二值化对于后面的预测还是有点点影响的

构建模型
  1. 算法选择
    以下列举三个算法代码都会实现(但选其中一个就可以了)

    KNN算法
    逻辑回归算法
    卷积神经网络

  2. 构建模型,训练,对模型进行评分

代码部分

image_process.py

from PIL import Image
import numpy as np
import os, re
import matplotlib.pylab as plt

def get_img_names(path):
    file_names = os.listdir(path)
    img_names = []
    for i in file_names:
        if re.findall('\d_\d+\.png', i) != []:
            img_names.append(i)
    return img_names

def get_img_data(path):
    data = []    # 特征数据(图像数组)
    labels = []    # 目标(标签)数据
    img = get_img_names(path)
    # print(img)
    img = np.array(img)
    # print(img.shape)
    n = int(img.shape[0] / 10) + 1    # 得到每个数字的图片数
    for i in range(10):
        for j in range(1, n):
            img = Image.open(path + "%d_%d.png" % (i, j))  # 打开图片
            # print(img)    # <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=38x41 at 0x21E8FD19748>
            img = img.resize((32, 32))      # 将图片化为32*32的
            img = img.convert('RGBA')     # "L"为灰度化
            raw_data = img.load()             # 得到图片的像素值
            # 将其降噪并转化为黑白两色
            for y in range(img.size[1]):
                for x in range(img.size[0]):
                    if raw_data[x, y][0] < 90:
                        raw_data[x, y] = (0, 0, 0, 255)

            for y in range(img.size[1]):
                for x in range(img.size[0]):
                    if raw_data[x, y][1] < 136:
                        raw_data[x, y] = (0, 0, 0, 255)

            for y in range(img.size[1]):
                for x in range(img.size[0]):
                    if raw_data[x, y][2] > 0:
                        raw_data[x, y] = (255, 255, 255, 255)

            # print(img)    # <PIL.Image.Image image mode=RGBA size=38x41 at 0x21E8FD19828>
            img.save(path + '%d_%d(%d).png' % (i, j, i))  # 保存,方便查看
            # 读取图片,一共有10个数字(0-9),每个有12张图片.图片命名格式为:_0_1.png
            digit = plt.imread(path + '%d_%d(%d).png' % (i, j, i))
            data.append(digit)    # 逐个图片添加
            labels.append(i)
    # 把列表转成数组
    data = np.array(data)
    labels = np.array(labels)
    # 查看数组形状
    # print(data.shape)     # (120,)

    # 随机显示一张图片(方便查看,上述操作后是否有变化)
    # index = np.random.randint(0, 20, size=1)[0]
    # img_ = data[index]
    # plt.figure(figsize=(0.3, 0.3))          # 设置画布宽为0.3,高为0.3
    # plt.imshow(img_, cmap='gray')         # 显示颜色为gray
    # plt.axis("off")     # 去掉坐标轴
    # plt.show()
    # print(labels[index])
    return data, labels

data.py

from image_process import get_img_data
from sklearn.neighbors import KNeighborsClassifier      # KNN算法
from sklearn.metrics import classification_report, confusion_matrix
import matplotlib.pyplot as plt

# 得到训练集和测试集样本
data_tr, labels_tr = get_img_data("trainImages/")
data_te, labels_te = get_img_data("testImages/")
# (120, 32, 32, 4) (120,) (30, 32, 32, 4) (30,)
# 训练数据要为二维数组,如果不做转换会报如下错误,说4维数组不能做运算。报错: ValueError: Found array with dim 4. Estimator expected <= 2.
# data_tr = data_tr.reshape(120, -1)
# data_te = data_te.reshape(30, -1)
# print(data_tr.shape, labels_tr.shape, data_te.shape, labels_te.shape)    # (120, 4096) (120,) (30, 4096) (30,)

# 使用KNN算法   n_neighbors: int,默认值为5,表示knn算法中选取离测试数据最近的k个点,
model = KNeighborsClassifier(n_neighbors=1)  # 构建模型
model.fit(data_tr.reshape(120, -1), labels_tr)      # 训练模型
pre = model.predict(data_te.reshape(30, -1))       # 预测
print(pre)
# 对训练后的模型进行评分(# 模型在测试集上的精度)
acc = model.score(data_te.reshape(30, -1), labels_te)
print(acc)
# 性能评价
print(confusion_matrix(labels_te, pre))         # confusion_matrix:混淆矩阵
print(classification_report(labels_te, pre))

# 可视化预测结果
# 画布大小10行10列,每行高为1,每列宽为1.5
plt.figure(figsize=(10*1, 10*1.5))
for i in range(30):
    #绘制子图
    axes = plt.subplot(10, 10, i+1)
    #测试数据为500张,绘制其中的30张
    axes.imshow(data_te[i], cmap='gray')
    #添加标题
    t = labels_te[i]
    p = pre[i]
    axes.set_title('True:%d\nPred:%d' % (t, p))
    #不显示坐标刻度
    axes.axis('off')
plt.savefig('axes.png')
plt.show()

KNN算法的正确率不是特别高,如果想要达到0.9几的可以尝试卷积神经网络
这里有设计了一个知识点:监督算法和无监督算法

结果:

[1 0 0 1 1 1 2 1 7 3 7 3 4 1 4 5 5 6 6 6 6 7 7 7 8 6 8 9 3 9]
0.7333333333333333
[[2 1 0 0 0 0 0 0 0 0]
 [0 3 0 0 0 0 0 0 0 0]
 [0 1 1 0 0 0 0 1 0 0]
 [0 0 0 2 0 0 0 1 0 0]
 [0 1 0 0 2 0 0 0 0 0]
 [0 0 0 0 0 2 1 0 0 0]
 [0 0 0 0 0 0 3 0 0 0]
 [0 0 0 0 0 0 0 3 0 0]
 [0 0 0 0 0 0 1 0 2 0]
 [0 0 0 1 0 0 0 0 0 2]]
              precision    recall  f1-score   support

           0       1.00      0.67      0.80         3
           1       0.50      1.00      0.67         3
           2       1.00      0.33      0.50         3
           3       0.67      0.67      0.67         3
           4       1.00      0.67      0.80         3
           5       1.00      0.67      0.80         3
           6       0.60      1.00      0.75         3
           7       0.60      1.00      0.75         3
           8       1.00      0.67      0.80         3
           9       1.00      0.67      0.80         3

    accuracy                           0.73        30
   macro avg       0.84      0.73      0.73        30
weighted avg       0.84      0.73      0.73        30


Process finished with exit code 0

在这里插入图片描述

  • 16
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
手写数字识别是一个很好的机器学习实验项目,它可以让你了解到如何使用神经网络来训练模型,以便能够自动识别手写数字。 以下是手写数字识别的基本步骤: 1. 收集数据集:你需要收集一些手写数字的数据集。你可以使用MNIST数据集,它是一个包含60,000个训练图像和10,000个测试图像的公共数据集。你也可以自己制作数据集,收集一些手写数字图片并将其标记。 2. 数据预处理:你需要对数据集进行预处理,例如将图片转换为灰度图像、将其调整为相同的大小,并将数据集分为训练集和测试集。 3. 构建模型:你需要构建一个神经网络模型,用于处理手写数字图像并输出相应的数字标签。你可以使用卷积神经网络(CNN)或全连接神经网络(FCN)来实现这个模型。 4. 训练模型:你需要将数据集输入到模型中进行训练。在训练期间,模型将不断优化其权重和偏置,以便最小化损失函数并提高准确性。你可以使用反向传播算法(backpropagation)来优化模型。 5. 测试模型:当模型训练完成后,你需要将测试集输入到模型中进行测试。测试结果将为你提供模型的准确性。 6. 应用模型:最后,你可以将训练好的模型应用于实际场景中,例如手写数字识别应用程序或自动化识别系统。 以上是手写数字识别的基本步骤。当然,这只是一个简单的例子,你可以使用更复杂的方法来提高模型的准确性,例如使用数据增强、正则化、批处理规范化等技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值