手寫數字識別

2021-02-13 知之Python

      計算機視覺是Deep Learning中非常廣泛的應用之一,在這之中有一個非常著名的數據集——MNIST數據集,通常會作為在計算機視覺方面的第一個示例,來實踐在DeepLearning中的圖像識別的算法。在這裡將會通過Keras實現卷積神經網絡來處理這個數據集,進步加深對卷積審計網絡的理解。

13.1 問題描述

MNIST數據集是由YannLeCun、Corinna Cortes和ChristopherBurges開發的用於評估手寫數字分類問題的機器學習模型的數據集。該數據集是由美國國家標準與技術研究所(NIST)提供的許多掃描文件數據集構成的,這是數據集的名稱來MNIST或者NIST的來源。

數字圖像是從各種掃描文件中取出的,並且大小統一,這使得它成為評估模型的優秀數據集之一。因為數據集的大小統一,只需要很少的數據清理或準備工作,就可以直接用於模型的訓練,讓開發人員可以專注於模型的構建上。每個圖像是一個28×28像素(總共784像素點)。在這個項目中將數據集預先分割為訓練數據集和評估數據集,其中使用60,000個圖像來訓練模型,並且使用單獨的10,000張圖像來評估得到模型的準確度。

這是一個數字識別任務。因此,預測結果是將圖片中的手寫數字識別為有10個數字(0到9)。使用預測準確度來報告結果,優異的結果能夠達到99%以上的預測準確度。目前,大型卷積神經網絡可以實現約0.2%的預測誤差的高準確度。

13.2 導入數據

在這裡將會使用Keras提供的數據集,因此數據導入過程非常簡單,導入的數據也不需要進行進一步的預處理,可以直接用於神經網絡模型的訓練。導入的數據直接被分割成訓練數據集和評估數據集。同時,為了確保每次執行模型生產相同的模型,數據導入之後會設定隨機種子,並查看最初的4張手寫數字的圖片。代碼如下:

from keras.datasets import mnist

from matplotlib import pyplot as plt

import numpy as np

from keras.models import Sequential

from keras.layers import Dense

from keras.utils import np_utils

 

 

# 從Keras導入Mnist數據集

(X_train, y_train), (X_validation, y_validation) =mnist.load_data()

 

# 顯示4張手寫數字的圖片

plt.subplot(221)

plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))

 

plt.subplot(222)

plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))

 

plt.subplot(223)

plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))

 

plt.subplot(224)

plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))

 

plt.show()

 

# 設定隨機種子

seed = 7

np.random.seed(seed)

 

在第一次導入數據時會從網上下載數據到本地,Keras默認使用Https協議來下載文件,需要注意的是,如果出現「SSL:CERTIFCATE_VERIFY_FAILED」的問題,可以暫時全局取消證書驗證,來下載數據,具體的方法就不在這裡贅述了。執行代碼後,可以看到最初的4張手寫數字的圖片(圖13-1)。

                           

圖13-1

13.3 多層感知器模型

在採用卷積神經網絡來處理手寫數字識別的這個問題之前,先採用多層網絡感知器(MLP)來簡單的實現一下這個問題,作為比較的基準,看一下卷積神經網絡對圖像識別這個問題的改進。也許卷積神經網絡在這個簡單的手寫數字識別問題中的準確度的提升不會很大,但是這會加深對卷積神經網路的理解。

數據導入後,圖像的信息會被保存到,每位有0-255之間的數字構成的28x28的矩陣中,因此多層網絡感知器(MLP)的輸入層的神經元個數是784(28x28),同樣構建一個包含784個神經元的隱藏層。輸入層和隱藏層的激活函數都採用relu。因為在這個數據集中的手寫數字包含0-9這10個數字,也就是說數據集被分成10個類別,因此,輸出層包含10個神經元,激活函數採用softmax。

因為輸入數據是0-255之間的整數,在輸入神經網絡之前對數據進行歸一元處理,並對輸出結果進行one-hot編碼。然後,通過訓練數據集訓練模型,通過驗證數據集來評估模型的準確度。代碼如下:

from keras.datasets import mnist

from matplotlib import pyplot as plt

import numpy as np

from keras.models import Sequential

from keras.layers import Dense

from keras.utils import np_utils

 

 

