機器學習入坑指南(九):TensorFlow 實戰——手寫數字識別(MNIST 數據集)

上篇文章簡要介紹了「深度學習」,接下來,咱們將從最經典的例子入手進行實戰。html

1、背景知識簡介

1 TensorFlow

Tensor:張量(即多維數組),Flow:(數據)流python

TensorFlow,是一個使用數據流圖(data flow graohs)技術來進行科學計算的開源軟件庫,它由Google Brain 團隊開發,被普遍應用於各類感知和語言理解任務的機器學習。git

點擊訪問:TensorFlow 官網,能夠查閱官方文檔、獲取一手資訊和下載最新版本。github

或者訪問:GitHub - tensorflow 來達到一樣的效果api

英文閱讀有困難的同窗參考:TensorFlow 中文文檔數組

在本次實戰中咱們還將使用 Keras,它是一個基於 Theano(另外一個開源庫)和 TensorFlow 構建的高級神經網絡 API,可以在 Theano、TensorFlow 或 Microsoft Cognitive Toolkit 上運行。網絡

點擊訪問:Keras 中文文檔機器學習

2 MNIST 數據集

在上篇文章中咱們已經提到過 MNIST 了,它是一個收錄了許多 28 x 28 像素手寫數字圖片(以灰度值矩陣存儲)及其對應的數字的數據集,能夠把它理解成下圖這個樣子:
MNIST 數據集
圖片來源:3Blue1Brown 的視頻,強烈推薦觀看系列視頻:B 站播放地址函數

2、Python 實現

這裏咱們依舊使用 Jupyter Notebook 做爲開發環境,沒有使用過的同窗參考個人文章「機器學習入坑指南(一):Python 環境搭建」性能

固然,使用 Pycharm 等 IDE 也沒有問題。

1 安裝並導入 TensorFlow、Keras

在 Anaconda 終端中輸入命令

conda install tf-nightly

或輸入(Python Shell 中也可使用此命令)

pip install tf-nightly

Keras 已經被集成進了 TensorFlow 中。咱們能夠經過 tensorflow.keras來訪問它。

接下來,導入這兩個庫

import tensorflow.keras as keras
import tensorflow as tf

能夠經過簡單的代碼測試導入是否成功

print(tf.__version__)

2 導入並測試 MNIST 數據集

Keras 默認從 googleapis 下載 MNIST,若是沒法訪問,可在 GitHub 上下載,點擊這裏,下載到本地後更改 mnist.py 中的引用路徑。

TensorFlow 中存在多個 mnist.py ,這裏咱們須要修改的是 Keras 下的,個人路徑爲
cmd C:\ProgramData\Anaconda3\Lib\site-packages\tensorflow\python\keras\datasets

打開以後,把

origin_folder = 'https://storage.googleapis.com/tensorflow/tf-keras-datasets/'

中的路徑修改成你存放數據集的位置便可。進入正題

mnist = tf.keras.datasets.mnist #導入mnist
(x_train,y_train),(x_test,y_test) = mnist.load_data() #分割
print(x_train[0]) # 查看第一個測試數據的輸入

而後你就看到了以下的輸出:

讓咱們把這個矩陣用圖像表示出來

import matplotlib.pyplot as plt
%matplotlib inline # 加上這句才能顯示圖像
plt.imshow(x_train[0],cmap=plt.cm.binary) # 顯示黑白圖像
plt.show()

能夠經過如下代碼對數據進行歸一化處理

x_train = tf.keras.utils.normalize(x_train, axis=1)
x_test = tf.keras.utils.normalize(x_test, axis=1)

再次查看圖像

plt.imshow(x_train[0],cmap=plt.cm.binary)
plt.show()

圖像的像素值被限定在了 [0,1] 。能夠經過

print(x_train[0])

查看矩陣數據。

3 構建與訓練模型

終於進入核心環節了。在這裏,咱們使用 Keras 的 Sequential 模型(順序模型)。Sequential 模型是最經常使用的模型,也就是一個按照順序向前傳遞的神經網絡。

model = tf.keras.models.Sequential()

接下來爲模型添加圖層。神經網絡的輸入層是一個一維向量,因此咱們須要把輸入的圖像矩陣展平,從 28 x 28 變爲 1 x 784 。Keras 爲咱們提供了以下方法:

