深度学习在手写数字识别中的应用

深度学习是一种强大的技术,它使得开发者能够提升机器的性能。人类如何记住一项任务是如何完成的?通过不断练习和重复执行这项任务,人类最终能够熟练地快速准确地完成任务。大脑中的神经元经过一段时间的训练后能够自动触发并执行任务。同样,深度学习也遵循这种方法来解决问题。深度学习算法使用不同类型的神经网络架构来解决各种问题。

在本文中,将使用MNIST数据集来实现一个手写数字识别应用程序。将使用一种特殊的深度神经网络——卷积神经网络(CNN)。最后,还将构建一个图形用户界面(GUI),用户可以直接在界面上绘制数字并立即识别它。此外,还涵盖了如何在Python中实现手写识别,以展示这些手写代码是如何实现的。让开始吧。

目录

  • 什么是手写数字识别?
  • MNIST数据集
  • 构建手写数字识别系统的步骤
  • 数据预处理
  • 创建模型
  • 训练模型
  • 评估模型
  • 创建GUI以预测数字
  • 常见问题解答

什么是手写数字识别?

手写数字识别是指赋予机器识别人类手写数字的能力。对于机器来说,这不是一项容易的任务,因为手写数字并不完美,人与人之间的差异很大,而且可以用许多不同的风格书写。

先决条件

要运行这个项目,需要具备深度学习基础知识,特别是使用Keras库、Tkinter库进行GUI构建,以及Python编程。以下是安装所需库的命令:

pip install numpy pip install tensorflow pip install keras pip install pillow

MNIST数据集

在市面上成千上万的数据集中,MNIST是机器学习和深度学习爱好者最受欢迎的数据集之一。MNIST数据集包含超过60,000张手写数字的培训图像,从0到9,以及超过10,000张用于测试的图像。因此,MNIST数据集中有10个不同的类别。手写数字的图像显示为28×28的矩阵,每个单元格包含一个灰度像素值。

构建手写数字识别系统的步骤

1. 导入库和数据集

在项目开始时,导入所有需要的模块来训练模型。可以轻松地导入数据集并开始工作,因为Keras库已经包含了许多数据集,MNIST就是其中之一。调用mnist.load_data()函数来获取带有标签的训练数据和测试数据。

import keras from keras.datasets import mnist from keras.models import Sequential from keras.layers import Dense, Flatten, Dropout, Conv2D, MaxPooling2D from keras import backend as K # 导入数据集 (x_train, y_train), (x_test, y_test) = mnist.load_data()

数据预处理

模型不能直接处理图像数据,因此需要执行一些基本操作并处理数据,使其准备好用于神经网络。训练数据的维度是(60000*28*28)。需要为CNN模型增加一个维度,因此将矩阵重塑为形状(60000*28*28*1)。

x_train = x_train.reshape(x_train.shape[0], 28, 28, 1) x_test = x_test.reshape(x_test.shape[0], 28, 28, 1) input_shape = (28, 28, 1) # 将类别向量转换为二进制类别矩阵 y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 x_test /= 255

创建模型

现在是为这个基于Python的数据科学项目创建CNN模型的时候了。卷积层和池化层是CNN模型的两个轮子。CNN之所以能够成功地解决图像分类问题,是因为它适用于网格结构化数据。将使用Adadelta优化器进行模型编译。

batch_size = 128 num_classes = 10 epochs = 10 model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(256, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(num_classes, activation='softmax')) model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])

训练模型

hist = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test)) print("模型已成功训练") model.save('mnist.h5') print("将模型保存为mnist.h5")

评估模型

score = model.evaluate(x_test, y_test, verbose=0) print('测试损失:', score[0]) print('测试准确率:', score[1])

创建GUI以预测数字

from keras.models import load_model from Tkinter import * import Tkinter successful as tk import win32gui from PIL import ImageGrab, Image import numpy as np model = load_model('mnist.h5') def predict_digit(img): # 调整图像大小至28x28像素 img = img.resize((28,28)) # 将rgb转换为灰度 img = img.convert('L') img = np.array(img) # 重塑模型归一化 img = img.reshape(1,28,28,1) img = img/255.0 # 预测类别 res = model.predict([img])[0] return np.argmax(res), max(res) class App(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.x = self.y = 0 # 创建元素 self.canvas = tk.Canvas(self, width=200, height=200, bg="black", cursor="cross") self.label = tk.Label(self, text="Analyzing..", font=("Helvetica", 48)) self.classify_btn = tk.Button(self, text="Searched", command=self.classify_handwriting) self.button_clear = tk.Button(self, text="Dlt", command=self.clear_all) # 网格结构 self.canvas.grid(row=0, column=0, pady=2, sticky=W) self.label.grid(row=0, column=1, pady=2, padx=2) self.classify_btn.grid(row=1, column=1, pady=2, padx=2) self.button_clear.grid(row=1, column=0, pady=2) self.canvas.bind("", self.draw_lines) def clear_all(self): self.canvas.delete("all") def classify_handwriting(self): Hd = self.canvas.winfo_id() rect = win32gui.GetWindowRect(Hd) im = ImageGrab.grab(rect) digit, acc = predict_digit(im) self.label.configure(text= str(digit)+', '+ str(int(acc*100))+'%') def draw_lines(self, event): self.x = event.x self.y = event.y r=8 self.canvas.create_oval(self.x-r, self.y-r, self.x + r, self.y + r, fill='black') app = App() .mainloop()
Q1. 哪种算法最适合手写数字识别
CNN最适合识别手写数字,因为它们能够学习和识别图像中的模式,特别是在MNIST这样的数据集中。
Q2.手写数字识别的准确率有多高?
使用现代算法如CNN的手写数字识别非常准确,通常在MNIST数据集上实现超过99%的准确率。
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485