1. TensorFlow命名空间
在深度学习模型构建和训练的过程中,我们常常需要定义很多变量、操作和张量,为了方便管理和控制,TensorFlow提供了命名空间的机制。命名空间可以理解为将一组相关的变量、操作和张量封装在一个命名空间中,以便于管理和复用。TensorFlow提供了两种方式创建命名空间:
1.1 tf.name_scope()
tf.name_scope()可以为变量、操作和张量加上前缀,用来区分归属于不同的命名空间。下面是一个示例:
import tensorflow as tf
with tf.name_scope('input'):
x = tf.placeholder(tf.float32, shape=[None, 784], name='x')
y_ = tf.placeholder(tf.float32, shape=[None, 10], name='y_')
with tf.name_scope('hidden1'):
W = tf.Variable(tf.truncated_normal([784, 256], stddev=0.1), name='W')
b = tf.Variable(tf.zeros([256]), name='b')
hidden1 = tf.nn.relu(tf.matmul(x, W) + b)
with tf.name_scope('output'):
W1 = tf.Variable(tf.truncated_normal([256, 10], stddev=0.1), name='W1')
b1 = tf.Variable(tf.zeros([10]), name='b1')
y = tf.matmul(hidden1, W1) + b1
通过使用tf.name_scope(),我们可以将x、y_、W、b、hidden1、W1、b1都封装在不同的命名空间中。在TensorBoard中查看图节点时,可以发现类似于下面这样的结构:
1.2 tf.variable_scope()
tf.variable_scope()与tf.name_scope()类似,也可以创建命名空间,并且可以共享变量。不同之处在于,tf.variable_scope()可以通过设置reuse参数,使得不同的命名空间可以共享相同的变量。下面是一个示例:
import tensorflow as tf
def my_network(input):
with tf.variable_scope('hidden1'):
W = tf.get_variable('W', [784, 256], initializer=tf.truncated_normal_initializer(stddev=0.1))
b = tf.get_variable('b', [256], initializer=tf.constant_initializer(0.0))
hidden1 = tf.nn.relu(tf.matmul(input, W) + b)
with tf.variable_scope('output'):
W1 = tf.get_variable('W1', [256, 10], initializer=tf.truncated_normal_initializer(stddev=0.1))
b1 = tf.get_variable('b1', [10], initializer=tf.constant_initializer(0.0))
output = tf.matmul(hidden1, W1) + b1
return output
x = tf.placeholder(tf.float32, shape=[None, 784], name='x')
y_ = tf.placeholder(tf.float32, shape=[None, 10], name='y_')
with tf.variable_scope('network'):
y = my_network(x)
with tf.variable_scope('network', reuse=True):
y2 = my_network(x)
在上面的代码中,我们使用tf.get_variable()创建变量,并且在my_network函数中将变量封装在两个命名空间中。在外部定义的y和y2在相同的命名空间中,它们使用了相同的网络参数。通过reuse参数的设置,我们将y2的当前scope和y的scope设置为相同的命名空间,这样它们就可以共享相同的变量。事实上,tf.variable_scope()常用于使用LSTM和GRU等循环神经网络中实现权值共享。
2. TensorBoard图节点实例
TensorBoard是TensorFlow提供的可视化工具,可以帮助我们更加直观地了解模型的构建和运行过程。下面我们给出一个简单的线性回归模型,在TensorBoard中查看图节点的例子。
import tensorflow as tf
import numpy as np
# 构建数据集
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data * 0.1 + 0.3
# 定义变量
with tf.name_scope('input'):
x = tf.placeholder(tf.float32, name='x')
y_ = tf.placeholder(tf.float32, name='y_')
with tf.name_scope('parameters'):
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0), name='W')
b = tf.Variable(tf.zeros([1]), name='b')
# 定义前向传播过程
with tf.name_scope('forward'):
y = tf.multiply(W, x) + b
# 定义损失函数和优化器
with tf.name_scope('loss'):
loss = tf.reduce_mean(tf.square(y - y_))
tf.summary.scalar('loss', loss)
with tf.name_scope('train'):
optimizer = tf.train.GradientDescentOptimizer(0.5)
train_step = optimizer.minimize(loss)
# 定义会话和日志记录
merged_summary = tf.summary.merge_all()
with tf.Session() as sess:
writer = tf.summary.FileWriter('logs/', sess.graph)
sess.run(tf.global_variables_initializer())
for i in range(201):
summary, _, loss_val, W_val, b_val = sess.run([merged_summary, train_step, loss, W, b], feed_dict={x: x_data, y_: y_data})
if i % 20 == 0:
print("Step %d: loss = %f, W = %f, b = %f" % (i, loss_val, W_val, b_val))
writer.add_summary(summary, i)
writer.close()
在上面的代码中,我们首先构建了一个简单的线性回归模型,然后使用tf.summary.scalar()函数记录了损失函数的变化,并将所有的summary操作合并到一起。最后,我们在每次训练迭代完之后,将summary和迭代次数写入到tf.summary.FileWriter中,以便将来在TensorBoard中查看。下面是在TensorBoard中查看graph和scalars的效果:
在上面的效果图中,我们可以看到,TensorBoard将我们构建的图像转化为一个个的节点,通过拖动和缩放可以很方便地进行查看。同时,我们也可以看到损失函数的变化趋势,这有助于我们对模型进行调试和调优。