TensorFlow 中 Variable 和 get_variable 的区别
Difference between Variable and get_variable in TensorFlow
据我所知,Variable
是做变量的默认操作,get_variable
主要用于权重共享。
一方面,有些人建议在需要变量时使用 get_variable
而不是原始的 Variable
操作。另一方面,我只是在 TensorFlow 的官方文档和演示中看到任何 get_variable
的使用。
因此我想知道一些关于如何正确使用这两种机制的经验法则。有什么"standard"原则吗?
tf.Variable 是一个 class,创建 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。
我建议始终使用 tf.get_variable(...)
——如果您需要随时共享变量,这将使重构代码变得更容易,例如在多 GPU 设置中(参见多 GPU CIFAR 示例)。它没有缺点。
纯tf.Variable
低级;在某些时候 tf.get_variable()
不存在,所以一些代码仍然使用低级方式。
我可以找到两者之间的两个主要区别:
首先是 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
最后一个断言错误很有意思:同一作用域下的两个同名变量应该是同一个变量。但是如果你测试变量名 d
和 e
你会发现 Tensorflow 改变了变量名 e
:
d.name #d.name == "two/v:0"
e.name #e.name == "two/v_1:0"
另一个区别在于一个在('variable_store',)
collection 而另一个不在。
请查看来源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>}
据我所知,Variable
是做变量的默认操作,get_variable
主要用于权重共享。
一方面,有些人建议在需要变量时使用 get_variable
而不是原始的 Variable
操作。另一方面,我只是在 TensorFlow 的官方文档和演示中看到任何 get_variable
的使用。
因此我想知道一些关于如何正确使用这两种机制的经验法则。有什么"standard"原则吗?
tf.Variable 是一个 class,创建 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。
我建议始终使用 tf.get_variable(...)
——如果您需要随时共享变量,这将使重构代码变得更容易,例如在多 GPU 设置中(参见多 GPU CIFAR 示例)。它没有缺点。
纯tf.Variable
低级;在某些时候 tf.get_variable()
不存在,所以一些代码仍然使用低级方式。
我可以找到两者之间的两个主要区别:
首先是
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
最后一个断言错误很有意思:同一作用域下的两个同名变量应该是同一个变量。但是如果你测试变量名 d
和 e
你会发现 Tensorflow 改变了变量名 e
:
d.name #d.name == "two/v:0"
e.name #e.name == "two/v_1:0"
另一个区别在于一个在('variable_store',)
collection 而另一个不在。
请查看来源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>}