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