10分鐘教你用python 30行代碼搞定簡單手寫識別!

欲直接下載代碼文件,關注咱們的公衆號哦!查看歷史消息便可!python

手寫筆記仍是電子筆記好呢?算法

畢業季剛結束,眼瞅着2018級小萌新立刻就要來了,老臘肉小編爲了咱學弟學妹們的學習,絞盡腦汁準備編一套大學祕籍,這不剛開了個頭就趕上了個難題——作筆記究竟是手寫筆記好呢仍是電子筆記好呢?編程

聰明的小夥伴們或許就該懟小編了,不是有電子手寫筆記嗎!哼,機智如我怎麼可能沒想過這個呢!數組

你們用電子筆記除了省紙張外,每每還但願有筆記整理和搜索的功能,手寫電子筆記若是不能實現手寫識別搜索的功能,那還真是隻能省紙張了。爲此小編親自體驗過GoodNotes這款手寫筆記應用,雖然可以作到手寫識別搜索,但須要字跡工整,不能連筆,大概能勸退一批包括小編在內的字跡感人羣體了吧。網絡

image

那麼到底怎麼實現手寫識別呢?本期魔術師就來教會你們如何用簡單的編程實現看似高深的手寫識別技術。參考網上的一些教程,咱們將展現用tensorflow實現MNIST手寫識別的例子。app

首先給你們學習該篇內容的思惟導圖,若是有沒講到的細節,請自行參考學習:框架

MNIST 數據集來自美國國家標準與技術研究所,National Institute of Standards and Technology (NIST)。訓練集 (training set) 由來自 250 個不一樣人手寫的數字構成,其中 50% 是高中學生, 50% 來自人口普查局 (the Census Bureau) 的工做人員。測試集(test set) 也是一樣比例的手寫數字數據。機器學習

先給你們介紹一下tensorflow吧。編程語言

tensorflow是谷歌於2015年11月9日正式開源的計算框架。tensorflow計算框架能夠很好地支持深度學習的各類算法,但它的應用也不限於深度學習,是由Jeff Dean領頭的谷歌大腦團隊基於谷歌內部第一代深度學習系統DistBelief改進而來的通用計算框架。函數

咱們經過基於python3的編程語言調用tensorflow這一框架。

下載方式參考以下:

入門捷徑:線性迴歸

咱們看一個最簡單的機器學習模型,線性迴歸的例子。

狹義的最小二乘方法,是線性假設下的一種有閉式解的參數求解方法,最終結果爲全局最優。

梯度降低法,是假設條件更爲普遍(無約束)的,一種經過迭代更新來逐步進行的參數優化方法,最終結果爲局部最優。

而咱們經過調用Tensorflow計算梯度降低的函數tf.train.GradientDescentOptimizer來實現優化。

咱們看下這個例子代碼,只有30多行,邏輯仍是很清晰的。

最終會獲得一個接近2的值,好比我此次運行的值爲1.9183811

線性模型:logistic迴歸

線性迴歸不過癮,咱們直接一步到位,開始進行手寫識別。

咱們採用深度學習三巨頭之一的Yann Lecun教授的MNIST數據爲例。 如上圖所示,MNIST的數據是28x28的圖像,而且標記了它的值應該是什麼。

咱們先看看數據是怎樣從圖片一步步轉化爲咱們的預測的:

咱們能夠獲取到的數據在編譯器裏是以矩陣形式存儲的,以下:

teX爲10000乘784的矩陣,teY爲10000乘10的矩陣,10000表示例子的數目,784就是28x28個像素點,由於有10種不一樣的數字,因此teY的另外一維度爲10,每一維的值用來判斷是不是該維對應的數字。teX,teY構成了訓練集的數據。同理,trX,trY爲測試集。

接下來要介紹的部分都只是模型構建的部分不一樣,你們能夠參考上面數據的轉化圖片進行理解。

咱們首先無論三七二十一,就用線性模型來作分類。

算上註釋和空行,一共加起來30行左右,咱們就能夠解決手寫識別這麼困難的問題啦!請看代碼:

通過100輪的訓練,咱們的準確率是92.36%。

無腦的淺層神經網絡

用了最簡單的線性模型,咱們換成經典的神經網絡來實現這個功能。

咱們仍是無論三七二十一,創建一個隱藏層,用最傳統的sigmoid函數作激活函數。sigmoid的數學形式以下:

