0. 寫在前面
參考書
《TensorFlow:實戰Google深度學習框架》(第2版)
工具
python3.5.1,pycharm
1. TensorBoard簡介
一個簡單的TensorFlow程序,在這個程序中完成了TensorBoard日志輸出的功能。
#!/usr/bin/env python # -*- coding: UTF-8 -*- # coding=utf-8 """ @author: Li Tian @contact: 694317828@qq.com @software: pycharm @file: tensorboard_test1.py @time: 2019/5/10 9:27 @desc: TensorBoard簡介。一個簡單的TensorFlow程序,在這個程序中完成了TensorBoard日志輸出的功能。 """ import tensorflow as tf # 定義一個簡單的計算圖,實現向量加法的操作。 input1 = tf.constant([1.0, 2.0, 3.0], name="input1") input2 = tf.Variable(tf.random_uniform([3], name="input2")) output = tf.add_n([input1, input2], name="add") # 生成一個寫日志的writer,並將當前的TensorFlow計算圖寫入日志。TensorFlow提供了 # 多種寫日志文件的API,在后面詳細介紹。 writer = tf.summary.FileWriter('./log/', tf.get_default_graph()) writer.close()
運行之后輸入:tensorboard --logdir=./log
查看TensorBoard。
然后在瀏覽器中輸入下面的網址。
2. TensorFlow計算圖可視化
2.1 命名空間與TensorBoard圖上節點
tf.variable_scope與tf.name_scope函數的區別
#!/usr/bin/env python # -*- coding: UTF-8 -*- # coding=utf-8 """ @author: Li Tian @contact: 694317828@qq.com @software: pycharm @file: tensorboard_test2.py @time: 2019/5/10 10:26 @desc: tf.variable_scope與tf.name_scope函數的區別 """ import tensorflow as tf with tf.variable_scope("foo"): # 在命名空間foo下獲取變量"bar",於是得到的變量名稱為“foo/bar”。 a = tf.get_variable("bar", [1]) # 輸出:foo/bar: 0 print(a.name) with tf.variable_scope("bar"): # 在命名空間bar下獲取變量“bar”,於是得到的變量名稱為“bar/bar”。此時變量 # “bar/bar”和變量“foo/bar”並不沖突,於是可以正常運行。 b = tf.get_variable("bar", [1]) # 輸出:bar/bar:0 with tf.name_scope("a"): # 使用tf.Variable函數生成變量會受到tf.name_scope影響,於是這個變量的名稱為“a/Variable”。 a = tf.Variable([1]) # 輸出:a/Variable:0 print(a.name) # tf.get_variable函數不受tf.name_scope函數的影響。 # 於是變量並不在a這個命名空間中。 a = tf.get_variable("b", [1]) # 輸出:b:0 print(a.name) with tf.name_scope("b"): # 因為tf.get_variable不受tf.name_scope影響,所以這里試圖獲取名稱為 # “a”的變量。然而這個變量已經被聲明了,於是這里會報重復聲明的錯誤 tf.get_variable("b", [1])
對不起,這一段代碼,我知道作者想要表達什么意思。。。但我實在是覺得不知所雲。
改進向量相加的樣例代碼
#!/usr/bin/env python # -*- coding: UTF-8 -*- # coding=utf-8 """ @author: Li Tian @contact: 694317828@qq.com @software: pycharm @file: tensorboard_test3.py @time: 2019/5/10 10:41 @desc: 改進向量相加的樣例代碼 """ import tensorflow as tf # 將輸入定義放入各自的命名空間中,從而使得TensorBoard可以根據命名空間來整理可視化效果圖上的節點。 with tf.name_scope("input1"): input1 = tf.constant([1.0, 2.0, 3.0], name="input1") 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", tf.get_default_graph()) writer.close()
得到改進后的圖:
\
展開input2節點的可視化效果圖:
可視化一個真實的神經網絡結構圖
我是真的佛了。。。這里原諒我真的又要噴。。。首先是用之前的mnist_inference文件就已經炸了,然后下面還有一句跟前面一樣的方式訓練神經網絡。。。我特么。。。。你你聽,這說的是人話嗎?我已經無力吐槽了。。。這本書用來作為我的TensorFlow啟蒙書,真的是后悔死了。。。
下面的代碼,依然是我自己憑借自己的理解,改后的,這本書是真的垃圾。
#!/usr/bin/env python # -*- coding: UTF-8 -*- # coding=utf-8 """ @author: Li Tian @contact: 694317828@qq.com @software: pycharm @file: tensorboard_test4.py @time: 2019/5/10 11:06 @desc: 可視化一個真實的神經網絡結構圖。 """ import tensorflow as tf import os from tensorflow.examples.tutorials.mnist import input_data # mnist_inference中定義的常量和前向傳播的函數不需要改變,因為前向傳播已經通過 # tf.variable_scope實現了計算節點按照網絡結構的划分。 import BookStudy.book2.mnist_inference as mnist_inference INPUT_NODE = 784 OUTPUT_NODE = 10 LAYER1_NODE = 500 # 配置神經網絡的參數。 BATCH_SIZE = 100 LEARNING_RATE_BASE = 0.8 LEARNING_RATE_DECAY = 0.99 REGULARAZTION_RATE = 0.0001 TRAINING_STEPS = 30000 MOVING_AVERAGE_DECAY = 0.99 # 模型保存的路徑和文件名。 MODEL_SAVE_PATH = './model/' MODEL_NAME = 'model.ckpt' 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(REGULARAZTION_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) variable_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, variable_averages_op]): train_op = tf.no_op(name='train') # 初始化Tensorflow持久化類。 saver = tf.train.Saver() with tf.Session() as sess: tf.global_variables_initializer().run() # 在訓練過程中不再測試模型在驗證數據上的表現,驗證和測試的過程將會有一個獨立的程序來完成。 for i in range(TRAINING_STEPS): xs, ys = mnist.train.next_batch(BATCH_SIZE) _, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys}