TensorFlow学习笔记(三)——变量管理

前言:

       TensorFlow提供了通过变量名称来创建或者获取一个变量的机制。通过这个机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过参数的形式到处传递。TensorFlow 中通过变量名称获取变量的机制主要是通过 tf.get_variable 和tf.variable_scope数实现的。分别介绍如何使用这两个函数。

一、变量的创建方式—— tf.Variable和 tf.get_variable函数

    通过 tf.Variable函数来创建一个变量。除了 tf.Variable函数,TensorFlow 提供了tf.get_variable函数来或者获取变量。当 tf.get_variable用于创建变量,它和tf.Variable的功能是基本等价的。以下代码过这两个函数创建一个变量的样例:

#coding=gbk
import  tensorflow  as  tf

#下面这两个定义是等价的
v = tf.get_variable("v", shape=[1],initializer=tf.constant_initializer(1.0))
v1 = tf.Variable(tf.constant(1.0, shape=[1]), name="v1")

#打印变量的值
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    print("v:",sess.run(v))
    print("v的类型:", type(sess.run(v)))
    print("v1:",sess.run(v1))
    print("v1的类型:", type(sess.run(v1)))

运行程序,输出:


    从上的代码中可以出, tf.Variable和 tf.get_variable函数创变量的过上是一样的,同时变量的结果也是一样的。tf.get_variable函数调用时提供的维度(shape)信息以初始化方法(initializer) tf.Variable函数调时提供的初过程中的参数类似。在上面的例程序中使用到的常数初始化函数 tf.constant_initializer成函数tf.constant功能上就是一的。

      tf.get_variable函数与tf.Variable函数最大的区别在于指定变量名称的参数。对于tf.Variable,变量名称是一个可选的参数,通过name=”v“的形式给出。但是对于tf.get_variable函数,变量名称是一个必填的参数。tf.get_variable会根据这个名字去创建或者获取变量。


二、变量的获取方式—— tf.variable_scope函数

       在上面的样例程序中,tf.get_variable首会试去创建一名字为v的参数,如果创建失败(比如已经有名的参数),么这个程就会报错。这是为避免无意识的变量复用造成的错误比如在定义神经网络参数时,第一层网络的权重已经叫 weights了,那么在创建第二层网络时果参名仍然叫 weights,就会触发变量重用误。则两层经网会出一些比较难以发的错误。果需要通过tf.get_variable获取一个建的变量,需要通过tf.variable_scope函数来生成一个上下文管理器,确指定在这个上下文管理器中,tf.get_variable将直接获取已经成的量。

       下给出一段代何通tf.variable_scope函数来tf.get_variable函数获取已经建过的变

#coding=gbk
import tensorflow as tf

#在名字为namespace_1的命名空间内创建名字为v的变量
with tf.variable_scope("namespace_1"):
    v = tf.get_variable("v", [1], initializer = tf.constant_initializer(1.0))

#因为在命名空间namespace_1中已经存在名字为v的变量,所有下面的代码将会报错:
with tf.variable_scope("namespace_1"):
    v = tf.get_variable("v", [1])

运行程序,输出报错:


显然,在同一个命名空间内创建同名的变量是不允许的。再看看下面这段程序:

#coding=gbk
import tensorflow as tf

#在名字为namespace_1的命名空间内创建名字为v的变量
with tf.variable_scope("namespace_1",reuse=False):
    v = tf.get_variable("v", [1], initializer = tf.constant_initializer(1.0))

# 在生成上下文管理器时,将参数reuse设置为True。这样tf.get_variable函数将直接获取已经声明的变量
with tf.variable_scope("namespace_1", reuse=True) :
    v1 = tf.get_variable("v",[1])
    with tf.Session() as sess:
        init_op = tf.global_variables_initializer()
        sess.run(init_op)
        print(v1 == v)
        print("v1:", sess.run(v1))
        print(v1)
运行程序,输出:

     上面的程序简单地说明 tf.variable_scope 函数可控制tf.get_variable 函数的语义。当 tf.variable_scope函数使用 reuse=True成上下文管理器时,这上下文管理器内所有的 tf.get_variable函数会直接获取创建的变量。如果变量不存 tf.get_variable 函数报错相反,如果 tf.variable_scope函数使用 reuse=None或者 reuse=False创建上下管理器,tf.get_variable 操作将创建新的变量。如果同名的变量已经存在,tf.get_variable函数将报错。


三、通过tf.variable_scope管理变量的名称

       tf.variable_scope函数生成的上下文管理器也会创建一个 TensorFlow中的命名空间,在命名空间内创建的变量名称都会带上这个命名空间名作为前缀。所以,tfvariable_scope函数除了可以控制 tf.get_variable执行的功能之外,这个函数也提供了一个管理变量命名空间的方式。以下代码显示了如何通过 tf.variable_scope来管理变量的名称

#coding=gbk
import tensorflow as tf

v1 = tf.get_variable("v",[1])
print(v1.name )
# 输出v:0。“v”为变量的名称,其中“ :0”表示这个变量是生成变量这个运算的第一个结果

with tf.variable_scope("namespace_1"):
    v2 = tf.get_variable("v", [1])
    print(v2.name )
    # 输出namespace_1/v:0。在tf.variable_scope中创建的变量,名称前面会加入命名空间的名称,
    # 并通过/来分隔命名空间的名称和变量的名称

with tf.variable_scope("namespace_1") :
    with tf.variable_scope("namespace_2"):
        v3 = tf.get_variable("v",[1])
        print(v3.name )
        # 输出 namespace_1/namespace_2/v;0。命名空间可以嵌套,同时变量的名称也会加
        # 入所有命名空间的名称作为前缀

    v4 = tf.get_variable("v1", [1])
    print(v4.name)
    #输出 namespace_1/v1:0。当命名空间退出之后,变量名称也就不会再被加入其前缀了。


# 创建一个名称为空的命名空间,并设置 reuse=True。
# 可以直接通过带命名空间名称的变量名来获取其他命名空间下的变量。
# 比如这里通过指定名称namespace_1/namespace_2/v来获取在命名空间namespace_1/namespace_2中创建的变量。
with tf.variable_scope("", reuse=True):
    v5 = tf.get_variable("namespace_1/namespace_2/v",[1])
    print(v5 == v3)     #输出True
    v6 = tf.get_variable("namespace_1/v1",[1])
    print(v6 == v4)      #输出True

运行程序,输出:


参考文献:

[1]  郑泽宇著  《TensorFlow实战Google深度学习框架》

[2] 黄文坚著   《TensorFlow实战》

猜你喜欢

转载自blog.csdn.net/weixin_41695564/article/details/80178370