Tensorboard教程:Tensorflow命名空間與計算圖可視化

Tensorflow命名空間與計算圖可視化

以爲有用的話,歡迎一塊兒討論相互學習~Follow Me

參考文獻 強烈推薦Tensorflow實戰Google深度學習框架 實驗平臺: Tensorflow1.4.0 python3.5.0node

  • Tensorflow可視化獲得的圖並不只是將Tensorflow計算圖中的節點和邊直接可視化,它會根據每一個Tensorflow計算節點的命名空間來整理可視化獲得效果圖,使得神經網絡的總體結構不會被過多的細節所淹沒。除了顯示Tensorflow計算圖的結構,Tensorflow還能夠展現Tensorflow計算節點上的信息進行描述統計,包括頻數統計和分佈統計。
  • 爲了更好的組織可視化效果圖中的計算節點,Tensorboard支持經過Tensorflow命名空間來整理可視化效果圖上的節點。在Tensorboard的默認視圖中,Tensorflow計算圖中同一個命名空間下的全部節點會被縮略爲一個節點,而頂層命名空間的節點纔會被顯示在Tensorboard可視化效果圖中。

<font color=Purple>tf.variable_scope和tf.name_scope函數區別</font>

  • tf.variable_scope和tf.name_scope函數都提供了命名變量管理的功能,這兩個函數在大部分狀況下是等價的,惟一的區別在於使用tf.get_variable函數時:
import tensorflow as tf
# 不一樣的命名空間
with tf.variable_scope("foo"):
    # 在命名空間foo下獲取變量"bar",因而獲得的變量名稱爲"foo/bar"
    a = tf.get_variable("bar", [1])
    print(a.name)
    # foo/bar:0
with tf.variable_scope("bar"):
    # 在命名空間bar下獲取變量"bar",因而獲得的變量名稱爲"bar/bar".此時變量在"bar/bar"和變量"foo/bar"並不衝突,因而能夠正常運行
    b = tf.get_variable("bar", [1])
    print(b.name)
    # bar/bar:0
#  tf.Variable和tf.get_variable的區別。

with tf.name_scope("a"):
    # 使用tf.Variable函數生成變量時會受到tf.name_scope影響,因而這個變量的名稱爲"a/Variable"
    a = tf.Variable([1])
    print(a.name)
    # a/Variable: 0

    # tf.get_variable函數不受頭tf.name_scope函數的影響,因而變量並不在a這個命名空間中
    a = tf.get_variable("b", [1])
    print(a.name)
    # b:0

# with tf.name_scope("b"):
    # 由於tf.get_variable不受tf.name_scope影響,因此這裏將試圖獲取名稱爲"a"的變量。然而這個變量已經被聲明瞭,因而這裏會報重複聲明的錯誤。
    # tf.get_variable("b",[1])
  • 經過對變量命名空間進行管理,使用Tensorboard查看模型的結構時更加清晰
import tensorflow as tf
with tf.name_scope("input1"):
    input1 = tf.constant([1.0, 2.0, 3.0], name="input2")
with tf.name_scope("input2"):
    input2 = tf.Variable(tf.random_uniform([3]), name="input2")
output = tf.add_n([input1, input2], name="add")

writer = tf.summary.FileWriter("log/simple_example.log", tf.get_default_graph())
writer.close()
  • 這樣程序中定義的加法運算都被清晰的展現出來,而且變量初始化等基本操做都被摺疊起來。

Tensorboard展現圖片

  • 點擊input2上的加號按鈕,可以看到關於input2變量初始化的全過程。

input2節點操做

<font color=Purple>可視化MNIST程序</font>

MNIST基本程序python

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# mnist_inference中定義的常量和前向傳播的函數不須要改變,由於前向傳播已經經過
# tf.variable_scope實現了計算節點按照網絡結構的劃分
import mnist_inference

# #### 1. 定義神經網絡的參數。
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99
REGULARIZATION_RATE = 0.0001
TRAINING_STEPS = 3000
MOVING_AVERAGE_DECAY = 0.99


