【TensorFlow篇】--Tensorflow框架實現SoftMax模型識別手寫數字集

LHBlog發表於2018-03-28

一、前述

本文講述用Tensorflow框架實現SoftMax模型識別手寫數字集,來實現多分類。

同時對模型的儲存和恢復做下示例。

二、具體原理

程式碼一:實現程式碼

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 檔名: 12_Softmax_regression.py

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf


# mn.SOURCE_URL = "http://yann.lecun.com/exdb/mnist/"
my_mnist = input_data.read_data_sets("MNIST_data_bak/", one_hot=True)#從本地路徑載入進來

# The MNIST data is split into three parts:
# 55,000 data points of training data (mnist.train)#訓練集圖片
# 10,000 points of test data (mnist.test), and#測試集圖片
# 5,000 points of validation data (mnist.validation).#驗證集圖片

# Each image is 28 pixels by 28 pixels

# 輸入的是一堆圖片,None表示不限輸入條數,784表示每張圖片都是一個784個畫素值的一維向量
# 所以輸入的矩陣是None乘以784二維矩陣
x = tf.placeholder(dtype=tf.float32, shape=(None, 784)) #x矩陣是m行*784列
# 初始化都是0,二維矩陣784乘以10個W值 #初始值最好不為0
W = tf.Variable(tf.zeros([784, 10]))#W矩陣是784行*10列
b = tf.Variable(tf.zeros([10]))#bias也必須有10個

y = tf.nn.softmax(tf.matmul(x, W) + b)# x*w 即為m行10列的矩陣就是y #預測值

# 訓練
# labels是每張圖片都對應一個one-hot的10個值的向量
y_ = tf.placeholder(dtype=tf.float32, shape=(None, 10))#真實值 m行10列
# 定義損失函式,交叉熵損失函式
# 對於多分類問題,通常使用交叉熵損失函式
# reduction_indices等價於axis,指明按照每行加,還是按照每列加
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)#將損失函式梯度下降 #0.5是學習率


# 初始化變數
sess = tf.InteractiveSession()#初始化Session
tf.global_variables_initializer().run()#初始化所有變數
for _ in range(1000):
    batch_xs, batch_ys = my_mnist.train.next_batch(100)#每次迭代取100行資料
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
#每次迭代內部就是求梯度,然後更新引數
# 評估

# tf.argmax()是一個從tensor中尋找最大值的序號 就是分類號,tf.argmax就是求各個預測的數字中概率最大的那一個
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))

# 用tf.cast將之前correct_prediction輸出的bool值轉換為float32,再求平均
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 測試
print(accuracy.eval({x: my_mnist.test.images, y_: my_mnist.test.labels}))

# 總結
# 1,定義演算法公式,也就是神經網路forward時的計算
# 2,定義loss,選定優化器,並指定優化器優化loss
# 3,迭代地對資料進行訓練
# 4,在測試集或驗證集上對準確率進行評測

程式碼二:儲存模型

# 有時候需要把模型保持起來,有時候需要做一些checkpoint在訓練中
# 以致於如果計算機當機,我們還可以從之前checkpoint的位置去繼續
# TensorFlow使得我們去儲存和載入模型非常方便,僅需要去建立Saver節點在構建階段最後
# 然後在計算階段去呼叫save()方法

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf


# mn.SOURCE_URL = "http://yann.lecun.com/exdb/mnist/"
my_mnist = input_data.read_data_sets("MNIST_data_bak/", one_hot=True)

# The MNIST data is split into three parts:
# 55,000 data points of training data (mnist.train)
# 10,000 points of test data (mnist.test), and
# 5,000 points of validation data (mnist.validation).

# Each image is 28 pixels by 28 pixels

# 輸入的是一堆圖片,None表示不限輸入條數,784表示每張圖片都是一個784個畫素值的一維向量
# 所以輸入的矩陣是None乘以784二維矩陣
x = tf.placeholder(dtype=tf.float32, shape=(None, 784))
# 初始化都是0,二維矩陣784乘以10個W值
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

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

# 訓練
# labels是每張圖片都對應一個one-hot的10個值的向量
y_ = tf.placeholder(dtype=tf.float32, shape=(None, 10))
# 定義損失函式,交叉熵損失函式
# 對於多分類問題,通常使用交叉熵損失函式
# reduction_indices等價於axis,指明按照每行加,還是按照每列加
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)

# 初始化變數
init = tf.global_variables_initializer()
# 建立Saver()節點
saver = tf.train.Saver()#在運算之前,初始化之後

n_epoch = 1000

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(n_epoch):
        if epoch % 100 == 0:
            save_path = saver.save(sess, "./my_model.ckpt")#每跑100次save一次模型,可以保證容錯性
            #直接儲存session即可。

        batch_xs, batch_ys = my_mnist.train.next_batch(100)#每一批次跑的資料 用m行資料/迭代次數來計算出來。
        sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

    best_theta = W.eval()
    save_path = saver.save(sess, "./my_model_final.ckpt")#儲存最後的模型,session實際上儲存的上面所有的資料

程式碼三:恢復模型

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf


# mn.SOURCE_URL = "http://yann.lecun.com/exdb/mnist/"
my_mnist = input_data.read_data_sets("MNIST_data_bak/", one_hot=True)

# The MNIST data is split into three parts:
# 55,000 data points of training data (mnist.train)
# 10,000 points of test data (mnist.test), and
# 5,000 points of validation data (mnist.validation).

# Each image is 28 pixels by 28 pixels

# 輸入的是一堆圖片,None表示不限輸入條數,784表示每張圖片都是一個784個畫素值的一維向量
# 所以輸入的矩陣是None乘以784二維矩陣
x = tf.placeholder(dtype=tf.float32, shape=(None, 784))
# 初始化都是0,二維矩陣784乘以10個W值
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)
# labels是每張圖片都對應一個one-hot的10個值的向量
y_ = tf.placeholder(dtype=tf.float32, shape=(None, 10))

saver = tf.train.Saver()

with tf.Session() as sess:
    saver.restore(sess, "./my_model_final.ckpt")#把路徑下面所有的session的資料載入進來 y y_head還有模型都儲存下來了。

    # 評估
    # tf.argmax()是一個從tensor中尋找最大值的序號,tf.argmax就是求各個預測的數字中概率最大的那一個
    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))

    # 用tf.cast將之前correct_prediction輸出的bool值轉換為float32,再求平均
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    # 測試
    print(accuracy.eval({x: my_mnist.test.images, y_: my_mnist.test.labels}))

相關文章