TensorFlow中Variable和get_variable的区别

Posted

技术标签:

【中文标题】TensorFlow中Variable和get_variable的区别【英文标题】:Difference between Variable and get_variable in TensorFlow 【发布时间】:2016-09-03 01:43:12 【问题描述】:

据我所知,Variable是做变量的默认操作,get_variable主要用于权重共享。

一方面,有人建议在需要变量时使用get_variable 而不是原始的Variable 操作。另一方面,我只是在 TensorFlow 的官方文档和演示中看到了 get_variable 的任何用法。

因此,我想了解一些关于如何正确使用这两种机制的经验法则。有什么“标准”原则吗?

【问题讨论】:

get_variable 是新方式,Variable 是旧方式(可能永远支持),正如 Lukasz 所说(PS:他在 TF 中编写了很多变量名作用域) 【参考方案1】:

tf.Variable 是一个类,创建 tf.Variable 的方法有多种,包括tf.Variable.__init__tf.get_variable

tf.Variable.__init__:用initial_value创建一个新变量。

W = tf.Variable(<initial-value>, name=<optional-name>)

tf.get_variable:使用这些参数获取现有变量或创建一个新变量。你也可以使用初始化器。

W = tf.get_variable(name, shape=None, dtype=tf.float32, initializer=None,
       regularizer=None, trainable=True, collections=None)

使用xavier_initializer等初始化器非常有用:

W = tf.get_variable("W", shape=[784, 256],
       initializer=tf.contrib.layers.xavier_initializer())

更多信息here。

【讨论】:

是的,Variable 实际上我的意思是使用它的__init__。既然get_variable这么方便,我想知道为什么我看到的大多数TensorFlow代码都使用Variable而不是get_variable。在它们之间进行选择时是否有任何约定或因素需要考虑。谢谢! 如果你想有某个值,使用Variable很简单:x = tf.Variable(3)。 @SungKim 通常当我们使用tf.Variable() 时,我们可以将其初始化为截断正态分布的随机值。这是我的例子w1 = tf.Variable(tf.truncated_normal([5, 50], stddev = 0.01), name = 'w1')。这相当于什么?我怎么告诉它我想要一个截断的法线?我应该只做w1 = tf.get_variable(name = 'w1', shape = [5,50], initializer = tf.truncated_normal, regularizer = tf.nn.l2_loss) 吗? @Euler_Salter:您可以使用tf.truncated_normal_initializer() 来获得想要的结果。【参考方案2】:

我可以找到两者之间的两个主要区别:

    首先是tf.Variable 将始终创建一个新变量,而tf.get_variable 从图中获取具有指定参数的现有 变量,如果它不存在,则创建一个新的。

    tf.Variable 要求指定初始值。

重要的是要澄清函数tf.get_variable 以当前变量范围作为名称的前缀,以执行重用检查。例如:

with tf.variable_scope("one"):
    a = tf.get_variable("v", [1]) #a.name == "one/v:0"
with tf.variable_scope("one"):
    b = tf.get_variable("v", [1]) #ValueError: Variable one/v already exists
with tf.variable_scope("one", reuse = True):
    c = tf.get_variable("v", [1]) #c.name == "one/v:0"

with tf.variable_scope("two"):
    d = tf.get_variable("v", [1]) #d.name == "two/v:0"
    e = tf.Variable(1, name = "v", expected_shape = [1]) #e.name == "two/v_1:0"

assert(a is c)  #Assertion is true, they refer to the same object.
assert(a is d)  #AssertionError: they are different objects
assert(d is e)  #AssertionError: they are different objects

最后一个断言错误很有意思:在同一个作用域下,两个同名的变量应该是同一个变量。但是如果你测试变量de的名字你会发现Tensorflow改变了变量e的名字:

d.name   #d.name == "two/v:0"
e.name   #e.name == "two/v_1:0"

【讨论】:

很好的例子!关于d.namee.name,我刚刚遇到了一个解释它的this TensorFlow doc on tensor graph naming operation:If the default graph already contained an operation named "answer", the TensorFlow would append "_1", "_2", and so on to the name, in order to make it unique.【参考方案3】:

另一个区别在于一个在('variable_store',) 集合中,而另一个不在。

请看来源code:

def _get_default_variable_store():
  store = ops.get_collection(_VARSTORE_KEY)
  if store:
    return store[0]
  store = _VariableStore()
  ops.add_to_collection(_VARSTORE_KEY, store)
  return store

让我来说明一下:

import tensorflow as tf
from tensorflow.python.framework import ops

embedding_1 = tf.Variable(tf.constant(1.0, shape=[30522, 1024]), name="word_embeddings_1", dtype=tf.float32) 
embedding_2 = tf.get_variable("word_embeddings_2", shape=[30522, 1024])

graph = tf.get_default_graph()
collections = graph.collections

for c in collections:
    stores = ops.get_collection(c)
    print('collection %s: ' % str(c))
    for k, store in enumerate(stores):
        try:
            print('\t%d: %s' % (k, str(store._vars)))
        except:
            print('\t%d: %s' % (k, str(store)))
    print('')

输出:

collection ('__variable_store',): 0: 'word_embeddings_2': <tf.Variable 'word_embeddings_2:0' shape=(30522, 1024) dtype=float32_ref>

【讨论】:

【参考方案4】:

我建议始终使用tf.get_variable(...)——如果您需要随时共享变量,这将使重构代码变得更加容易,例如在多 GPU 设置中(请参阅多 GPU CIFAR 示例)。它没有缺点。

tf.Variable 是低级的;在某些时候tf.get_variable() 不存在所以一些代码仍然使用低级方式。

【讨论】:

非常感谢您的回答。但是我仍然有一个关于如何在任何地方用tf.get_variable 替换tf.Variable 的问题。那就是当我想用一个 numpy 数组初始化一个变量时,我找不到像tf.Variable 那样干净有效的方法。你如何解决它?谢谢。

以上是关于TensorFlow中Variable和get_variable的区别的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow:variable变量和变量空间

Tensorflow Variable&Constant

[翻译] Tensorflow中name scope和variable scope的区别是什么

如何在 TensorFlow 中使用 tf.get_variable 和 numpy 值初始化变量?

tensorflow中一个tensor怎么转化成tf.get_variable格式

tensorflow中tf.Variable()的使用