model.add(tf.keras.layers.Flatten())

以後,爲神經網絡添加隱藏層。這裏咱們使用最簡單的 Dense 層(即全鏈接層,每個神經元與先後兩層的全部神經元相連)

model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))

這個層有 128 個單元,激活函數選擇 reLU,最初人們喜歡用 Sigmoid 函數,但後來發現 reLU 效果更好,因此能夠當作一個默認的選擇。

接下來再加入一個相同的層

model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))

再加入輸出層

model.add(tf.keras.layers.Dense(10, activation=tf.nn.softmax))

輸出層有 10 個結點,表明 10 種不一樣的數字。這裏使用 softmax 函數做爲激活函數,由於咱們想要找到預測結果的機率分佈。(使用 reLU 獲得的數字並無這個意義)

咱們構建出的模型大概是這個樣子的(示意圖來自 3Blue1Brown,隱藏層只有 16 個單元,實際上咱們有 128 個)

添加好全部的層後,「編譯」這個模型。

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

optimizer 即優化器,咱們通常默認使用 adam
loss 指損失函數,這裏咱們將其指定爲 sparse_categorical_crossentropy,即計算分類結果的交叉熵損失。
metrics 列表,參數爲評估模型性能的指標,典型用法即 metrics=['accuracy']

最後,擬合這個模型

model.fit(x_train, y_train, epochs=3)

在訓練的過程當中,咱們會發現損失值(loss)在下降,而準確度(accuracy)在提升,最後達到了一個使人滿意的程度。

4 測試模型

讓咱們利用測試集試試這個模型是否是真的學會了識別數字

val_loss, val_acc = model.evaluate(x_test, y_test)
print(val_loss)
print(val_acc)


損失和準確度看起來還湊合,嘗試識別訓練集

predictions = model.predict(x_test)
print(predictions)


看不出來這是個啥?別急,用 argmax 解析一下(就是找出最大數對應的索引,即爲識別出的數字)

import numpy as np

print(np.argmax(predictions[0]))


啊哈,來看看 x_test[0] 這個圖像是什麼樣的

plt.imshow(x_test[0],cmap=plt.cm.binary)
plt.show()

OK,妥妥的,相信你也認爲這就是個 7,咱們的模型已經能夠識別數字啦!固然,這只是一個簡單的開始,後面的路還有很長,要多思考多動手,堅持學習,才能早日成爲大牛!

最後附上能夠跑起來的完整代碼,來自Deep Learning basics with Python, TensorFlow and Keras p.1

import tensorflow as tf  # 深度學習庫,Tensor 就是多維數組

mnist = tf.keras.datasets.mnist  # mnist 是 28x28 的手寫數字圖片和對應標籤的數據集
(x_train, y_train),(x_test, y_test) = mnist.load_data()  # 分割數據集

x_train = tf.keras.utils.normalize(x_train, axis=1)  # 把數據值縮放到 0 到 1
x_test = tf.keras.utils.normalize(x_test, axis=1)  

model = tf.keras.models.Sequential()  # 基礎的前饋神經網絡模型
model.add(tf.keras.layers.Flatten())  # 把圖片展平成 1x784
model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))  # 簡單的全鏈接圖層,,128 個單元,激活函數爲 relu
model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu)) 
model.add(tf.keras.layers.Dense(10, activation=tf.nn.softmax))  # 輸出層 ,10 個單元, 使用 Softmax 得到機率分佈

model.compile(optimizer='adam',  # 默認的較好的優化器
              loss='sparse_categorical_crossentropy',  # 評估「錯誤」的損失函數,模型應該儘可能下降損失
              metrics=['accuracy'])  # 評價指標

model.fit(x_train, y_train, epochs=3)  # 訓練模型

val_loss, val_acc = model.evaluate(x_test, y_test)  # 評估模型對樣本數據的輸出結果
print(val_loss)  # 模型的損失值
print(val_acc)  # 模型的準確度

您的認真閱讀就是對我最大的鼓勵!若是以爲個人文章對您有幫助,想要和我一塊兒不斷學習新的知識、不斷進步,歡迎點擊頭像旁邊的「關注」按鈕,讓我好跟基友們吹個牛逼!

歡迎關注 evan 的博客

相關文章
相關標籤/搜索