一、变量管理
当神经网络的结构更加复杂、参数更多时,需要更好的方式传递和管理神经网络中的参数。
Tensorflow提供了通过变量名称来创建或获取一个变量的机制,通过该机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过参数的形式到处传递。
通过用tf.get_variable
和tf.variable_scope
实现的。
1.1 tf.get_variable()
1.1.1 函数参数
tf.get_variable(
name, shape=None, dtype=None, initializer=None,
regularizer=None, trainable=None, collections=None, caching_device=None, partitioner=None,
validate_shape=True, use_resource=None, custom_getter=None, constraint=None,
synchronization=tf.VariableSynchronization.AUTO, aggregation=tf.VariableAggregation.NONE
)
- name:
- shape:
- dtype:
- initializer:
可以是Tensor,但如果初始化是具体的Tensor, 参数shape不应该指定。 - trainable:
是否参与训练。
1.1.2 例子
# 下面两个定义是等价的.
v = tf.get_variable("v", shape=[1], initializer=tf.constant_initializer(1.0))
v = tf.Variable(tf.constant(1.0, shape=[1]), name="v")
tf.get_variable
函数与tf.Variable
函数最大的区别在于name
参数,对于tf.Variable
函数,变量名称是可选参数,但对于tf.get_variable
函数,变量名称是必填参数。
tf.get_variable
根据去创建还是获取变量,是通过tf.variable_scope
来管理控制的:
详情见下节。
1.2 tf.variable_scope()
1.2.1 函数参数
tf.VariableScope(
reuse, name='', initializer=None, regularizer=None, caching_device=None,
partitioner=None, custom_getter=None, name_scope='', dtype=tf.dtypes.float32,
use_resource=None, constraint=None
)
- initializer:
默认的初始化器,用于get_variable的初始化. - reuse:
True or False or tf.compat.v1.AUTO_REUSE
1.2.2 例子
- 在reuse=False,或者没有指定reuse的命名空间下,使用tf.get_variable()会创建变量,如果该变量已存在,则会报错
- 在reuse=True,使用tf.get_variable()会获取已经创建过的变量,如果该变量不存在,则会报错
with tf.variable_scope("foo"):
v = tf.get_variable("v", [1], initializer=tf.constant_initializer(1.0))
# 下面会报错, 因为命名空间foo中存在名字为v的变量
with tf.variable_scope("foo"):
v = tf.get_variable("v", [1])
with tf.variable_scope("foo", reuse=True):
v1 = tf.get_variable("v", [1])
# 为True, 因为命名空间相同,name也相同
print(v == v1)
with tf.variable_scope("bar", reuse=True):
v = tf.get_variable("v", [1])
对于嵌套tf.variable_scope
, 如果不指定reuse, 则默认取值和外面一层的reuse保持一致。最高层默认为False。
with tf.varibale_scope("root"): # False
with tf.variable_scope("foo", reuse=True): # True
with tf.variable_scope("bar"): # True
1.3 变量复用
1.3.1 例子
import tensorflow as tf
with tf.variable_scope("cc"):
b = tf.constant([[1]], dtype=tf.int64)
for _ in range(2):
with tf.variable_scope("var", reuse=tf.AUTO_REUSE):
a = tf.Variable(name="a", initial_value=1, dtype=tf.int64) # 这个是不支持复用的.
c = tf.get_variable(name="c", initializer=tf.constant(1, dtype=tf.int64), dtype=tf.int64)
b = b + a + c
b = tf.layers.dense(b, units=1)
for var in tf.trainable_variables():
print(var)
最后运行的结果是:
<tf.Variable 'cc/var/a:0' shape=() dtype=int64_ref>
<tf.Variable 'cc/var/c:0' shape=() dtype=int64_ref>
<tf.Variable 'cc/var/dense/kernel:0' shape=(1, 1) dtype=int64_ref>
<tf.Variable 'cc/var/dense/bias:0' shape=(1,) dtype=int64_ref>
<tf.Variable 'cc/var_1/a:0' shape=() dtype=int64_ref>
结论:使用Variable()创建的变量是无法复用的,因此想要一个变量之后复用,需要使用tf.get_variable()来创建.
二、TensorBoard可视化
TensorBoard支持通过Tensorflow命名空间来整理可视化效果图上的节点,Tensorflow计算图中同一个命名空间下的所有节点会被缩略成一个节点,只有顶层空间中的节点才会被显示在TensorBoard可视化效果图上。
通过命名空间,对tensorflow网络实现模块化,处理数据的过程统一放在input
下, 计算损失的函数统一放在loss_function
下,等等。