其核心邏輯仍是矩陣乘法,這裏面沒有任何技巧。

    h = tf.nn.sigmoid(tf.matmul(X, w_h)) 
       return tf.matmul(h, w_o)

完整代碼以下,仍然是40多行,不長:

第一輪運行,我此次的準確率只有69.11% ,第二次就提高到了82.29%。跑100輪的最終結果是95.41%,比Logistic迴歸的強!

請注意咱們模型的核心那兩行代碼,徹底就是無腦地全鏈接作了一個隱藏層而己,這其中沒有任何的技術。徹底是靠神經網絡的模型能力。

深度學習時代方案 - ReLU和Dropout

咱們將sigmoid函數換成ReLU函數。

線性整流函數(Rectified Linear Unit, ReLU),又稱修正線性單元, 是一種人工神經網絡中經常使用的激活函數(activation function),一般指代以斜坡函數及其變種爲表明的非線性函數。

固然,Dropout也是要作的,Dropout能夠比較有效地減輕過擬合的發生,必定程度上達到了正則化的效果。因而咱們仍是一個隱藏層,寫個更現代一點的模型吧:

    X = tf.nn.dropout(X, p_keep_input)

    h = tf.nn.relu(tf.matmul(X, w_h)) 

    h = tf.nn.dropout(h, p_keep_hidden) 

    h2 = tf.nn.relu(tf.matmul(h, w_h2))

    h2 = tf.nn.dropout(h2, p_keep_hidden) 

    return tf.matmul(h2, w_o)

除了ReLU和dropout這兩個技巧,咱們仍然只有一個隱藏層,表達能力沒有太大的加強。並不能算是深度學習。

從結果看到,第二次就達到了96%以上的正確率。後來就一直在98.4%左右遊蕩。僅僅是ReLU和Dropout,就把準確率從95%提高到了98%以上。

卷積神經網絡出場

接下來,真正的深度學習利器CNN,卷積神經網絡出場。此次的模型比起前面幾個無腦型的,的確是複雜一些。涉及到卷積層和池化層。

咱們看下此次的運行數據:

    0 0.95703125
    1 0.9921875
    2 0.9921875
    3 0.98046875
    4 0.97265625
    5 0.98828125
    6 0.99609375

在第6輪的時候,就跑出了99.6%的高分值,比ReLU和Dropout的一個隱藏層的神經網絡的98.4%大大提升。由於難度是越到後面越困難。

在第16輪的時候,居然跑出了100%的正確率:

    7 0.99609375
    8 0.99609375
    9 0.98828125
    10 0.98828125
    11 0.9921875
    12 0.98046875
    13 0.99609375
    14 0.9921875
    15 0.99609375
    16 1.0

藉助Tensorflow和機器學習工具,咱們只有幾十行代碼,就解決了手寫識別這樣級別的問題,並且準確度能夠達到如此程度。

模型結果展現

說了這麼多模型,咱們來作個對比:

模型實踐顯神威

咱們再用手寫的圖片試驗一下模型的效果,手寫圖片以下:

圖片處理的方式以下:

    import numpy as np

    from PIL import Image

    img=Image.open(r'圖片文件路徑').convert('L')

    # resize的過程

    if img.size[0] != 28 or img.size[1] != 28:

        img = img.resize((28, 28))

    # 暫存像素值的一維數組

    arr = []

    for i in range(28):

        for j in range(28):

            # mnist 裏的顏色是0表明白色(背景),1.0表明黑色

            pixel = 1.0 - float(img.getpixel((j, i)))/255.0

            # pixel = 255.0 - float(img.getpixel((j, i))) # 若是是0-255的顏色值

            arr.append(pixel)

    arr1 = np.array(arr).reshape((1, 28, 28, 1))#arr1就是輸入模型的圖像數據

咱們能夠看到,圖片導入到編譯器裏後存儲爲了一個矩陣,矩陣裏面的數字表明瞭每個像素點。

輸出結果分別爲[2]和[3],預測成功!說明訓練出來的模型識別數字的能力仍是挺強的。

據說最近蘋果霸霸又申請了一項新專利——實時手寫識別技術。

手寫電子筆記的福音啊!

連蘋果都在研究的技術,我們也能小秀一把,是否是超開心
欲直接下載代碼文件,關注咱們的公衆號哦!查看歷史消息便可!

相關文章
相關標籤/搜索