# #### 2. 定義訓練的過程並保存TensorBoard的log文件。
def train(mnist):
    #  將處理輸入數據的計算都放在名字爲"input"的命名空間中
    with tf.name_scope('input'):
        x = tf.placeholder(tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input')
        y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input')
    regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
    y = mnist_inference.inference(x, regularizer)
    global_step = tf.Variable(0, trainable=False)

    # 將處理滑動平均相關的計算都放在名爲moving average 的命名空間下。
    with tf.name_scope("moving_average"):
        variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
        variables_averages_op = variable_averages.apply(tf.trainable_variables())  # 對可訓練變量集合使用滑動平均

    # 將計算損失函數相關的計算都放在名爲loss function 的命名空間下。
    with tf.name_scope("loss_function"):
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
        cross_entropy_mean = tf.reduce_mean(cross_entropy)
        # 將交叉熵加上權值的正則化
        loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))

    # 將定義學習率、優化方法以及每一輪訓練須要執行的操做都放在名字爲"train_step"的命名空間下。
    with tf.name_scope("train_step"):
        learning_rate = tf.train.exponential_decay(
            LEARNING_RATE_BASE,
            global_step,
            mnist.train.num_examples/BATCH_SIZE, LEARNING_RATE_DECAY,
            staircase=True)

        train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
        # 在反向傳播的過程當中更新變量的滑動平均值
        with tf.control_dependencies([train_step, variables_averages_op]):
            train_op = tf.no_op(name='train')
    # 將結果記錄進log文件夾中
    writer = tf.summary.FileWriter("log", tf.get_default_graph())

    # 訓練模型。
    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        for i in range(TRAINING_STEPS):
            xs, ys = mnist.train.next_batch(BATCH_SIZE)

            if i%1000 == 0:
                # 配置運行時須要記錄的信息。
                run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
                # 運行時記錄運行信息的proto。
                run_metadata = tf.RunMetadata()
                # 將配置信息和記錄運行信息的proto傳入運行的過程,從而記錄運行時每個節點的時間空間開銷信息
                _, loss_value, step = sess.run(
                    [train_op, loss, global_step], feed_dict={x: xs, y_: ys},
                    options=run_options, run_metadata=run_metadata)
                writer.add_run_metadata(run_metadata=run_metadata, tag=("tag%d"%i), global_step=i)
                print("After %d training step(s), loss on training batch is %g."%(step, loss_value))
            else:
                _, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})

    writer.close()


# #### 3. 主函數。
def main(argv=None):
    mnist = input_data.read_data_sets("../../datasets/MNIST_data", one_hot=True)
    train(mnist)


if __name__ == '__main__':
    main()

<font color=DeepPink>可視化效果圖</font>

  • input節點表明了訓練神經網絡須要的輸入數據,這些輸入數據會提供給神經網絡的第一層layer1.而後神經網絡第一層layerl的結果會被傳到第二層layer2,通過layer2的計算獲得前向傳播的結果.loss function節點表示計算損失函數的過程,這個過程既依賴於前向傳播的結果來計算交叉熵(layer2到loss_function的邊,又依賴於每一層中所定義的變量來計算L2 正則化損失(layer1和layer2到loss_function的邊).loss_function 的計算結果會提供給神經網絡的優化過程,也就是圖中位train_step 所表明的節點。

  • 發現節點之間有兩種不一樣的邊。一種邊是經過實線表示的,這種邊刻畫了數據傳輸,邊上箭頭方向表達了數據傳輸的方向。好比layerl和layer2之間的邊表示了layer1的輸出將會做爲layer2的輸入。TensorBoard 可視化效果圖的邊上還標註了張量的維度信息。

  • 從圖中能夠看出,節點input和layer1之間傳輸的張量的維度爲*784。這說明了訓練時提供的batch大小不是固定的(也就是定義的時候是None),輸入層節點的個數爲784。當兩個節點之間傳輸的張量多於1時,可視化效果圖上將只顯示張量的個數。效果圖上邊的粗細表示的是兩個節點之間傳輸的標量維度的總大小,而不是傳輸的標量個數。好比layer2和train_step之間雖然傳輸了6個張量,但其維度都比較小,因此這條邊比layerl和moving_average之間的邊(只傳輸了4個張量〉還要細。當張量的維度沒法肯定時,TensorBoard會使用最細的邊來表示。好比layer1與layer2之間的邊。

  • Tensor Board可視化效果圖上另一種邊是經過虛線表示的,好比圖中所示的moving_ average 和train_step 之間的邊.虛邊表達了計算之間的依賴關係,好比在程序中,經過tf.control_dependencies函數指定了更新參數滑動平均值的操做和經過反向傳播更新變量的操做須要同時進行,因而moving_average 與train_step 之間存在一條虛邊.

  • 除了手動的經過TensorFlow中的命名空間來調整TensorBoard的可視化效果圖,TensorBoard也會智能地調整可視化效果圖上的節點.TensorFlow中部分計算節點會有比較多的依賴關係,若是所有畫在一張圖上會即可視化獲得的效果圖很是擁擠.因而TensorBoard將TensorFlow計算圖分紅了主圖(Main Graph)和輔助圖(Auxiliary nodes)兩個部分來呈現。TensorBoard 會自動將鏈接比較多的節點放在輔助圖中,使得主圖的結構更加清晰。

  • 除了自動的方式,TensorBoard也支持手工的方式來調整可視化結果。右鍵單擊可視化效果圖上的節點會彈出一個選項,這個選項能夠將節點加入主圖或者從主圖中刪除。左鍵選擇一個節點並點擊信息框下部的選項也能夠完成相似的功能。注意TensorBoard 不會保存用戶對計算圖可視化結果的手工修改,頁面刷新以後計算圖可視化結果又會回到最初的樣子。

相關文章
相關標籤/搜索