一步一步教你建立手寫數(shù)字識(shí)別項(xiàng)目,需要源文件的請(qǐng)可直接跳轉(zhuǎn)下邊的鏈接:All project
Deep Learning Project – Handwritten Digit Recognition using Python
本文摘要
在本文中,我們將使用MNIST數(shù)據(jù)集實(shí)現(xiàn)一個(gè)手寫數(shù)字識(shí)別應(yīng)用程序。我們將使用一種特殊類型的深度神經(jīng)網(wǎng)絡(luò),即卷積神經(jīng)網(wǎng)絡(luò)。最后,我們將構(gòu)建一個(gè)GUI,您可以在其中繪制數(shù)字并立即識(shí)別它。
實(shí)現(xiàn)效果:
運(yùn)行項(xiàng)目的需求
這個(gè)有趣的Python項(xiàng)目要求你具備Python編程的基本知識(shí),使用Keras庫和Tkinter庫進(jìn)行深度學(xué)習(xí),以構(gòu)建GUI。
使用下面的命令為這個(gè)項(xiàng)目安裝必要的庫:
pip install numpy, tensorflow, keras, pillow,
MNIST 數(shù)據(jù)集
這可能是機(jī)器學(xué)習(xí)和深度學(xué)習(xí)愛好者中最受歡迎的數(shù)據(jù)集之一。MNIST數(shù)據(jù)集包含60,000張從0到9的手寫數(shù)字的訓(xùn)練圖像和10,000張用于測(cè)試的圖像。MNIST數(shù)據(jù)集有10個(gè)不同的類。手寫數(shù)字圖像表示為28×28矩陣,其中每個(gè)單元格包含灰度像素值。
建立基于深度學(xué)習(xí)的手寫數(shù)字識(shí)別項(xiàng)目
以下是實(shí)現(xiàn)手寫數(shù)字識(shí)別項(xiàng)目的步驟:
1、導(dǎo)入庫并加載數(shù)據(jù)集
首先,我們將導(dǎo)入訓(xùn)練模型所需的所有模塊。Keras庫已經(jīng)包含了一些數(shù)據(jù)集,MNIST就是其中之一。所以我們可以很容易地導(dǎo)入數(shù)據(jù)集并開始使用它。mnist.load_data()方法返回訓(xùn)練數(shù)據(jù)及其標(biāo)簽以及測(cè)試數(shù)據(jù)及其標(biāo)簽。
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print(x_train.shape, y_train.shape)
2、處理數(shù)據(jù)集
圖像數(shù)據(jù)不能直接輸入到模型中,所以我們需要對(duì)數(shù)據(jù)進(jìn)行一些操作和處理,使其為神經(jīng)網(wǎng)絡(luò)做好準(zhǔn)備。訓(xùn)練數(shù)據(jù)的維數(shù)為(60000,28,28)。CNN模型將需要多一個(gè)維度,因此我們將矩陣重塑為形狀(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)
# convert class vectors to binary class matrices
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
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
3、建立模型
現(xiàn)在我們將在Python數(shù)據(jù)科學(xué)項(xiàng)目中創(chuàng)建CNN模型。CNN模型通常由卷積層和池化層組成。它對(duì)于表示為網(wǎng)格結(jié)構(gòu)的數(shù)據(jù)效果更好,這就是為什么CNN在圖像分類問題上效果很好的原因。dropout層用于使一些神經(jīng)元失活,在訓(xùn)練時(shí),它減少了模型的擬合。然后,我們將使用Adadelta優(yōu)化器編譯模型。
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'])
4、訓(xùn)練模型
Keras的model.fit()函數(shù)將開始模型的訓(xùn)練。它需要訓(xùn)練數(shù)據(jù)、驗(yàn)證數(shù)據(jù)、epoch和批大小。
訓(xùn)練模型需要一些時(shí)間。訓(xùn)練完成后,我們將權(quán)值和模型定義保存在“mnist.h5”文件。
hist = model.fit(x_train, y_train,batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(x_test, y_test))
print("The model has successfully trained")
model.save('mnist.h5')
print("Saving the model as mnist.h5")
5、評(píng)估模型
我們的數(shù)據(jù)集中有10,000張圖像,這些圖像將用于評(píng)估我們的模型工作的好壞。測(cè)試數(shù)據(jù)沒有參與數(shù)據(jù)的訓(xùn)練,因此是我們模型的新數(shù)據(jù)。MNIST數(shù)據(jù)集很好地平衡了,所以我們可以得到大約99%的準(zhǔn)確率。
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
6、建立GUI界面預(yù)測(cè)數(shù)字
現(xiàn)在對(duì)于GUI,我們已經(jīng)創(chuàng)建了一個(gè)新文件,我們?cè)谄渲袠?gòu)建了一個(gè)交互式窗口,用于在畫布上繪制數(shù)字,并且通過一個(gè)按鈕,我們可以識(shí)別數(shù)字。Tkinter庫包含在Python標(biāo)準(zhǔn)庫中。我們已經(jīng)創(chuàng)建了一個(gè)函數(shù)predict_digit(),它將圖像作為輸入,然后使用訓(xùn)練好的模型來預(yù)測(cè)數(shù)字。
然后我們創(chuàng)建App類,它負(fù)責(zé)為我們的應(yīng)用程序構(gòu)建GUI。我們創(chuàng)建一個(gè)畫布,我們可以通過捕獲鼠標(biāo)事件和按鈕來繪制,我們觸發(fā)predict_digit()函數(shù)并顯示結(jié)果。
下面是我們的gui_digit_recognizer.py文件的完整代碼:
from keras.models import load_model
from tkinter import *
import tkinter as tk
import win32gui
from PIL import ImageGrab, Image
import numpy as np
model = load_model('mnist.h5')
def predict_digit(img):
#resize image to 28x28 pixels
img = img.resize((28,28))
#convert rgb to grayscale
img = img.convert('L')
img = np.array(img)
#reshaping to support our model input and normalizing
img = img.reshape(1,28,28,1)
img = img/255.0
#predicting the class
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
# Creating elements
self.canvas = tk.Canvas(self, width=300, height=300, bg = "white", cursor="cross")
self.label = tk.Label(self, text="Thinking..", font=("Helvetica", 48))
self.classify_btn = tk.Button(self, text = "Recognise", command = self.classify_handwriting)
self.button_clear = tk.Button(self, text = "Clear", command = self.clear_all)
# Grid structure
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("<Motion>", self.start_pos)
self.canvas.bind("<B1-Motion>", self.draw_lines)
def clear_all(self):
self.canvas.delete("all")
def classify_handwriting(self):
HWND = self.canvas.winfo_id() # get the handle of the canvas
rect = win32gui.GetWindowRect(HWND) # get the coordinate of the canvas
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()
截屏結(jié)果
總結(jié)
在本文中,我們成功地在手寫數(shù)字識(shí)別應(yīng)用程序上構(gòu)建了一個(gè)Python深度學(xué)習(xí)項(xiàng)目。我們構(gòu)建并訓(xùn)練了卷積神經(jīng)網(wǎng)絡(luò),它對(duì)于圖像分類非常有效。稍后,我們構(gòu)建GUI,在畫布上繪制數(shù)字,然后對(duì)數(shù)字進(jìn)行分類并顯示結(jié)果。
博客主頁:https://blog.csdn.net/weixin_51141489,需要源碼或相關(guān)資料實(shí)物的友友請(qǐng)關(guān)注、點(diǎn)贊,私信吧!