# 從Keras導入Mnist數據集

(X_train, y_train), (X_validation, y_validation) =mnist.load_data()

 

# 顯示4張手寫數字的圖片

plt.subplot(221)

plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))

 

plt.subplot(222)

plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))

 

plt.subplot(223)

plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))

 

plt.subplot(224)

plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))

 

plt.show()

 

# 設定隨機種子

seed = 7

np.random.seed(seed)

 

num_pixels = X_train.shape[1] * X_train.shape[2]

print(num_pixels)

X_train = X_train.reshape(X_train.shape[0],num_pixels).astype('float32')

X_validation = X_validation.reshape(X_validation.shape[0],num_pixels).astype('float32')

 

# 格式化數據到0-1之前

X_train = X_train / 255

X_validation = X_validation / 255

 

# one-hot編碼

y_train = np_utils.to_categorical(y_train)

y_validation = np_utils.to_categorical(y_validation)

num_classes = y_validation.shape[1]

print(num_classes)

 

# 定義基準MLP模型

def create_model():

    # 創建模型

    model = Sequential()

   model.add(Dense(units=num_pixels, input_dim=num_pixels,kernel_initializer='normal', activation='relu'))

   model.add(Dense(units=num_classes, kernel_initializer='normal',activation='softmax'))

 

    # 編譯模型

   model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy'])

    return model

 

model = create_model()

model.fit(X_train, y_train, epochs=10, batch_size=200)

 

score = model.evaluate(X_validation, y_validation)

print('MLP: %.2f%%' % (score[1] * 100))

 

執行上述代碼,可以看到多層感知器(MLP)的準確度是:

MLP: 98.17%

 

13.4 簡單卷積神經網絡

已經完成了如何加載MNIST數據集並在其上訓練一個簡單的多層感知器模型,現在是開發更複雜的卷積神經網絡模型的時候了。 Keras提供了可以很簡單就可以創建卷積神經網絡的API。接下來將使用MNIST數據集創建一個簡單的卷積神經網路,演示如何在Keras中實現卷積神經網絡,包括卷積層,池化層和全聯接層。

數據的導入和準備與多層感知器(MLP)中的類似,就不在重複。在這裡主要介紹一下,這個簡單的卷積神經網路如何設計:

              I.        第一個隱藏層是一個稱為Conv2D的卷積層。該層使用5x5的感受野,輸出具有32個特徵圖,輸入的數據期待具有input_shape參數所描述的特徵,並採用relu作為激活函數。

            II.        接下來,定義一個採用最大值MaxPooling2D的池化層。並配置它在縱向和橫向兩個方向的採樣因子(pool_size)為2x2,這表示圖片在兩個維度均變成原來的一半。

          III.        下一層是使用名為Dropout的Dropout的正則化層,並配置為隨機排除層中的20%的神經元,以減少過度擬合。

           IV.        接下來是將多維數據轉換為一維數據的Flatten 層。它的輸出便於標準的全連接的層處理。

             V.        接下來是具有128個神經元的全連接的層,採用relu作為激活函數。

           VI.        最後,輸出層有10個神經元,在MNIST數據集的輸出具有10個分類,因此採用softmax激活函數,輸出每張圖片在每個分類上的得分。

卷積神經網絡的模型定義完成了,在對模型進行訓練前,依然需要編譯模型,在這裡採用categorical_crossentropy損失函數,和adam優化器來編譯模型。採用10個epochs和batch_size為100來訓練模型。完整代碼如下:

from keras.datasets import mnist
import numpy asnp
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import  Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from keras importbackend
backend.set_image_data_format('channels_first')


# 設定隨機種子
seed = 7
np.random.seed(seed)

# 從Keras導入Mnist數據集
(X_train, y_train), (X_validation, y_validation) = mnist.load_data()

X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
X_validation = X_validation.reshape(X_validation.shape[0],1, 28, 28).astype('float32')

# 格式化數據到0-1之前
X_train = X_train / 255
X_validation = X_validation / 255

# one-hot編碼
y_train = np_utils.to_categorical(y_train)
y_validation = np_utils.to_categorical(y_validation)

# 創建模型
def create_model():
    model = Sequential()
    model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(units=128, activation='relu'))
    model.add(Dense(units=10, activation='softmax'))

    # 編譯模型
    model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
    return model

