Tensorflow學習筆記:基礎篇(9)——Mnist手寫集完結版(Embedding Visualization)

Tensorflow學習筆記:基礎篇(9)——Mnist手寫集完結版(Embedding Visualization)


前序

— 前文中,我們說了過擬合現象,通過Dropout的方法進行緩解。
— 今天是我們三層全連接神經網絡的最後一篇博文,我們先來回憶一下這一系列我們做了些什麼:
單層神經網絡 —> 三層神經網絡 —> 交叉熵函數 —> Optimizer —> Dropout —> Tensorboard
— 我們針對這個神經網絡進行反覆修改與優化,將準確率從0.91一步步提升至0.98,大家有沒有發現,我們到目前爲止得到的結果一直是一個準確率這個數字,有人似乎會好奇這些圖片真的能分類的這麼準嗎,我們能夠在Tensorboard可視化界面中看到分類完成後效果嗎,答案是可以的。
— 這也引出了我們今天要做的事情:Embedding Visualization。有人會問,這是個什麼玩意呢?
— 這個是Tensorflow針對moist手寫數據集做的一個可視化項目,這個在Tensorflow沒更新前,官網上是有的,現在出來1.4版本後,被刪減掉了,我幫大家把這個網址重新找出來,供大家進行參考學習。
Reference:TensorBoard: Embedding Visualization
這裏寫圖片描述
這幅動圖就是我從Tensorflow官網上抓取下來的,大家可以看到一個個數字圖片通過模型訓練後,能夠進行扎堆歸類,一個數字的聚集在一塊區域,用一個顏色顯示,大家是不是覺得很贊呢,那麼這效果究竟是怎麼實現的呢~~


Setup

這裏寫圖片描述

Mnist手寫數據集的1w個測試集圖片,被隨機順序存放在sprite image中,排列順序爲100x100,這裏我給出了下載鏈接:sprite image
這裏寫圖片描述

這裏寫圖片描述

接下來,我們只需要按照官方文檔,在之前的神經網絡中修改即可。


準備工作

在程序的根目錄中新建一個projector文件夾,就像這樣:
這裏寫圖片描述
在projector文件夾中再新建一個projector同名文件夾和一個data文件夾:
這裏寫圖片描述
將剛纔的mnist_10k_sprite.png的數據集圖片放在data文件夾中:
這裏寫圖片描述
並且保證projector的同名文件夾中清空(第一次創建不存在此問題,如第二次運行程序,請先清空,否則程序會報錯)
這裏寫圖片描述


代碼示例

1、數據準備

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.contrib.tensorboard.plugins import projector

# 載入數據集
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
#圖片數量
image_num = 10000
#文件路徑
DIR = "F://untitled/"#設置文件路徑(這是我的程序文件位置,大家自行做修改),之後生成metadata文件時會用到
#載入圖片
embedding = tf.Variable(tf.stack(mnist.test.images[:image_num]), trainable=False, name='embedding')
#tf.stack(mnist.test.images[:image_num])中的image_num可以控制測試圖片個數,最大爲10000,我這裏取值爲10000
# 批次
n_batch = 100

sess = tf.Session()
#這裏我們今天直接開啓session,替換之前在後面用的with tf.Session() as sess

def variable_summaries(var):
    with tf.name_scope('summaries'):
        mean = tf.reduce_mean(var)
        tf.summary.scalar('mean', mean)
        with tf.name_scope('stddev'):
            stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
        tf.summary.scalar('stddev', stddev)
        tf.summary.scalar('max', tf.reduce_max(var))
        tf.summary.scalar('min', tf.reduce_min(var))
        tf.summary.histogram('histogram', var)  ##直方圖

2、準備好placeholder

with tf.name_scope('input'):
    x = tf.placeholder(tf.float32, [None, 784], name='x_input')
    y = tf.placeholder(tf.float32, [None, 10], name='y_input')
    keep_prob = tf.placeholder(tf.float32, name='keep_prob')
    lr = tf.Variable(0.001, dtype=tf.float32, name='learning_rate')

3、初始化參數/權重

with tf.name_scope('layer'):
    with tf.name_scope('Input_layer'):
        with tf.name_scope('W1'):
            W1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1), name='W1')
            variable_summaries(W1)
        with tf.name_scope('b1'):
            b1 = tf.Variable(tf.zeros([500]) + 0.1, name='b1')
            variable_summaries(b1)
        with tf.name_scope('L1'):
            L1 = tf.nn.relu(tf.matmul(x, W1) + b1, name='L1')
        L1_drop = tf.nn.dropout(L1, keep_prob)
    with tf.name_scope('Hidden_layer'):
        with tf.name_scope('W2'):
            W2 = tf.Variable(tf.truncated_normal([500, 300], stddev=0.1), name='W2')
            variable_summaries(W2)
        with tf.name_scope('b2'):
            b2 = tf.Variable(tf.zeros([300]) + 0.1, name='b2')
            variable_summaries(b2)
        with tf.name_scope('L2'):
            L2 = tf.nn.relu(tf.matmul(L1_drop, W2) + b2, name='L2')
        L2_drop = tf.nn.dropout(L2, keep_prob)
    with tf.name_scope('Output_layer'):
        with tf.name_scope('W3'):
            W3 = tf.Variable(tf.truncated_normal([300, 10], stddev=0.1), name='W3')
            variable_summaries(W3)
        with tf.name_scope('b3'):
            b3 = tf.Variable(tf.zeros([10]) + 0.1, name='b3')
            variable_summaries(b3)

4、計算預測結果

prediction = tf.nn.softmax(tf.matmul(L2, W3) + b3)

5、計算損失值

with tf.name_scope('loss'):
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))
    tf.summary.scalar('loss', loss)

6、初始化optimizer

with tf.name_scope('optimizer'):
    optimizer = tf.train.AdamOptimizer(lr).minimize(loss)

with tf.name_scope('train'):
    with tf.name_scope('correct_prediction'):
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))

    with tf.name_scope('accuracy'):
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        tf.summary.scalar('accuracy', accuracy)

init = tf.global_variables_initializer()
sess.run(init)
merged = tf.summary.merge_all()

7、生成metadata文件

程序會在新建的projector的文件夾中的projector子文件夾中會生成一個metadata.tsv文件

# 生成metadata文件
with open(DIR + 'projector/projector/metadata.tsv', 'w') as f:
    labels = sess.run(tf.argmax(mnist.test.labels[:], 1))
    for i in range(image_num):
        f.write(str(labels[i]) + '\n')

#下段代碼,按照Tensorflow文檔進行操作
projector_writer = tf.summary.FileWriter(DIR + 'projector/projector', sess.graph)
saver = tf.train.Saver()
config = projector.ProjectorConfig()
embed = config.embeddings.add()
embed.tensor_name = embedding.name
embed.metadata_path = DIR + 'projector/projector/metadata.tsv'
embed.sprite.image_path = DIR + 'projector/data/mnist_10k_sprite.png'
embed.sprite.single_image_dim.extend([28, 28])
#將下載下來的數據集圖片以28x28的像素進行分隔,分隔成一個個數字圖片
projector.visualize_embeddings(projector_writer, config)

7、指定迭代次數,並在session執行graph

for epoch in range(2001):
    sess.run(tf.assign(lr, 0.001 * (0.95 ** (epoch / 50))))
    batch_xs, batch_ys = mnist.train.next_batch(n_batch)
    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
    run_metadata = tf.RunMetadata()
    summary, _ = sess.run([merged, optimizer], feed_dict={x: batch_xs, y: batch_ys, keep_prob: 1.0}, options=run_options, run_metadata=run_metadata)
    projector_writer.add_run_metadata(run_metadata, 'step%03d' % epoch)
    projector_writer.add_summary(summary, epoch)

    if epoch % 100 == 0:
        test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})
        learning_rate = sess.run(lr)
        print("Iter" + str(epoch) + ", Testing accuracy:" + str(test_acc) + ", Learning rate:" + str(learning_rate))

saver.save(sess, DIR + 'projector/projector/a_model.ckpt', global_step=1001)
projector_writer.close()
sess.close()#因爲這次沒有用with tf.Session() as less,需要在最後加上本條語句

運行結果

迭代2000次,最終準確率爲0.9721
這裏寫圖片描述
我們可以看到,在剛開始保持爲空的文件夾中,生成了些數據文件:
這裏寫圖片描述
其中以P-V-10的文件類型爲Tensorboard數據文件,在Tensorboard打開,與之前不同的是,標籤中多了一項Projector,裏面就是我們的1w張測試集圖片,每張圖片包含一個手寫數字,密密麻麻堆疊在一起:
這裏寫圖片描述
接下來,我們要做的就是進行分類識別,在這之前,我們選取左邊欄中的Color,選取label 10 colors:
這裏寫圖片描述
隨後,我們點擊左邊欄下方的T-SNE,程序就會自動運行,界面中會產生動畫效果,開始分類,左下角的Iteration爲迭代次數,這是Iteration = 307時的分類效果:
這裏寫圖片描述
當Iteration = 709時,分類已經基本成型,由於我們模型的準確率爲0.97,因此可以看到個別的數字出現分類錯誤的情況。
這裏寫圖片描述

好啦,到此爲止,這一系列我們用三層全連接網絡實現對MNIST手寫數據集的分類就告一段落了。下一個系列,將是Tensorflow對CNN卷積神經網絡的介紹。


完整代碼

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.contrib.tensorboard.plugins import projector

mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

#圖片數量
image_num = 10000
#文件路徑
DIR = "F://untitled/"
#載入圖片
embedding = tf.Variable(tf.stack(mnist.test.images[:image_num]), trainable=False, name='embedding')
# 批次
n_batch = 100

sess = tf.Session()

def variable_summaries(var):
    with tf.name_scope('summaries'):
        mean = tf.reduce_mean(var)
        tf.summary.scalar('mean', mean)
        with tf.name_scope('stddev'):
            stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
        tf.summary.scalar('stddev', stddev)
        tf.summary.scalar('max', tf.reduce_max(var))
        tf.summary.scalar('min', tf.reduce_min(var))
        tf.summary.histogram('histogram', var)  ##直方圖

with tf.name_scope('input'):
    x = tf.placeholder(tf.float32, [None, 784], name='x_input')
    y = tf.placeholder(tf.float32, [None, 10], name='y_input')
    keep_prob = tf.placeholder(tf.float32, name='keep_prob')
    lr = tf.Variable(0.001, dtype=tf.float32, name='learning_rate')

#顯示圖片
with tf.name_scope('input_reshape'):
    image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
    tf.summary.image('input', image_shaped_input, 10)

with tf.name_scope('layer'):
    with tf.name_scope('Input_layer'):
        with tf.name_scope('W1'):
            W1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1), name='W1')
            variable_summaries(W1)
        with tf.name_scope('b1'):
            b1 = tf.Variable(tf.zeros([500]) + 0.1, name='b1')
            variable_summaries(b1)
        with tf.name_scope('L1'):
            L1 = tf.nn.relu(tf.matmul(x, W1) + b1, name='L1')
        L1_drop = tf.nn.dropout(L1, keep_prob)
    with tf.name_scope('Hidden_layer'):
        with tf.name_scope('W2'):
            W2 = tf.Variable(tf.truncated_normal([500, 300], stddev=0.1), name='W2')
            variable_summaries(W2)
        with tf.name_scope('b2'):
            b2 = tf.Variable(tf.zeros([300]) + 0.1, name='b2')
            variable_summaries(b2)
        with tf.name_scope('L2'):
            L2 = tf.nn.relu(tf.matmul(L1_drop, W2) + b2, name='L2')
        L2_drop = tf.nn.dropout(L2, keep_prob)
    with tf.name_scope('Output_layer'):
        with tf.name_scope('W3'):
            W3 = tf.Variable(tf.truncated_normal([300, 10], stddev=0.1), name='W3')
            variable_summaries(W3)
        with tf.name_scope('b3'):
            b3 = tf.Variable(tf.zeros([10]) + 0.1, name='b3')
            variable_summaries(b3)
        prediction = tf.nn.softmax(tf.matmul(L2_drop, W3) + b3)

# 二次代價函數
# loss = tf.reduce_mean(tf.square(y - prediction))

# 交叉熵代價函數
with tf.name_scope('loss'):
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))
    tf.summary.scalar('loss', loss)

# 梯度下降
# optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
with tf.name_scope('optimizer'):
    optimizer = tf.train.AdamOptimizer(lr).minimize(loss)

init = tf.global_variables_initializer()
sess.run(init)

with tf.name_scope('train'):
    with tf.name_scope('correct_prediction'):
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))

    with tf.name_scope('accuracy'):
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        tf.summary.scalar('accuracy', accuracy)

# 生成metadata文件
if tf.gfile.Exists(DIR + 'projector/projector/metadata.tsv'):
    tf.gfile.DeleteRecursively(DIR + 'projector/projector/metadata.tsv')
with open(DIR + 'projector/projector/metadata.tsv', 'w') as f:
    labels = sess.run(tf.argmax(mnist.test.labels[:], 1))
    for i in range(image_num):
        f.write(str(labels[i]) + '\n')

merged = tf.summary.merge_all()

projector_writer = tf.summary.FileWriter(DIR + 'projector/projector', sess.graph)
saver = tf.train.Saver()
config = projector.ProjectorConfig()
embed = config.embeddings.add()
embed.tensor_name = embedding.name
embed.metadata_path = DIR + 'projector/projector/metadata.tsv'
embed.sprite.image_path = DIR + 'projector/data/mnist_10k_sprite.png'
embed.sprite.single_image_dim.extend([28, 28])
projector.visualize_embeddings(projector_writer, config)


for epoch in range(2001):
    sess.run(tf.assign(lr, 0.001 * (0.95 ** (epoch / 50))))
    batch_xs, batch_ys = mnist.train.next_batch(n_batch)
    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
    run_metadata = tf.RunMetadata()
    summary, _ = sess.run([merged, optimizer], feed_dict={x: batch_xs, y: batch_ys, keep_prob: 1.0},
                          options=run_options, run_metadata=run_metadata)
    projector_writer.add_run_metadata(run_metadata, 'step%03d' % epoch)
    projector_writer.add_summary(summary, epoch)

    if epoch % 100 == 0:
        test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})
        learning_rate = sess.run(lr)
        print("Iter" + str(epoch) + ", Testing accuracy:" + str(test_acc) + ", Learning rate:" + str(learning_rate))

saver.save(sess, DIR + 'projector/projector/a_model.ckpt', global_step=1001)
projector_writer.close()
sess.close()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章