1. 程式人生 > >TensorFlow實現機器學習的“Hello World”--Mnist手寫數字識別

TensorFlow實現機器學習的“Hello World”--Mnist手寫數字識別

TensorFlow實現機器學習的“Hello World”

上一篇部落格我們已經說了TensorFlow大概怎麼使用,這次來說說機器學習中特別經典的案例,也相當於是機器學習的“Hello World”,他就是Mnist手寫數字識別,也就是通過訓練機器讓他能看懂手寫的阿拉伯數字。

1.系統是ubuntu 16.04 LTS
2.我用的是sublime text3搭建的Python開發環境
3.Python用的是3.5
4.TensorFlow用的是0.12.0,only cpu

一.Mnist資料集準備

  • 首先要進行機器訓練就必須要有訓練的資料,那我們今天的就是Mnist的資料集,那極客學院已經幫我們把這份資料都打包好了,只要在Python裡面執行以下程式碼就可以,複製進去可以直接執行一次。
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import gzip
import os
import tempfile

import numpy
from six.moves import urllib
from six.moves import xrange  # pylint: disable=redefined-builtin
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets.mnist import
read_data_sets
  • 然後你要使用這份資料按照以下程式碼匯入就可以(極客學院的教程裡面的程式碼匯入進去會無法執行,原因未知,所以使用我下面這段程式碼吧)
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
  • 那到此你就已經準備好了資料集
    下載下來的資料集被分成兩部分:60000行的訓練資料集(mnist.train)和10000行的測試資料集(mnist.test)。詳細的分析建議看極客網Mnist教程。

二、構建TensorFlow模型

A.構建模型

首先我們要使用TensorFlow,就需要匯入它:

import tensorflow as tf

我們通過操作符號變數來描述這些可互動的操作單元,簡單的說就是需要一個輸入值:

x = tf.placeholder(tf.float32, [None, 784])
  • x不是一個特定的值,而是一個佔位符placeholder,我們在TensorFlow執行計算時輸入這個值。我們希望能夠輸入任意數量的MNIST影象,每一張圖展平成784維的向量。我們用2維的浮點數張量來表示這些圖,這個張量的形狀是[None,784 ]。(這裡的None表示此張量的第一個維度可以是任何長度的。)

在構建機器學習神經元網路的時候,有兩個特別重要的值就是權重值和偏置量,TensorFlow有一個很好的方法來表示它們,關於這兩個引數可以自行Google

W = tf.Variable(tf.zeros([784,10])) #權重值
b = tf.Variable(tf.zeros([10]))   #偏置量
  • 我們賦予tf.Variable不同的初值來建立不同的Variable:在這裡,我們都用全為零的張量來初始化W和b。因為我們要學習W和b的值,它們的初值可以隨意設定。
    注意,W的維度是[784,10],因為我們想要用784維的圖片向量乘以它以得到一個10維的證據值向量,每一位對應不同數字類。b的形狀是[10],所以我們可以直接把它加到輸出上面。

B.實現模型

y = tf.nn.softmax(tf.matmul(x,W) + b)
  • 首先,我們用tf.matmul(​​X,W)表示x乘以W,對應之前等式裡面的,這裡x是一個2維張量擁有多個輸入。然後再加上b,把和輸入到tf.nn.softmax函式裡面。
  • softmax是一個迴歸模型,它用來描述其他各種數值計算,從機器學習模型對物理學模擬模擬模型,簡單的說就是建模,把輸入一個圖片資訊,輸出他的結果,不同的圖片資訊會有不同的結果,這些結果具有一定的規律性,根據這個規律性,我們就可以反推輸入的是什麼圖片。

C.訓練模型

為了訓練我們的模型,我們首先需要定義一個指標來評估這個模型是好的。但在機器學習,我們通常定義指標來表示一個模型是壞的,這個指標稱為成本(cost)或損失(loss),然後儘量最小化這個指標。但是,這兩種方式是相同的。這時就有一個非常漂亮的成本函式是“交叉熵”(cross-entropy)。交叉熵是用來衡量我們的預測用於描述真相的低效性,也就是他可以衡量我們的模型到底有多壞。

  • 為了計算交叉熵,我們首先需要新增一個新的佔位符用於輸入正確值:
y_ = tf.placeholder("float", [None,10])
  • 然後我們可以用以下方法來計算交叉熵:
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
  • 接著我們構建一個反向傳播自動修正引數的方法:
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
  • 這個函式的意思就是我們要求TensorFlow用梯度下降演算法(gradient descent algorithm)以0.01的學習速率最小化交叉熵。梯度下降演算法(gradient descent algorithm)是一個簡單的學習過程,TensorFlow只需將每個變數一點點地往使成本不斷降低的方向移動

  • 現在,我們已經設定好了我們的模型。在執行計算之前,我們需要新增一個操作來初始化我們建立的變數:

init = tf.initialize_all_variables()
  • 接著我們可以在一個Session裡面啟動我們的模型,並且初始化變數:
sess = tf.Session()
sess.run(init)
  • 然後開始訓練模型,這裡我們讓模型迴圈訓練1000次!
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

D.評估模型

那麼我們的模型效能如何呢?

首先讓我們找出那些預測正確的標籤。tf.argmax 是一個非常有用的函式,它能給出某個tensor物件在某一維上的其資料最大值所在的索引值。由於標籤向量是由0,1組成,因此最大值1所在的索引位置就是類別標籤,比如tf.argmax(y,1)返回的是模型對於任一輸入x預測到的標籤值,而 tf.argmax(y_,1) 代表正確的標籤,我們可以用 tf.equal 來檢測我們的預測是否真實標籤匹配(索引位置一樣表示匹配)。

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

這行程式碼會給我們一組布林值。為了確定正確預測項的比例,我們可以把布林值轉換成浮點數,然後取平均值。例如,[True, False, True, True] 會變成 [1,0,1,1] ,取平均值後得到 0.75.

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

最後,我們計算所學習到的模型在測試資料集上面的正確率。

print (sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
  • 這裡有個坑是極客學院沒有說到的,如果你的Python版本是Python2的話,直接複製極客網的程式碼不會有問題,但是你是Python3的話,它的print語法已經變了,變成print (),也就是需要把你要列印的東西放在括號裡面,不然會報錯!

E.執行結果

那我最終的執行結果是92.06%,比極客學院說的91%稍微好點。
執行結果

完整程式碼:

import tensorflow as tf
import sys
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

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

y_ = tf.placeholder("float", [None,10])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

for i in range(1000):
  if i % 20 == 0:
    sys.stdout.write('.')
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})


correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

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