model = create_model()
model.fit(X_train, y_train, epochs=10, batch_size=200, verbose=2)

score = model.evaluate(X_validation, y_validation, verbose=0)
print('CNN_Small:%.2f%%' % (score[1] * 100))

 

執行代碼得到模型的準確度使99.05%。在訓練時verbose設置為2,進輸入每個epoch的最終結果,忽略在每一個epoch的詳細內容。輸出結果如下:

Epoch 1/10

161s - loss: 0.2310 - acc: 0.9344

Epoch 2/10

151s - loss: 0.0737 - acc: 0.9780

Epoch 3/10

144s - loss: 0.0532 - acc: 0.9838

Epoch 4/10

148s - loss: 0.0402 - acc: 0.9879

Epoch 5/10

147s - loss: 0.0335 - acc: 0.9894

Epoch 6/10

155s - loss: 0.0275 - acc: 0.9916

Epoch 7/10

154s - loss: 0.0232 - acc: 0.9928

Epoch 8/10

141s - loss: 0.0204 - acc: 0.9935

Epoch 9/10

139s - loss: 0.0168 - acc: 0.9945

Epoch 10/10

138s - loss: 0.0142 - acc: 0.9957

CNN_Small: 99.05%

13.5 複雜卷積神經網絡

剛剛創建一個簡單的卷積神經網絡,在卷積神經網絡中可以使用多個卷積層,接下來就定義一個採用多個卷積層的卷積神經網絡。網絡拓撲結構如下:

              I.        卷積層,具有30個特徵圖,感受野大小為5x5。

            II.        採樣因子(pool_size)為2x2 的池化層。

          III.        卷積層,具有15個特徵圖,感受野大小為3x3。

          IV.        採樣因子(pool_size)為2x2 的池化層。

            V.        Dropout概率為20%的Dropout層。

          VI.        Flatten層。

        VII.        具有128個神經元和relu激活函數的全全聯接層。

       VIII.        具有50個神經元和relu激活函數的全全聯接層。

          IX.        輸出層。

採用與簡單卷積神經網絡相同的編譯方式和訓練方法,完整代碼如下:

from keras.datasets import mnist
import numpy asnp
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import  Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from keras importbackend
backend.set_image_data_format('channels_first')


# 設定隨機種子
seed = 7
np.random.seed(seed)

# 從Keras導入Mnist數據集
(X_train, y_train), (X_validation, y_validation) = mnist.load_data()

X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
X_validation = X_validation.reshape(X_validation.shape[0],1, 28, 28).astype('float32')

# 格式化數據到0-1之前
X_train = X_train / 255
X_validation = X_validation / 255

# one-hot編碼
y_train = np_utils.to_categorical(y_train)
y_validation = np_utils.to_categorical(y_validation)

