tensorflow学习笔记1:tf.Variable、tf.get_variable与tf.get_variable、tf.variable_scope对比总结

**

0. 浅谈tensorflow变量机制

**
tensorflow提供了通过变量名称来创建或者获取一个变量的机制。通过这个机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过参数的形式到处传递,实现了变量共享。
**

1. 对比tf.Variable与tf.get_variable

**

tf.Variable(initial_value=None, trainable=True, collections=None, validate_shape=True, caching_device=None, name=None, variable_def=None, dtype=None, expected_shape=None, import_scope=None)
tf.get_variable(name, shape=None, dtype=None, initializer=None, regularizer=None, trainable=True, collections=None, caching_device=None, partitioner=None, validate_shape=True, custom_getter=None)

共同点:
如果没有创建变量对象的话,就创建一个新的变量。
区别:
tf.Variable() :运行到第二个拥有相同名字的变量的时候,创建新对象。
get_variable():拥有一个变量检查机制,运行到第二个拥有相同名字的变量的时候,会检测已经存在的变量是否设置为共享变量(reuse=True),如果已经存在的变量没有设置为共享变量,就会报错;如果设置为共享变量,就把那个对象返回。

v = tf.Variable(tf.constant(1.0, shape=[1]), name='v')

//不报错,每次创建新的名为‘v’的变量
v = tf.Variable(tf.constant(1.0, shape=[2]), name='v')
v = tf.get_variable('v', shape=[1], initializer=tf.constant_initializer(1.0))

//ValueError: Variable v already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? 
v = tf.get_variable('v', shape=[2], initializer=tf.constant_initializer(1.0))

**

2. tf.get_variable与tf.variable_scope的关系

**
这两个函数是变量共享主要涉及到两个函数。
上面提到的通过tf.get_variable来获取一个已经创建的变量,需要使用tf.variable_scope()函数实现,tf.variable_scope会生成一个上下文管理器,并明确指定在这个上下文管理器中,tf.get_variable将直接获得已经生成的变量。
【注意:当reuse=true时只能获取已经存在的变量,不能创建新变量,否则报错见下例】

//ValueError: Variable foo/v does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?
with tf.variable_scope('test', reuse=True):
    v = tf.get_variable('v',[1])

正确使用方法例子:

// create “foo/v”
with tf.variable_scope('test'):
    v = tf.get_variable('v',[1], initializer=tf.constant_initializer(1.0))

先创建变量(创建时reuse默认为false,见上),再获取变量(获取时reuse设置为true,见下)。

// find “foo/v”
with tf.variable_scope('test', reuse=True):
    v1 = tf.get_variable('v',[1])

**

3. tf.variable_scope与tf.name_scope的关系

**
引:
这两个都是名字作用域的概念:既然用到变量名了,就涉及到了名字域的概念–通过不同的域来区别变量名,毕竟让我们给所有变量都直接取不同名字还是有点辛苦的,这就是为什么会有scope 的概念。
差别:
对于tf.Variable()函数,两者的使用情况都一样;
而对于tf.get_variable()函数,它不受name_scope约束,name_scope 会对operation 起作用,已经声明过的变量就不能再声明了。

例子1:

with tf.name_scope("scope1"):
    v1 = tf.get_variable("v1", [1], dtype=tf.float32)
    x = 1.0 + v1
    v2 = tf.Variable(1, name="v2", dtype=tf.float32)

with tf.variable_scope("scope2"):
    v3 = tf.get_variable("v1", [1], dtype=tf.float32)
    v4 = tf.Variable(1, name="v2", dtype=tf.float32)
    
print("v1:",v1)
print("x:",x.op)
print("v2:",v2)
print("v3:",v3)
print("v4:",v4)

输出结果为:

v1: <tf.Variable 'v1:0' shape=(1,) dtype=float32_ref>
x: name: "scope1/add"
    op: "Add"...
v2: <tf.Variable 'scope1/v2:0' shape=() dtype=float32_ref>
v3: <tf.Variable 'scope2/v1:0' shape=(1,) dtype=float32_ref>
v4: <tf.Variable 'scope2/v2:0' shape=(1,) dtype=float32_ref>

不难发现:v1 没有“scope1”前缀,而x有“scope1”前缀,这就说明tf.get_variable()函数不受name_scope约束,name_scope 只会影响其 ops 的名字。

例子2:

//“v1”重定义报错,ValueError: Variable v1 already exists, disallowed. 
with tf.name_scope("scope1"):
    v1 = tf.get_variable("v1", [1], dtype=tf.float32)
    x = 1.0 + v1
    v2 = tf.Variable(1, name="v2", dtype=tf.float32)

with tf.name_scope("scope2"):
    v3 = tf.get_variable("v1", [1], dtype=tf.float32)
    v4 = tf.Variable(1, name="v2", dtype=tf.float32)
//不报错
with tf.variable_scope("scope1"):
    v1 = tf.get_variable("v1", [1], dtype=tf.float32)
    x = 1.0 + v1
    v2 = tf.Variable(1, name="v2", dtype=tf.float32)

with tf.variable_scope("scope2"):
    v3 = tf.get_variable("v1", [1], dtype=tf.float32)
    v4 = tf.Variable(1, name="v2", dtype=tf.float32)

再次说明了tf.get_variable()函数不受name_scope约束。

猜你喜欢

转载自blog.csdn.net/weixin_39860046/article/details/83340250
今日推荐