安裝完Tensorflow之後,嘗試經典的MNIST手寫體識別的例子。該例子在安裝tensorflow之後自帶,可在如下目錄中找到(Anaconda_PATH代表安裝Anaconda的目錄位置)
Anaconda_PATH\envs\TensorFlow\Lib\site-packages\tensorflow\examples\tutorials\mnist
該目錄中包含三個例子mnist_softmax.py,fully_connected_feed.py,mnist_with_summaries.py。其他幾個文件是這幾個例子執行時需要引用的。先從最簡單的例子mnist_softmax.py來說明tensorflow的基本概念和原理。
mnist_softmax.py文件的內容如下:
# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""A very simple MNIST classifier.
See extensive documentation at
http://tensorflow.org/tutorials/mnist/beginners/index.md
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys
# Import data
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
FLAGS = None
def main(_):
mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
# Create the model
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.matmul(x, W) + b
# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, 10])
# The raw formulation of cross-entropy,
#
# tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)),
# reduction_indices=[1]))
#
# can be numerically unstable.
#
# So here we use tf.nn.softmax_cross_entropy_with_logits on the raw
# outputs of 'y', and then average across the batch.
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y, y_))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.InteractiveSession()
# Train
tf.global_variables_initializer().run()
for _ in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
y_: mnist.test.labels}))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--data_dir', type=str, default='/tmp/tensorflow/mnist/input_data',
help='Directory for storing input data')
FLAGS, unparsed = parser.parse_known_args()
tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
可在命令行執行如下命令直接運行它:
python mnist_softmax.py
但是很有可能運行報錯,因爲天朝的網絡很難下載數據集(反正我運行了好幾次都不行)。最可靠的方法是新建data目錄,下載下面四個文件(數據集)放到data中
http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
然後執行如下命令:
python mnist_softmax.py --data_dir data
可能的輸出如下:
恭喜,說明第一個例子運行成功了。
接下來解釋一下這個例子做了什麼事。
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
這兩句用於下載數據(很不幸一般很難下載下來),並將數據讀入內存。數據讀入內存後會分爲三部分,訓練集(mnist.train,包含55000個樣例),測試集(mnist.test,包含10000個樣例),校驗集(mnist.validation,包含5000個樣例)。每一個樣例可以看成一個”點“,每個點包含一張圖(手寫數字的照片,可記爲x)和一個標記(一個數字,表示這個手寫的數字是幾,可記爲y)。每張圖都是28x28=784像素大小的,如果把每個像素點記爲一個浮點數,則每個點包含784個x(因爲圖片是黑白的,所以用一個浮點數表示灰度即可)和一個0-9的整數y。
在此例中,採用了單層10個神經元的神經網絡,每個神經元對應0-9中的一個數,每個神經元最終的輸出相當於該圖片爲這個數字的概率。Tensorflow在python環境中獲取所有的神經網絡模型信息之後,利用底層的庫(通過NumPy庫進行轉換)來進行高效地計算(比如大量的矩陣乘法)。
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
這兩句中第一句引入了tensorflow庫,第二句則定義了輸入變量,因爲要在獲得整個網絡信息之後才進行計算,所以此處的網絡輸入是未知的,因此只是定義了一個佔位符變量,表示輸入量是2維浮點數,其中第一維可能是任意長度(第一維是None,代表任意長度),第二維長度爲784,代表一張圖上所有的像素點。
接下來兩句定義了變量,表示在計算中可以改變但一直存在的參數,並規定其初值均爲0。由於神經網絡計算就是要求出權重W和偏置b,因此這些變量可以取任意初始值。
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
本來至此應該定義模型如下,表示輸出y=f_softmax(W.x+b)
y = tf.nn.softmax(tf.matmul(x, W) + b)
但正如mnist_softmax.py原文中所解釋的,爲了後面定義訓練模型的規則,此處改爲了
y = tf.matmul(x, W) + b
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y, y_))
第1行僅定義了y=W.x+b,然後爲了定義該模型怎麼樣算好,或者說我們希望以什麼東西爲標準來進行優化,又定義了cross_entropy(交叉熵)的概念,該概念依賴於真實值y'和計算值y,滿足
cross_entropy = - sum_i y'_i log(y_i)
y' 代表每張圖所代表的真實值,比如 3 的話,就是(0,0,0,1,0,0,0,0,0,0)。交叉熵越大,意味着結果越差。因此第2行定義了y_佔位符來保存真正的輸出值,第3行給出了交叉熵的定義。
接下來利用反向傳播算法最小化cross_entropy,訓練模型
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
該語句表示利用梯度下降算法,以learning_rate=0.5的學習速率,最小化之前定義的cross_entropy。至此,整個神經網絡模型構建好,tensorflow可以進行計算,調整參數,給出最終結果了。注意tensorflow提供了很多優化算法,可參考如下鏈接
https://www.tensorflow.org/api_guides/python/train#optimizers
最後可以進行真正的計算了
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
for _ in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
前兩句創建了一個session進行計算,並對變量進行初始化;後面的循環進行真正的計算。在此處共循環1000次,每次從訓練集中隨機取100個點(每個點包含一張圖和一個標籤),然後用這些點替換之前的佔位符,然後執行train_step定義的計算。值得注意的是,原則上每次循環都應該用上訓練集中的所有點,但這樣計算過於耗時,因此這個例子中使用了訓練集的子集來進行計算,也能給出不錯的結果。
最後,對訓練的結果進行測試
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
y_: mnist.test.labels}))
tf.argmax函數給出張量沿某個方向的最大值所在的指標,因此tf.argmax(y,1)給出神經網絡模型所認爲的圖片對應的數字,而tf.argmax(y_,1)則給出該圖片真實對應的數字。correct_prediction表示神經網絡模型預言是否正確。第2行則將這些對錯序列轉化爲浮點數,比如[true, true, false, true,...]轉化爲[1,1,0,1,...],然後計算其平均值。最後一行將最終的正確率打印出來。如前面圖中的結果所示,正確率達到0.9196,約爲92%,還算不錯。
更詳細的說明可參考如下鏈接:
https://www.tensorflow.org/get_started/mnist/beginners