# 創建模型
def create_model():
    model = Sequential()
    model.add(Conv2D(30, (5, 5), input_shape=(1, 28, 28), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Conv2D(15, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(units=128, activation='relu'))
    model.add(Dense(units=50, activation='relu'))
    model.add(Dense(units=10, activation='softmax'))

    # 編譯模型
    model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
    return model

model = create_model()
model.fit(X_train, y_train, epochs=10, batch_size=200, verbose=2)

score = model.evaluate(X_validation, y_validation, verbose=0)
print('CNN_Large:%.2f%%' % (score[1] * 100))

 

可以看到識別的準確度為99.18%,有一定程度的提升。當準確度在90%以上是即使輕微的提升也是難能可貴。執行結果如下:

Epoch 1/10

176s - loss: 0.3918 - acc: 0.8804

Epoch 2/10

163s - loss: 0.0954 - acc: 0.9708

Epoch 3/10

169s - loss: 0.0694 - acc: 0.9787

Epoch 4/10

177s - loss: 0.0563 - acc: 0.9826

Epoch 5/10

155s - loss: 0.0478 - acc: 0.9851

Epoch 6/10

154s - loss: 0.0433 - acc: 0.9862

Epoch 7/10

156s - loss: 0.0383 - acc: 0.9877

Epoch 8/10

154s - loss: 0.0343 - acc: 0.9893

Epoch 9/10

153s - loss: 0.0320 - acc: 0.9902

Epoch 10/10

153s - loss: 0.0273 - acc: 0.9910

CNN_Large: 99.18%

相關焦點

  • 手把手教你學Python之手寫數字識別
    問題描述:手寫數字識別是指給定一系列的手寫數字圖片以及對應的數字標籤,構建模型進行學習,目標是對於一張新的手寫數字圖片能夠自動識別出對應的數字
  • 使用AI算法進行手寫數字識別
    但這些都不是本文討論的重點,本文主要以機器學習初學者的身份,使用最基本的機器學習算法,加以微積分、線性代數、概率統計等基礎數學知識,來解決手寫數字的識別的問題。為什麼要去研究數字的識別問題呢?因為最近剛過雙11,又看了到許多曝光快遞行業野蠻分揀的新聞。
  • 小白學機器學習|如何識別5000多個手寫數字
    今天我接著來分享一篇好玩的機器學習例子,我們如何識別手寫數字。怎麼玩呢:了解這個5000多個手寫數子清洗數據並用機器學習算法訓練讓機器來識別數字超參數調整提高準確率1.介紹一下這個數據集這個數據集也是非常有名的,是入門的經典數據集,而且時間也蠻久的了!
  • 構建深度學習3-手寫數字識別
    我們堅信,只有動手創建一個模型,才能真正掌握一個模型,本系列全是用Python代碼創建深度學習,不直接用現成的框架。
  • 漢王推出全新手寫識別金豬版手寫軟體
    它不僅支持在Vista系統下運行,還大大簡化了操作界面,對手寫識別的核心技術也做了全面升級。相較之前的版本,「金豬版」手寫軟體使用更簡單,功能更強大,也將漢王力求讓用戶「少點、少寫、越寫越快」的原則體現的更為淋漓盡致。    初打開「金豬版」手寫軟體,會發現其操作界面與之前的11.0版相比有了很大變化:數字區和符號區被取消,工具欄也相應簡化。
  • 靈雲手寫識別平臺 讓手寫輸入行雲流水
    靈雲智能手寫識別平臺是提供單一技術能力的靈雲全智能能力平臺系列產品之一,該平臺採用了捷通華聲打磨16年之久的iWrite手寫識別引擎,支持中文行寫、疊寫,以及西文連筆手寫,識別準確率高達99%,讓手寫輸入行雲流水,一氣呵成。
  • 10 行代碼,實現手寫數字識別
    聽說世界上只有百分之3的人關注Jayson,很幸運你是其中一位識別手寫的阿拉伯數字,對於人類來說十分簡單,但是對於程序來說還是有些複雜的
  • 深度學習系列:PaddlePaddle之手寫數字識別
    不過呢,這塊內容太複雜了,所以就簡單的介紹一下paddlepaddle的第一個「hello word」程序----mnist手寫數字識別。下一次再介紹用PaddlePaddle做分布式訓練的方案。其實之前也寫過一篇用CNN識別手寫數字集的文章是用keras實現的,這次用了paddlepaddle後,正好可以簡單對比一下兩個框架的優劣。什麼是PaddlePaddle?
  • 深度學習綜合案例:手寫數字識別
    在前文了解了卷積神經網絡的原理,接下看如何用卷積神經網絡處理MNIST數據集,實現對手寫數字識別。
  • 前沿 | 生物神經網絡與機器學習的碰撞,Nature論文提出DNA試管網絡識別手寫數字
    該網絡解決了一個經典的機器學習問題:正確識別手寫數字。該項研究中,研究者用了 36 個手寫數字 6 和 7 作為測試例子,結果表明這種新型神經網絡能夠正確識別出所有的數字。該研究是在生物工程助理教授 Lulu Qian 的實驗室中完成的。相關論文於 7 月 4 日上傳網絡,並將出現在 7 月 19 日的紙質版《Nature》雜誌上。
  • TF2.0深度學習實戰(一):分類問題之手寫數字識別
    手寫數字識別是一個非常經典的圖像分類任務,經常被作為深度學習入門的第一個指導案例。相當於我們學程式語言時,編寫的第一個程序「Hello World !」。不一樣的是,入門深度學習,需要有一定量的理論基礎。手寫數字識別是基於MNIST數據集的一個圖像分類任務,目的是通過搭建深度神經網絡,實現對手寫數字的識別(分類)。
  • 深度學習筆記13:Tensorflow實戰之手寫mnist手寫數字識別
    個人公眾號:數據科學家養成記 (微信ID:louwill12)前文傳送門:深度學習筆記1:利用numpy從零搭建一個神經網絡深度學習筆記2:手寫一個單隱層的神經網絡深度學習筆記3:手動搭建深度神經網絡(DNN)深度學習筆記4:深度神經網絡的正則化深度學習筆記5:正則化與dropout
  • 基於TensorFlow卷積神經網絡與MNIST數據集設計手寫數字識別算法
    隨著數位化的普及和信息技術的發展,在編號處理、數量讀取、價格統計等場合,手寫數字識別系統的應用需求越來越強烈,如何將數字方便、快速地輸入到計算機中已成為關係到計算機技術普及的關鍵問題。數字識別技術的研究不僅可以解決當下面臨的數字識別問題,同時在圖像識別、機器學習等方面也有鋪墊作用。
  • 使用sklearn隨機森林算法實現手寫數字識別
    二:sklearn中隨機森林算法函數使用基於sklearn中隨機森林算法函數創建隨機森林實現mnist手寫數字識別,完整的代碼實現如下:from sklearn.ensemble import RandomForestClassifierfrom sklearn.metrics import accuracy_scoreimport
  • 菜鳥深度學習教程:識別手寫數字
    MNIST(手寫數字分類)和CIFAR-10(飛機,汽車,鳥,貓,鹿,狗,蛙,馬,船,卡車十種不同小圖片分類)是已制定的機器學習標準,本文會儘量達到這些標準.深度的改變,能使我們直接將原始的輸入數據加入網絡當中.過去,通過精心設計的特徵函數從輸入提取出特徵,單層的神經網絡運行其上.這意味著,對於像計算機視覺,語音識別,自然語言處理這些問題,阻礙科學跨領域合作,我們需要明顯不同的方法.然而,當一個網絡具有多個隱含層的時候,它自身就能夠學會最佳的描述原始數據的特徵函數,因此可應用於端對端學習,並且可以在多種多樣的任務中使用同一個網絡,從流程中去除特徵函數設計
  • 詳解與實戰TensorFlow MNIST手寫體數字識別(softmax and cnn)
    更多人關注的公眾號:機器學習算法與Python精研編輯|魚大來源|githubMNIST是一套手寫體數字的圖像數據集
  • 實戰|手把手入門神經網絡,74行代碼實現手寫數字識別
    二、 我們要解決的問題:手寫數字識別手寫數字識別是機器學習領域中一個經典的問題,是一個看似對人類很簡單卻對程序十分複雜的問題。回到手寫數字識別,比如我們要識別出一個手寫的「9」,人類可能通過識別「上半部分一個圓圈,右下方引出一條豎線」就能進行判斷。但用程序表達就似乎很困難了,你需要考慮非常多的描述方式,考慮非常多的特殊情況,最終發現程序寫得非常複雜而且效果不好。
  • OCR文字識別——手寫漢字識別(一)
    2、文本定位+文本識別  隨著目標檢測算法的發展,漸漸出現了一種以「文本定位」+「文本識別」的不定長文本識別方法,利用目標檢測算法(如ssd、yolo)定位出每一行字,然後利用CRNN+CTC的方式進行不定長文本識別,直接識別出一行文字。這種方法目前應該是主流的ocr方法。
  • ActivInspire「手寫識別」與「形狀識別」
    《馨藝雅閣 》微 信號:tcxpmgzs歡迎關注    教育文化類公眾號    欄目分類互動課堂 | 墨舞書香 | 教育隨筆 | 家有萌寶 | 青春校園作者:陶長霞普米的筆工具還具有「手寫識別」和「形狀識別」的本領。
  • 捷通華聲靈雲手寫英文連筆識別再獲突破
    【IT168 資訊】靈雲科技訊:6月7日,捷通華聲靈雲平臺(www.hcicloud,com)發布最新版英文連寫引擎——FreeStylus 7.0,此款引擎具備支持英文整句輸入、自然連筆書寫、識別率高、備選詞智能等優點,靈雲手寫識別技術在國內已擁有50%的市場份額,此次升級將使靈雲手寫識別技術更加廣泛應用於帶觸控螢幕的各種智能設備上