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


欲直接下載代碼文件,關注我們的公眾號哦!查看歷史消息即可!

手寫筆記還是電子筆記好呢?

畢業季剛結束,眼瞅着2018級小萌新馬上就要來了,老臘肉小編為了咱學弟學妹們的學習,絞盡腦汁准備編一套大學秘籍,這不剛開了個頭就遇上了個難題——做筆記到底是手寫筆記好呢還是電子筆記好呢?

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

大家用電子筆記除了省紙張外,往往還希望有筆記整理和搜索的功能,手寫電子筆記如果不能實現手寫識別搜索的功能,那還真是只能省紙張了。為此小編親自體驗過GoodNotes這款手寫筆記應用,雖然能夠做到手寫識別搜索,但需要字跡工整,不能連筆,大概能勸退一批包括小編在內的字跡感人群體了吧。

image

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

首先給大家學習該篇內容的思維導圖,如果有沒講到的細節,請自行參考學習:

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],預測成功!說明訓練出來的模型識別數字的能力還是挺強的。

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

手寫電子筆記的福音啊!

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM