TensorFlow學習筆記(二)之視覺化(Tensorboard)
一、Tensorboard簡介
Tensorboard是TensorFlow自帶的一個強大的視覺化工具,也是一個web應用程式套件。通過將tensorflow程式輸出的日誌檔案的資訊視覺化使得tensorflow程式的理解、除錯和優化更加簡單高效。支援其七種視覺化:
- SCALARS:展示訓練過程中的準確率、損失值、權重/偏置的變化情況
- IMAGES:展示訓練過程中及記錄的影象
- AUDIO:展示訓練過程中記錄的音訊
- GRAPHS:展示模型的資料流圖,以及各個裝置上消耗的記憶體和時間
- DISTRIBUTIONS:展示訓練過程中記錄的資料的分佈圖
- HISTOGRAMS:展示訓練過程中記錄的資料的柱狀圖
- EMBEDDINGS:展示詞向量後的投影分佈
介面展示:
那如何啟動tensorboard呢?使用是手寫體識別的例子,原始碼如下:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
config = tf.ConfigProto(allow_soft_placement=True)
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.33 )
config.gpu_options.allow_growth = True
max_steps = 1000 # 最大迭代次數
learning_rate = 0.001 # 學習率
dropout = 0.9 # dropout時隨機保留神經元的比例
data_dir = './MNIST_DATA' # 樣本資料儲存的路徑
log_dir = './MNIST_LOG' # 輸出日誌儲存的路徑
# 獲取資料集,並採用採用one_hot熱編碼
mnist = input_data.read_data_sets(data_dir, one_hot=True)
sess = tf.InteractiveSession(config=config)
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')
# 儲存影象資訊
with tf.name_scope('input_reshape'):
image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
tf.summary.image('input', image_shaped_input, 10)
# 初始化權重引數
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
# 初始化偏執引數
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
# 繪製引數變化
def variable_summaries(var):
with tf.name_scope('summaries'):
# 計算引數的均值,並使用tf.summary.scaler記錄
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.scaler記錄記錄下標準差,最大值,最小值
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)
# 構建神經網路
def nn_layer(input_tensor, input_dim, output_dim, layer_name, act=tf.nn.relu):
# 設定名稱空間
with tf.name_scope(layer_name):
# 呼叫之前的方法初始化權重w,並且呼叫引數資訊的記錄方法,記錄w的資訊
with tf.name_scope('weights'):
weights = weight_variable([input_dim, output_dim])
variable_summaries(weights)
# 呼叫之前的方法初始化權重b,並且呼叫引數資訊的記錄方法,記錄b的資訊
with tf.name_scope('biases'):
biases = bias_variable([output_dim])
variable_summaries(biases)
# 執行wx+b的線性計算,並且用直方圖記錄下來
with tf.name_scope('linear_compute'):
preactivate = tf.matmul(input_tensor, weights) + biases
tf.summary.histogram('linear', preactivate)
# 將線性輸出經過激勵函式,並將輸出也用直方圖記錄下來
activations = act(preactivate, name='activation')
tf.summary.histogram('activations', activations)
# 返回激勵層的最終輸出
return activations
hidden1 = nn_layer(x, 784, 500, 'layer1')
# 建立dropout層
with tf.name_scope('dropout'):
keep_prob = tf.placeholder(tf.float32)
tf.summary.scalar('dropout_keep_probability', keep_prob)
dropped = tf.nn.dropout(hidden1, keep_prob)
y = nn_layer(dropped, 500, 10, 'layer2', act=tf.identity)
# 建立損失函式
with tf.name_scope('loss'):
# 計算交叉熵損失(每個樣本都會有一個損失)
diff = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)
with tf.name_scope('total'):
# 計算所有樣本交叉熵損失的均值
cross_entropy = tf.reduce_mean(diff)
tf.summary.scalar('loss', cross_entropy)
# 使用AdamOptimizer優化器訓練模型,最小化交叉熵損失
with tf.name_scope('train'):
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
# 計算準確率
with tf.name_scope('accuracy'):
with tf.name_scope('correct_prediction'):
# 分別將預測和真實的標籤中取出最大值的索引,弱相同則返回1(true),不同則返回0(false)
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
with tf.name_scope('accuracy'):
# 求均值即為準確率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.summary.scalar('accuracy', accuracy)
# summaries合併
merged = tf.summary.merge_all()
# 寫到指定的磁碟路徑中
train_writer = tf.summary.FileWriter(log_dir + '/train', sess.graph)
test_writer = tf.summary.FileWriter(log_dir + '/test')
# 執行初始化所有變數
tf.global_variables_initializer().run()
def feed_dict(train):
"""Make a TensorFlow feed_dict: maps data onto Tensor placeholders."""
if train:
xs, ys = mnist.train.next_batch(100)
k = dropout
else:
xs, ys = mnist.test.images, mnist.test.labels
k = 1.0
return {x: xs, y_: ys, keep_prob: k}
for i in range(max_steps):
if i % 10 == 0: # 記錄測試集的summary與accuracy
summary, acc = sess.run([merged, accuracy], feed_dict=feed_dict(False))
test_writer.add_summary(summary, i)
print('Accuracy at step %s: %s' % (i, acc))
else: # 記錄訓練集的summary
summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True))
train_writer.add_summary(summary, i)
train_writer.close()
test_writer.close()
在pycharm中執行這段程式碼,效果如下:
同時,在訓練的時候開啟命令列,輸入下面命令,啟動TesnorBoard:
tensorboard --logdir=./MNIST_LOG/
這裡生成一個連結地址,複製到遊覽器中檢視各個模組的內容。
總的來說步驟如下:
- 建立writer,寫日誌檔案:tf.summary.FileWriter(log_dir + ‘/train’, sess.graph)
- 儲存日誌檔案:writer.close()
- 執行視覺化命令,啟動服務:tensorboard –logdir /path/
二、SCALARS面板
SCALARS 面板,統計tensorflow中的標量(如:學習率、模型的總損失)隨著迭代輪數的變化情況。SCALARS 面板的左邊是一些選項,包括Split on undercores(用下劃線分開顯示)、Data downloadlinks(資料下載連結)、Smoothing(影象的曲線平滑程度)以及Horizontal Axis(水平軸)的表示,其中水平軸的表示分3 種(STEP 代表迭代次數,RELATIVE 代表按照訓練集和測試集的相對值,WALL 代表按照時間)。圖中右邊給出了準確率變化曲線。
如下圖二所示,SCALARS欄目顯示通過函式tf.summary.scalar()記錄的資料的變化趨勢。如下所示程式碼可新增到程式中,用於記錄學習率的變化情況。
tf.summary.scalar('accuracy', accuracy)
SCALARS 面板中還繪製了每一層的偏置(biases)和權重(weights)的變化曲線,包括每
次迭代中的最大值、最小值、平均值和標準差,如下圖,layer1層:
layer2層:
構建損失曲線:
tf.summary.scalar('loss', cross_entropy)
三、IMAGES面板
影象儀表盤,可以顯示通過tf.summary.image()函式來儲存的png圖片檔案。
1. # 指定圖片的資料來源為輸入資料x,展示的相對位置為[-1,28,28,1]
2. image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
3. # 將input名稱空間下的圖片放到summary中,一次展示10張
4. tf.summary.image('input', image_shaped_input , 10)
如上面程式碼,將輸入資料中的png圖片放到summary中,準備後面寫入日誌檔案。執行程式,生成日誌檔案,然後在tensorboard的IMAGES欄目下就會出現如下圖一所示的內容(實驗用的是mnist資料集)。儀表盤設定為每行對應不同的標籤,每列對應一個執行。影象儀表盤僅支援png圖片格式,可以使用它將自定義生成的視覺化影象(例如matplotlib散點圖)嵌入到tensorboard中。該儀表盤始終顯示每個標籤的最新影象。
IMAGES面板展示訓練過程中及記錄的影象,下圖展示了資料集合測試資料經過處理後圖片的樣子:
四、AUDIO
AUDIO 面板是展示訓練過程中處理的音訊資料。可嵌入音訊的小部件,用於播放通過tf.summary.audio()函式儲存的音訊。一個音訊summary要存成 的二維字元張量。其中,k為summary中記錄的音訊被剪輯的次數,每排張量是一對[encoded_audio, label],其中,encoded_audio 是在summary中指定其編碼的二進位制字串,label是一個描述音訊片段的UTF-8編碼的字串。
儀表盤設定為每行對應不同的標籤,每列對應一個執行。該儀表盤始終嵌入每個標籤的最新音訊。
五、GRAPHS
GRAPHS 面板是對理解神經網路結構最有幫助的一個面板,它直觀地展示了資料流圖。下圖所示介面中節點之間的連線即為資料流,連線越粗,說明在兩個節點之間流動的張量(tensor)越多。
在GRAPHS 面板的左側,可以選擇迭代步驟。可以用不同Color(顏色)來表示不同的Structure(整個資料流圖的結構),或者用不同Color 來表示不同Device(裝置)。例如,當使用多個GPU 時,各個節點分別使用的GPU 不同。當我們選擇特定的某次迭代時,可以顯示出各個節點的Compute time(計算時間)以及Memory(記憶體消耗)。
六、DISTRIBUTIONS
DISTRIBUTIONS 面板和接下來要講的HISTOGRAMS 面板類似,只不過是用平面來表示來自特定層的啟用前後、權重和偏置的分佈,它顯示了一些分發的高階統計資訊。
七、HISTOGRAMS
HISTOGRAMS面板,統計tensorflow中的張量隨著迭代輪數的變化情況。它用於展示通過tf.summary.histogram記錄的資料的變化趨勢。如下程式碼所示:
# 用直方圖記錄引數的分佈
tf.summary.histogram('histogram', var)
# 執行wx+b的線性計算,並且用直方圖記錄下來
tf.summary.histogram('linear', preactivate)
# 將線性輸出經過激勵函式,並將輸出也用直方圖記錄下來
tf.summary.histogram('activations', activations)
上述程式碼將神經網路中某一層的引數分佈、線性計算結果、經過激勵函式的計算結果資訊加入到日誌檔案中,執行程式生成日誌後,啟動tensorboard就可以在HISTOGRAMS欄目下看到對應的展開影象。
HISTOGRAMS 主要是立體地展現來自特定層的啟用前後、權重和偏置的分佈。
八、EMBEDDINGS
EMBEDDINGS 面板展示的是詞嵌入投影儀。(後續做詞嵌入的時候更新上…….)