参考资料:
TensorFlow 采用数据流图进行数值计算。节点代表计算图中的数学操作,计算图的边表示多维数组,即张量。
在 TensorFlow 官网上将其定义为基于数据流图的数值计算库,TensorFlow 还提供了一个可使得用户用数学方法从零开始定义模型的函数和类的广泛套件。这使得具有一定技术背景的用户可迅速而直观地创建自定义、具有较高灵活性的模型。
TensorFlow 的计算模型是有向图,其中的每个节点(通常以圆圈或方框表示)代表了一些函数或计算,而边(通常以箭头或线段表示)代表了数值、矩阵、张量。TensorFlow 能够自动计算任意节点关于其他对第一个节点的输出产生影响的任意节点的导数(即 Operation),还可以通过计算的分解,将计算分布在多个 CPU、GPU 以及其他计算设备上(只需要将完整的、较大的数据流图分解为一些较小的计算图,并借由一定的逻辑对不同设备间的共享信息进行调度来让每台计算设备负责一个独立的计算子图)。
定义数据流图
TensorFlow的核心工作模式:
1. 定义数据流图
2. 运行数据流图(在数据上)
import tensorflow as tf
# 在“input”节点上输入数据
a = tf.constant(5, name= 'input_a')
b = tf.constant(3, name= 'input_b')
# 定义运算节点“Operation”(简称:Op)
c = tf.multiply(a, b, name= 'mul_c')
d = tf.add(a, b, name= 'add_d')
e = tf.add(c, d, name= 'add_e')
# 运行数据流图
with tf.Session() as sess:
s = sess.run(e)
print(s)
23
创建summary.FileWriter
对象,并赋值给writer
writer = tf.summary.FileWriter('./my_graph', sess.graph)
writer.close()
sess.close()
a = tf.constant([5, 3], name= 'input_a')
b = tf.reduce_prod(a, name= 'prod_b') # 所有元素的乘积
c = tf.reduce_sum(a, name= 'sum_c') # 所有元素的和
d = tf.add(c, d, name= 'add_d')
with tf.Session() as sess:
print(sess.run([a, b, c, d]))
[array([5, 3]), 15, 8, 16]
1 张量
1.1 Python原生类型
TensorFlow可接收Python数值、布尔值、字符串或由它们构成的列表。
单个数值将会被转化为0阶张量(或标量),数值列表将被转化为2阶张量(矩阵),以此类推。
t0 = 50 # 标量
t1 = [b'apple', b'peach', b'grape'] # 向量
t2 = [[1, 3], [3, 5]] # 矩阵
可将张量视为一种以结构化格式保存任意数据的方式。
TensorFlow数据类型
数据类型(dtype) | 描述 |
---|---|
tf.float32 |
32位浮点型 |
tf.float64 |
64位浮点型 |
tf.int8 |
8位由符号整数 |
tf.int16 |
16位由符号整数 |
tf.int32 |
32位由符号整数 |
tf.int64 |
64位由符号整数 |
tf.uint8 |
8位由无符号整数 |
tf.string |
字符串(作为非Unicode编码的字节数组) |
tf.bool |
布尔型 |
tf.complex64 |
复数,实部和 虚部分别为32位浮点型 |
tf.qint8 |
8位有符号整数(用于量化) |
tf.qint328 |
32位有符号整数(用于量化) |
tf.quint8 |
8位有无符号整数(用于量化) |
tf.quint32 |
32位无符号整数(用于量化) |
1.2 Numpy
TensorFlow的数据类型是基于NumPy的数据类型:
import numpy as np
np.int64 == tf.int64
True
任何一个NumPy数组均可传递给TensorFlow Op:
字符串数据类型
对于数值类型和布尔类型TensorFlow和NumPy dtype属性是完全一致的。然而,在NumPy中并无与tf.string精确对应的类型。即TensorFlow可以从NumPy中完美地导入字符串数组,只是不要在NumPy中显式指定dtype。
在运行数据流图之前之后,都可以利用NumPy库的功能,因为从Session.run方法返回的张量均为NumPy数组。
t1 = np.array(50, dtype= np.int64)
# 在NumPy中使用字符串时,不要显式指定dtype属性
t2 = np.array([b'apple', b'peach', b'grape'])
t3 = np.array([[True, False, False],[False, False, True], [False, True, True]], dtype = np.bool)
t4 = np.array([[[1]]], dtype= np.float32)
虽然TensorFlow是为理解NumPy原生数据类型而设计的,但反之不然。请不要尝试用tf.int32去初始化一个NumPy数组。
a = np.array(3, np.int) # 不是np.int32
a.dtype
dtype('int32')
a = np.array(3, np.float)
a.dtype
dtype('float64')
a = np.array(3, np.float64)
a.dtype
dtype('float64')
a = np.array(3, np.float32)
a.dtype
dtype('float32')
手工指定Tensor对象时,使用NumPy是推荐的方式。
1.3 张量的形状
“形状”是TensorFlow的专有术语,它同时刻画了张量的维(阶)数以及每一维的长度。形式可以是列表或元组。
t1.shape # 标量
()
t2.shape # 向量
(3,)
t3.shape # 矩阵
(3, 3)
t4.shape # 3维数组(张量)
(1, 1, 1)
也可以将None作为某一维的长度,使得该张量具有可变长度。
此外,将形状指定为None,将通知TensorFlow允许一个张量为任意形状。
如果需要在数据流图的中间获取某个张量的形状,可使用tf.shape Op。它的输入为希望获取形状的Tensor对象,输出为一个int32类型的向量。
shape = tf.shape(t3, name= 't3_shape')
shape
<tf.Tensor 't3_shape:0' shape=(2,) dtype=int32>
with tf.Session() as sess:
print(sess.run(shape))
[3 3]
2 TensorFlow的Operation
在TensorFlow中,数据流图本质上是一组链接在一起的函数,每个函数都会将其输出传递给0个、1个或多个位于这个级联链上的其他函数。按照这种方式,用户可利用一些很小的、为人们所充分理解的数学函数构造数据的复杂变换。
数据流图的两个基本构件:节点和边。
2.1 节点(node)
节点通常以圆圈、椭圆和方框表示,代表了对数据所做的运算和某种操作。
“input”节点的作用仅仅是传递Tensor的输入值。
sess = tf.InteractiveSession()
# 初始化一些计算需要的张量
a = np.array([2, 3], dtype= np.int) # input_Op(节点)
a.dtype
dtype('int32')
b = np.array([4, 5], dtype= np.int) # input_Op
# 利用tf.add() 初始化一个"add" Op
# 变量c为指向该Op的Tensor对象的句柄
c = tf.add(a, b) # add Op
s = c.eval()
s
array([6, 8])
type(c) # c是Tensor对象
tensorflow.python.framework.ops.Tensor
type(s) # s是数组,即张量的输出值
numpy.ndarray
TensorFlow中,数据流图中的每个节点都被称为一个“Operation”(简记:Op)。各Op可接收0个或多个Tensor对象作为输入,并输出0个或多个Tensor对象。要创建一个Op,可调用与其关联的Python构造方法。比如:
# `tf.constant`创建了一个常量Op,可接收单个张量值,然后将同样的值输出给其直接连接的节点。
## 自动将标量值转化为了Tensor对象。
r = tf.constant(5, name= 'input_a')
r
<tf.Tensor 'input_a_4:0' shape=() dtype=int32>
type(r.eval())
numpy.int32
type(r)
tensorflow.python.framework.ops.Tensor
2.2 边(edge)
edge
对应于向Operation传入和从Operation传出的实际数值(可以视为Tensor),通常以箭头表示。
可从概念上将边视为不同的Operation之间的连接,因为它们将信息从一个节点传输到另一个节点。
运算符重载
运算符 | 相关TensorFlow运算 | |
---|---|---|
-x |
tf.negative() |
返回x中的每个元素的相反数 |
~x |
tf.logical_not |
返回x中的每个元素的逻辑非。只适用于dtype为tf.bool的Tensor对象 |
abs(x) |
tf.abs(x) |
返回x中的每个元素的绝对值 |
x + y |
tf.add() |
将下x, y逐元素相加 |
x - y |
tf.subtract |
将下x, y逐元素相减 |
x * y |
tf.multiply |
将下x, y逐元素相乘 |
x / y (Python 2.x) |
tf.div |
给定整数张量时,执行逐元素的整数除法;给定浮点数型张量,将执行逐元素的浮点数除法 |
x / y (Python 3.x) |
tf.truediv |
逐元素的浮点数除法(包括分子、分母为整数的情形) |
x // y (Python 3.x) |
tf.floordiv |
逐元素的向下取整除法,部返回余数 |
x % y |
tf.mod() |
逐元素取模 |
x ** y |
tf.pow() |
逐一计算x中的每一个元素为底数,y中相应的元素为指数时的幂 |
x < y |
tf.less |
逐元素地计算\(x < y\)的真值表 |
x <= y |
tf.less_equal() |
逐元素地计算\(x <= y\)的真值表 |
x > y |
tf.greater() |
逐元素地计算\(x > y\) 的真值表 |
x >= y |
tf.greater_equal() |
逐元素地计算\(x >= y\)的真值表 |
x & y |
tf.logical_and() |
逐元素地计算\(x \& y\)的真值表, 每个元素的dtype属性必须为tf.bool |
x \(\mid\) y |
tf.logical_or() |
逐元素地计算\(x \mid y\)的真值表, 每个元素的dtype属性必须为tf.bool |
x ^ y |
tf.logical_xor() |
逐元素地计算x ^ y 的真值表, 每个元素的dtype属性必须为tf.bool |
tf.equal()
和tf.not_equal
用于检查两个张量是否相等,返回布尔值张量,需要使用tf.cast
转化为 \(1\) 和 \(0\)。
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
-c.eval()
array([-6, -8])
tf.negative(c).eval()
array([-6, -8])
tf.div(34, 5).eval()
6
a = np.array([1, 3, 5, 4])
b = np.array([3, 4, 2, 3])
a ** b
array([ 1, 81, 25, 64], dtype=int32)
np.power(a, b)
array([ 1, 81, 25, 64], dtype=int32)
tf.pow(a, b).eval()
array([ 1, 81, 25, 64])
a == b
array([False, False, False, False], dtype=bool)
np.equal(a, b)
array([False, False, False, False], dtype=bool)
tf.equal(a, b).eval()
array([False, False, False, False], dtype=bool)
c = tf.constant(a)
d = tf.constant(b)
c == d
False
tf.equal(c, d).eval()
array([False, False, False, False], dtype=bool)
import numpy as np
a = np.array([1.44, 3.33, 5.0, 4])
b = np.array([-3, 4, -2, 3])
tf.ceil(a).eval() # 向上取整
array([ 2., 4., 5., 4.])
tf.floor(a).eval() # 向下取整
array([ 1., 3., 5., 4.])
tf.round(a).eval() # 4舍5入
array([ 1., 3., 5., 4.])
tf.abs(b).eval() # 绝对值
array([3, 4, 2, 3])
tf.cos(a).eval()
array([ 0.13042371, -0.98230378, 0.28366219, -0.65364362])
tf.exp(a).eval()
array([ 4.22069582, 27.9383417 , 148.4131591 , 54.59815003])
tf.maximum(a, b).eval() # 返回两个张量中最大的值
array([ 3., 4., 5., 4.])
tf.minimum(a, b).eval()
array([ 1.44, 3.33, 2. , 3. ])
tf.rsqrt(a).eval() # 返回平方根的倒数
array([ 0.83333333, 0.54799662, 0.4472136 , 0.5 ])
tf.sqrt(a).eval() # 返回平方根
array([ 1.2 , 1.82482876, 2.23606798, 2. ])
c = tf.constant([-2, 4, 5, 0, -3])
tf.sign(c).eval() # 根据输入的张量的符号,符号-1,1, 0
array([-1, 1, 1, 0, -1])
tf.square(c).eval() # 张量的平方
array([ 4, 16, 25, 0, 9])
tf.digamma(a).eval() # 浦西函数(Psi函数),lgamma() 函数的导数
array([-0.02114267, 1.04537223, 1.50611767, 1.25611767])
tf.erf(a).eval() # 高斯误差函数
array([ 0.95829657, 0.99999751, 1. , 0.99999998])
tf.erfc(a).eval() # 互补误差函数
array([ 4.17034304e-02, 2.48530987e-06, 1.53745979e-12,
1.54172579e-08])
tf.igamma(a, b).eval() # 下不完全伽马函数
array([ 0.89723547, 0.70058193, 0.05265302, 0.35276811])
tf.igammac(a, b).eval() # 上不完全伽马函数
array([ 0.10276453, 0.29941807, 0.94734698, 0.64723189])
tf.lbeta(a).eval() # 贝塔函数绝对值的自然对数
-16.088605561849441
tf.lgamma(a).eval() # 伽马函数绝对值的自然对数
array([-0.12125837, 1.01830177, 3.17805383, 1.79175947])
tf.squared_difference(a, b).eval() # 差值的平方
array([ 2.4336, 0.4489, 9. , 1. ])
2.3 节点的依赖关系
我们可以将整个节点序列抽象为拥有输入和输出的离散构件。这样使得级联在一起的若干运算组进行可视化更加容易,而无需关注每个部件的具体细节。
对于任意节点A,若其输出对于某个后继节点B的计算是必需的,则称节点A为节点B的依赖节点。
若某个节点A和节点B彼此不需要来自对方的任何信息,则称两者是独立的。
任何节点都可以将其输出传递给数据流图中的任何后继节点,而无论这两者之间发生了多少计算。
在TensorFlow中,真正的循环依赖关系是无法表示的,在实际使用中,完全可以通过对数据流图进行有限次的复制,然后将它们并排放置,并将代表相邻迭代轮次的副本的输出与输入串接。(此过程称为数据流图的“展开(unrolling)”)这样等价于将之前的数据流图遍历多次。
3 Graph对象
创建一个Graph对象的方法十分简单:
# 创建一个新的数据流图
g = tf.Graph()
Graph对象初始化完成后,便可利用tf.Graph.as_default()
方法访问其上下文管理器,为其添加Op。结合with语句,可利用上下文管理器通知TensorFlow我们需要添加到某个特定的Graphdx中:
with g.as_default():
# 创建一些Op,它们将会被添加到Graph对象g中
a = tf.multiply(2, 3)
...
当TensorFlow库被加载时,它会自动创建一个Graph对象,并将其作为默认的数据流图。因此,在tf.Graph.as_default()
上下文管理器之外的任何Op、Tensor对象都会自动放置在默认的数据流图中:
# 放置在默认数据流图中
in_default_graph = tf.add(1, 2)
# 放置在默认数据流图 g 中
with g.as_default():
# 创建一些Op,它们将会被添加到Graph对象g中
in_graph_g = tf.multiply(2, 3)
# 由于不在with语句块中,下面的Op将放置在默认的数据流图中
also_in_default_graph = tf.subtract(5, 1)
如果希望得到默认数据流图的句柄,可使用tf.get_default_graph()
函数:
default_graph = tf.get_default_graph()
default_graph
<tensorflow.python.framework.ops.Graph at 0x251a066ca20>
- 如若需要定义多个相互之间不存在依赖关系的模型,则创建多个Graph对象十分有用。
- 当需要在单个文件中定义多个数据流图时,最佳的实践是不使用默认数据流图,或为其立即分配句柄。这样可以保证各个节点按照一致的方式添加到每个数据流图中。
3.1 正确的实践——创建新的数据流图,将默认的数据流图忽略
import tensorflow as tf
g1 = tf.Graph()
g2 = tf.Graph()
with g1.as_default():
# 定义g1的Op、张量等
...
with g2.as_default():
# 定义g2的Op、张量等
...
3.2 正确的实践——获取默认数据流图的句柄
import tensorflow as tf
g1 = tf.get_default_graph()
g2 = tf.Graph()
with g1.as_default():
# 定义g1的Op、张量等
...
with g2.as_default():
# 定义g2的Op、张量等
...
3.3 错误的实践——将默认的数据流图和用户创建的数据流图混合使用
import tensorflow as tf
g2 = tf.Graph()
# 定义默认的数据流图的Op、张量等
...
with g2.as_default():
# 定义g2的Op、张量等
...
此外,从其他TensorFlow脚本中加载之前定义过的模型,并利用Graph.as_graph_def()
和tf.import_graph_def()
函数将其赋给Graph对象也是可行的。这样用户可在同一个Python文件中计算和使用若干独立的模型输出。
4 Session
Session
类负责数据流图的执行。
4.1 构造方法
tf.Session()
接收3个可选参数:
-
target
指定了所要使用的执行引擎。- 对于大多数应用,该参数取为默认的空字符串。
- 在分布式设置中该参数用于连接不同的
tf.train.Server
实例。
-
graph
指定了将要加载的Graph对象,其默认值为None,表示将使用当前默认数据流图。当使用多个数据流图时,最好的传入方式是显式传入你希望运行的Graph对象(而非在一个with语句块内创建Session对象)。 -
config
参数允许用户指定配置Session对象所需选项,如限制CPU或GPU的使用数目,为数据流图设置优化参数和日志选项等。
在典型的TensorFlow程序中,创建Session对象时无需改变任何默认构造参数。
import tensorflow as tf
# 创建Op、Tensor对象等(使用默认数据流图)
a = tf.add(2, 5)
b = tf.multiply(a, 3)
# 利用默认数据流图启动一个Session对象
sess = tf.Session()
# 或者传入参数
sess = tf.Session(graph = tf.get_default_graph())
一旦创建完Session,便可利用其主要方法run()
或eval()
来计算所期望的Tensor对象的输出:
sess.run(b)
21
b.eval()
21
4.2 Session.run()
run()接收一个参数fetchs
,以及其他三个可选参数:feed_dict
、options
和run_metadata
。
fetchs
参数接收任意的数据流图元素(Op、Tensor对象),后者指定了用户希望执行的对象。
- 若请求对象为Tensor,则
run()
的输出为一个NumPy数组; - 若请求对象为一个Op,则输出为None。
- 若请求对象为一个数据流图元素的列表,则输出一个与所请求的元素对应的值的列表。
sess.run([a, b])
[7, 21]
feed_dict
参数用于覆盖数据流图中的Tensor对象值,它需要Python字典对象作为输入。字典中的“键”为指向应当覆盖的Tensor对象的句柄,而字典的“值”、字符串、列表或NumPy数组。
这些“值”的类型必须与Tensor的“键”相同,或能转化为相同的类型。
# 定义一个字典,将a的值替换为15
replace_dict = {a: 15}
# 将replace_dict赋值给feed_dict
sess.run(b, feed_dict= replace_dict)
45
# 关闭数据流图,释放资源
sess.close()
5 利用占位节点添加输入
占位符的行为和Tensor对象一致,但在创建时无需为它们指定具体的数值。它的作用是为运行时即将到来的某个Tensor对象预留位置,因此实际上变成了“输入”节点。
利用tf.placeholder
Op可创建占位符。
-
dtype
(是必须指定的)指定了该占位符的值的数据类型。 -
shape
(可选)指定了传入的Tensor对象的形状。默认值为None
,表示可以接收任意形状的Tensor对象。 - 与任何Op一样,也可以在
tf.placeholder
中指定一个name
标识符。 - 为了给占位符传入一个实际的值,需要使用
Session.run()
的feed_dict
参数。将指向占位符输出的句柄作为字典的“键”,而希望传入的Tensor对象作为字典的“值”:
# 创建一个长度为2,数据类型为int32的占位向量
a = tf.placeholder(tf.int32, shape= [2], name= 'my_input')
# 将该占位符视为其他任意Tensor对象,加以使用
b = tf.reduce_prod(a, name= 'prob_a')
c = tf.reduce_sum(a, name= 'sum_a')
# 完成数据流图的定义
d = tf.add(b, c, name= 'add_d')
sess = tf.Session()
# 创建一个将传给feed_dict参数的字典
# “键”:`a` 指向占位符输出Tensor对象的句柄
input_dict = {a: np.array([5, 3], dtype= np.int)}
# 计算d, 将input_dict的“值”传给a
sess.run(d, feed_dict= input_dict)
23
sess.run(a, feed_dict= input_dict)
array([5, 3])
6 Variable对象
Tensor对象和Op对象都是不可变的(immutable),Variable对象是可变的。
6.1 创建Variable对象
tf.Variable()
# 为Variable对象传入初始值
my_var = tf.Variable(3, name= 'my_variable')
Variable对象可用于任何可能会使用Tensor对象的TensorFlow函数或Op中,其当前值将传给使用它的Op:
add = tf.add(5, my_var)
mul = tf.multiply(8, my_var)
6.2 Variable对象初始化
注意:tf.truncated_normal()
函数不会创建任何偏离均值超过2倍标准差的值,从而可以防止有一个或两个元素于该张量中的其他元素显著不同的情况出现:
# 该Tensor对象不会返回任何小于0.3或大于7.0的值
trunc = tf.truncated_normal([2, 2], mean= 5.0, stddev= 1.0)
可像手工初始化张量那样将Op作为Variable对象的初值传入:
random_var = tf.Variable(tf.truncated_normal([2, 2])) # 默认均值为0, 标准差为 1
Variable对象与大多数其他TensorFlow对象在Graph中存在的方式都比较类似,但是它们的状态实际上是由Session对象管理的。因此,为使用Variable对象,必须在一个Session对象内对Variable对象进行初始化(tf.global_variables_initializer().run()
)这样会使Session对象开始追踪Variable对象的值的变化。
tf.variables_initializer()
对部分Variable对象进行初始化。
6.3 Variable对象的修改
可使用Variable.assign()
(是一个Op,要使其生效必须在一个Session对象中运行)方法修改Variable对象:该方法的作用是为Variable对象赋予新值。
# 创建初始值为 1 的 Variable对象
my_var = tf.Variable(1)
# 创建一个Op,使其在每次运行时都将该Variable对象乘以 2
my_var_times_two = my_var.assign(my_var * 2)
# 初始化Op
init_op = tf.global_variables_initializer()
# 启动一个会话
sess = tf.Session()
# 初始化Variable对象
sess.run(init_op)
# 将Variable对象乘以 2,并将其返回
sess.run(my_var_times_two)
2
# 再次相乘
sess.run(my_var_times_two)
4
# 再次相乘
sess.run(my_var_times_two)
8
对于Variable对象自增、自减:Variable.assign_add()
、Variable.assign_sub()
# 自增 1
sess.run(my_var.assign_add(1))
9
# 自减 1
sess.run(my_var.assign_sub(1))
8
由于不同的Session对象会各自独立地维护Variable对象的值,因此每个Session对象都拥有自己的、在Graph对象中定义的Variable对象的当前值:
# 创建一些Op
my_var = tf.Variable(0)
init_op = tf.global_variables_initializer()
# 启动多个Session对象
sess1 = tf.Session()
sess2 = tf.Session()
# 在sess1内对Variable对象进行初始化,以及在同一Session对象中对my_var的值自增
sess1.run(init_op)
sess1.run(my_var.assign_add(5))
5
# 在sess2内对Variable对象进行初始化,以及在同一Session对象中对my_var的值自增
sess2.run(init_op)
sess2.run(my_var.assign_add(2))
2
# 能够在不同的Session对象中独立地对Variable对象的值实施自增运算
sess1.run(my_var.assign_add(5))
10
sess2.run(my_var.assign_add(2))
4
如果希望将所有的Variable对象的值重置为初始值,则只需再次调用tf.global_variables_initializer()
,如若只希望对部分Variable对象重新初始化,可调用tf.variables_initializer()
# Variable对象的值重置为初始值
sess1.run(init_op)
sess1.run(my_var)
0
my_var = tf.Variable(2)
my_var1 = tf.Variable(5)
my_var_times_two = my_var.assign(my_var * 2)
my_var1_times_two = my_var.assign(my_var1 * 2)
sess = tf.Session()
# 部分Variable对象的值重置为初始值
sess.run(tf.variables_initializer([my_var, my_var1]))
print(sess.run(my_var_times_two))
print(sess.run(my_var1_times_two))
4
10
6.4 trainable 参数
Optimizer
为自动训练机器学习模型的类,它们可以自动修改Variable对象的值,而无需显式地做出请求。
如果要求Graph对象中的一些Variable对象只可手工修改,而不允许使用Optimizer
类,可在创建这些Variable对象时将其参数trainable
设置为False
。
not_trainable = tf.Variable(0, trainable= False)
对于迭代计数器或其他任何不涉及机器学习模型计算的Variable对象,通常都需要将Variable对象的参数trainable设置为False。
7 通过名称作用域组织数据流图
名称作用域(name scope)非常易于使用,且在用TensorBoard对Graph对象可视化时极有价值。
本质上,名称作用域允许将Op划分到一些较大的、有名称的语句块中。当以后使用TensorBoard加载数据流图时,每个名称作用域都将对其自己的Op进行封装,从而获得更好的可视化效果。
名称作用域的基本用法是将Op添加到语句块with tf.name_scope(<name>)
中。
with tf.name_scope('Scope_A'):
a = tf.add(1, 2, name= 'A_add')
b = tf.multiply(a, 3, name= 'A_mul')
with tf.name_scope('Scope_B'):
c = tf.add(4, 5, name= 'B_add')
d = tf.multiply(c, 6, name= 'B_mul')
e = tf.add(b, d, name= 'output')
# 打开一个summary.FileWriter对象,并将Graph对象写入磁盘
writer = tf.summary.FileWriter('./name_scope_1',
graph= tf.get_default_graph())
writer.close()
可视化
由于summary.FileWriter
对象会将数据流图立即导出,可在运行完上述代码便启动TensorBoard。导航到运行上述脚本的路径,并启动TensorBoard:
!tensorboard --logdir= './name_scope_1'
Traceback (most recent call last):
File "c:\programdata\anaconda3\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\programdata\anaconda3\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\ProgramData\Anaconda3\Scripts\tensorboard.exe\__main__.py", line 9, in <module>
File "c:\programdata\anaconda3\lib\site-packages\tensorboard\main.py", line 36, in run_main
tf.app.run(main)
File "c:\programdata\anaconda3\lib\site-packages\tensorflow\python\platform\app.py", line 48, in run
_sys.exit(main(_sys.argv[:1] + flags_passthrough))
File "c:\programdata\anaconda3\lib\site-packages\tensorboard\main.py", line 45, in main
default.get_assets_zip_provider())
File "c:\programdata\anaconda3\lib\site-packages\tensorboard\program.py", line 161, in main
tb = create_tb_app(plugins, assets_zip_provider)
File "c:\programdata\anaconda3\lib\site-packages\tensorboard\program.py", line 185, in create_tb_app
raise ValueError('A logdir must be specified when db is not specified. '
ValueError: A logdir must be specified when db is not specified. Run `tensorboard --help` for details and examples.
!tensorboard --help
usage: tensorboard.exe [-h]
[--debugger_data_server_grpc_port DEBUGGER_DATA_SERVER_GRPC_PORT]
[--logdir LOGDIR] [--host HOST] [--port PORT]
[--purge_orphaned_data [PURGE_ORPHANED_DATA]]
[--nopurge_orphaned_data]
[--reload_interval RELOAD_INTERVAL] [--db DB]
[--inspect [INSPECT]] [--noinspect] [--tag TAG]
[--event_file EVENT_FILE] [--path_prefix PATH_PREFIX]
optional arguments:
-h, --help show this help message and exit
--debugger_data_server_grpc_port DEBUGGER_DATA_SERVER_GRPC_PORT
The port at which the debugger data server (to be
started by the debugger plugin) should receive
debugging data via gRPC from one or more debugger-
enabled TensorFlow runtimes. No debugger plugin or
debugger data server will be started if this flag is
not provided.
--logdir LOGDIR logdir specifies the directory where TensorBoard will
look to find TensorFlow event files that it can
display. TensorBoard will recursively walk the
directory structure rooted at logdir, looking for
.*tfevents.* files. You may also pass a comma
separated list of log directories, and TensorBoard
will watch each directory. You can also assign names
to individual log directories by putting a colon
between the name and the path, as in tensorboard
--logdir name1:/path/to/logs/1,name2:/path/to/logs/2
--host HOST What host to listen to. Defaults to serving on all
interfaces, set to 127.0.0.1 (localhost) to disable
remote access (also quiets security warnings).
--port PORT What port to serve TensorBoard on.
--purge_orphaned_data [PURGE_ORPHANED_DATA]
Whether to purge data that may have been orphaned due
to TensorBoard restarts. Disabling purge_orphaned_data
can be used to debug data disappearance.
--nopurge_orphaned_data
--reload_interval RELOAD_INTERVAL
How often the backend should load more data.
--db DB [Experimental] Sets SQL database URI. This mode causes
TensorBoard to persist experiments to a SQL database.
The following databases are supported: - sqlite: Use
SQLite built in to Python. URI must specify the path
of the database file, which will be created if it
doesn't exist. For example: --db
sqlite3:~/.tensorboard.db Warning: This feature is a
work in progress and only has limited support.
--inspect [INSPECT] Use this flag to print out a digest of your event
files to the command line, when no data is shown on
TensorBoard or the data shown looks weird. Example
usages: tensorboard --inspect --event_file
myevents.out tensorboard --inspect --event_file
myevents.out --tag loss tensorboard --inspect --logdir
mylogdir tensorboard --inspect --logdir mylogdir --tag
loss See
tensorflow/python/summary/event_file_inspector.py for
more info and detailed usage.
--noinspect
--tag TAG The particular tag to query for. Only used if
--inspect is present
--event_file EVENT_FILE
The particular event file to query for. Only used if
--inspect is present and --logdir is not specified.
--path_prefix PATH_PREFIX
An optional, relative prefix to the path, e.g.
"/path/to/tensorboard". resulting in the new base url
being located at localhost:6006/path/to/tensorboard
under default settings. A leading slash is required
when specifying the path_prefix, however trailing
slashes can be omitted. The path_prefix can be
leveraged for path based routing of an elb when the
website base_url is not available e.g.
"example.site.com/path/to/tensorboard/"
探寻有趣之事!