標籤:

使用TensorFlow分類手寫數字

回到2013年,我寫了一篇關於使用Python進行數字識別的帖子。 從那時起,Python數據生態系統發生了很大變化。 Google給了我們Tensorflow,scikit-learn已經成熟,「AI」現在是最新的熱潮。

所以我認定是時候把精力放到手寫識別這個領域。 它仍然是一個非常簡單,但迷人的概念:收集某人的手寫素材,並試圖預測這個人寫的東西。 好消息是,在過去幾年我們已經學習並掌握了幾個新的技巧,我會在這裡與大家分享一些。

近幾年來的顯著區別

PS: 想直接體驗應用嗎? 在這裡查看:

Yhat: End-to-End Data Science Platform

1我們在做什麼

其中之一我想改變手寫識別器的是使它更「實時」。 而不是讓用戶繪製的東西,然後點擊「猜」,如果應用程序主動嘗試弄清楚你正在繪製什麼是不是更有趣呢?

為此,我們需要一種途徑使得在用戶繪製數字時調用我們的模型。 這可能看起來很簡單,但這意味著我們可以(1)對圖像做足夠快的預測以跟上某人的手寫,(2)我們可以從我們的應用程序(可能使用像Javascript)來回收發預測。

幸運的是,自從我寫的第一篇文章以來,Yhat做了一些大的性能改進:它現在可以做幾千個預測每秒,而不是幾年前500-700個。

2數據

製作一個不斷進行預測的應用程序的後果之一是我們需要對不完整數據進行模型訓練。

讓我們假設你寫了一半數字5. 這可能看起來像一個6,9,甚至1(取決於你的書法風格)。 為了處理這些種類的部分數據情況,我們需要在部分完成的數字上(或在我們的提供圖像)收集數據。

為此,我做了一個小的Web應用程序,執行以下操作

  1. 用空白畫布呈現訪問者並要求他們繪製一個隨機數字。

  2. 當用戶繪製數字時,將圖像保存到S3桶(分類和標記)

  3. 一旦用戶完成,選擇一個新的數字並重複步驟一和二

說服我的同事後,我們很興奮的完成超過80000 個圖片。

我們收集在不同的繪製階段總共超過8萬個數字。 為了將這些圖像轉換為Python我使用了skimage庫,它提供了一個一致的、在OpenCV、scipy和其他python圖像工具易於使用的API。

你可以看到通過循環每個圖像文件並使用get_image_data函數將其轉換為numpy數組。 get_image_data獲取一個圖像文件,並執行以下操作:

  • 打開它,並將其作為數組讀入python

  • 將其從彩色轉換為灰度(節省大小)

  • 將圖片縮小25x(這可能看起來很多,但它不會對我們的分類產生顯著差異)

  • 將其從2維陣列(20×20)平鋪到1維陣列(1×400)

def get_image_data(filename):

img = io.imread(f, as_grey=True)

return transform.downscale_local_mean(img, (25, 25)).

flatten( )

data = [ ]

labels = [ ]

for i, (label, filename) in enumerate(files):

image = get_image_data(filename)

data.append(image)

classes = np.zeros(10)

classes[label] = 1.0

labels.append(classes)

if i%100==0:

print " %d of %d (%2f)" % (i, len(files), float(i) / len(files))

下一步是構建一個可以解釋它們的分類器!

3分類我們的圖片

分類手寫數字是機器學習庫中相當常見的教程/教科書問題。 MNIST數據集通常被引用,您可以在諸如scikit-learn,Tensorflow和Keras等庫的文檔中找到它。 所以幸運的是,我們有很多偉大的起點。 我們的問題可以簡化為應用其中的示例我們的探索中。

對於這篇文章,我決定使用Tensorflow。 他們實際上有兩個使用MNIST數據集構建分類器的示例,這對我們非常方便!

  • 基本示例

  • 高級示例

我將使用現在的基本示例,因為它使用更少的代碼和更直接。

4模型代碼

Tensorflow需要基於對基礎圖/網路中大量的「底層」理解和配置。 說實話,我不會推薦使用它,除非你相信你知道你在做什麼。

設置我們的模型,我們將創建「佔位符」變數(如下面的x)。 這些佔位符在實例化時不會執行。 相反,評估將延遲,直到您實際操作您的數據。

我們還將創建2個變數,W和b,它們代表我們模型的「權重」和「偏差」。 最初,我們將它們全部設置為0,但是一旦我們開始訓練我們的模型,這些變數將被更新以反映訓練數據。

最後,我們將使用tf.nn.softmax定義我們的模型。 在這種情況下,我們使用softmax演算法,但有很多其他選項可用。

import tensorflow as tf

x = tf.placeholder(tf.float32, [None, len(data[0])])

W = tf.Variable(tf.zeros([len(data[0]), 10]))

b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)

除了模型,我們還需要定義優化器如何進行訓練。

y_ = tf.placeholder(tf.float32, [None, 10])

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

train_step = tf.train.GradientDescentOptimizer(0.5).

minimize(cross_entropy)

好,到這一步。只需完成初始化變數的任務,並開始tensorflow任務的執行!

init = tf.initialize_all_variables( )

sess = tf.Session( )

sess.run(init)

5訓練

現在一切都設置完畢:我們可以開始訓練我們的模型。 Tensorflow是很好的,因為它支持迭代訓練 - 這意味著你不必在單步或單線(你認為scikit-learn)做到100%的訓練。 所以,當你獲得更多的數據,你可以更新你的模型和微調你的權重。下面你可以看到實際的訓練代碼。 我們每次在1000個數據點上進行10,000批訓練。 我寫了一個幫助函數叫next_batch隨機提供給模型數據。

def next_batch(n):

idx = np.random.randint(0, len(data), n)

return data[idx], labels[idx]

for i in range(10000):

batch_xs, batch_ys = next_batch(1000)

sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

if i%100==0:

print " epoch %d" % i

6做預測

好的,現在我們有我們的模型,我們可以開始做預測! 這在tenserflow中非常不直觀,但是我沒有寫API:

print sess.run(y, feed_dict={x: mnist.test.images })

我繼續使用ScienceOps(無恥的插件)部署這個模型,並關聯到的應用程序上。 我現在可以在用戶繪製特定數字時實時生成預測。 相當精巧! 我的模型耗費了些許精力,但它是非常酷,看到它的預測變得更好,當你給它更多的信息(當你接近完成你的繪圖)。

文章來源 / The Yhat Blog

原文作者 / Greg

譯 / 劉霄陽

編輯 / 珺妹妹, ZZ

推薦閱讀:

TensorFlow 教程 #04 - 保存 & 恢復
關於Tensorflow的一些想法?
學習tensorflow,買什麼筆記本好?
實踐指南!16位資深行業者教你如何學習使用TensorFlow

TAG:TensorFlow |