TensorFlow中的variables和get_variable之间的区别

据我所知, Variable是制作variables的默认操作, get_variable主要用于权重分享。

一方面,有一些人build议使用get_variable而不是原始的Variable操作,只要你需要一个variables。 另一方面,我只是在TensorFlow的官方文档和演示中看到使用get_variable

因此,我想知道如何正确使用这两种机制的一些经验法则。 有没有“标准”的原则?

我build议始终使用tf.get_variable(...) – 如果您需要随时共享variables(例如,在多gpu设置中tf.get_variable(...) ,则可以更轻松地重构代码(请参阅multi-gpu CIFAR示例)。 它没有坏处。

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

tf.Variable是一个类,有几种创buildtf.Variable的方法,包括tf.Variable .__ init__和tf.get_variable。

tf.Variable .__ init__:用initial_value创build一个新的variables。

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

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

 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()) 

更多信息请参见https://www.tensorflow.org/versions/r0.8/api_docs/python/state_ops.html#Variable

我可以find两者之间的主要区别:

  1. 首先是tf.Variable总是会创build一个新的variables,无论tf.get_variable是否从图中得到一个已经存在的variables与这些参数,如果它不存在,它会创build一个新的variables。

  2. tf.Variable要求指定一个初始值。

需要澄清的是,函数tf.get_variable在当前variables作用域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 

最后一个断言错误很有趣:在相同范围内有两个同名的variables应该是同一个variables。 但是如果你testingvariablesde的名字,你会发现Tensorflow改变了variablese的名字:

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