Python 来自检查点的tf.train.init_不会初始化使用tf.Variable创建的变量
似乎Python 来自检查点的tf.train.init_不会初始化使用tf.Variable创建的变量,python,tensorflow,Python,Tensorflow,似乎tf.train.init\u from\u checkpoint初始化通过tf.get\u variable创建的变量,而不是通过tf.variable创建的变量 例如,让我们创建两个变量并保存它们: import tensorflow as tf tf.Variable(1.0, name='foo') tf.get_variable('bar',initializer=1.0) saver = tf.train.Saver() with tf.Session() as sess:
tf.train.init\u from\u checkpoint
初始化通过tf.get\u variable
创建的变量,而不是通过tf.variable
创建的变量
例如,让我们创建两个变量并保存它们:
import tensorflow as tf
tf.Variable(1.0, name='foo')
tf.get_variable('bar',initializer=1.0)
saver = tf.train.Saver()
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.save(sess, './model', global_step=0)
如果我通过tf.train.Saver
再次加载它们,一切正常:变量被加载回1,即使它们在这里初始化为零:
import tensorflow as tf
foo = tf.Variable(0.0, name='foo')
bar = tf.get_variable('bar', initializer=0.0)
saver = tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess, './model-0')
print(f'foo: {foo.eval()} bar: {bar.eval()}')
# foo: 1.0 bar: 1.0
但是,如果我使用tf.train.init\u from\u checkpoint
我会得到
import tensorflow as tf
foo = tf.Variable(0.0, name='foo')
bar = tf.get_variable('bar', initializer=0.0)
tf.train.init_from_checkpoint('./model-0', {'/':'/'})
with tf.Session() as sess:
tf.global_variables_initializer().run()
print(f'foo: {foo.eval()} bar: {bar.eval()}')
# foo: 0.0 bar: 1.0
bar
按预期设置为1,但foo
保持为0
这是故意的行为吗?如果是,原因是什么?是的,这是有意的。此行为在
\u init\u from\u checkpoint
方法中描述,该方法在加载要还原的变量时迭代赋值映射
for tensor_name_in_ckpt, current_var_or_name in sorted(
six.iteritems(assignment_map)):
var = None
它首先将要恢复的变量设置为None
,如果满足其中一个条件,它将重置为当前变量名。在这种特殊情况下,循环包含语句
如果“/”在当前变量或名称中
因此,它将从先前创建的字典store\u vars
中加载变量。它是在检查点检查当前赋值映射中的变量是否为tf.variable之后创建的,此时为False
if _is_variable(current_var_or_name) or (
isinstance(current_var_or_name, list)
and all(_is_variable(v) for v in current_var_or_name)):
var = current_var_or_name
else:
store_vars = vs._get_default_variable_store()._vars
store\u vars
是由内部类\u VariableStore
创建的,更准确地说,是由它的\u get\u default\u variable\u store()方法创建的。此类使用get\u variable
作为变量构造函数。因为tf.Variable
没有默认范围,而tf.get\u Variable
首先调用tf.get\u Variable\u scope(),后者返回当前变量范围“foo”不在此范围内。此外,tf.Variable
将在每次调用时创建一个新变量,不允许共享
store\u vars
是从默认范围成员构造的,因此,它只包含“bar”变量,foo
稍后通过tf.variable
op添加到变量集合中
但是,如果assignment\u map
将包含{'foo':foo,'bar':bar}
,则上述的\u init\u from\u checkpoint
将找到这些变量并加载它们。因此,在这种情况下,您的代码将输出foo:1.0 bar:1.0
您可以在中找到代码
及
也可以看到这个答案是的,它不允许共享——为什么这意味着它无法恢复?毕竟,tf.Variable
确实被tf.train.Saver.restore
还原,正如我在第二个示例中所示。因为tf.train.init\u from\u checkpoint
将tf.Variable替换为tf.get\u Variable
初始值设定项,以便可以从检查点文件加载它们。根据So,为什么在tf.Variable
的情况下不更换初始值设定项?因为tf.train.init\u from\u checkpoint
忽略tf.Variable
。我将更新答案并稍加澄清。由于似乎没有人回答,我将尝试修复我以前的尝试。它大多是肤浅的,不中肯的。希望它有意义now@Sharky您的答案指向了发生这种情况的代码——事实上它必须发生在某个地方——但它没有回答我关于这个选择的基本原理的问题。据我所知,这可能是一个错误,而你的答案并没有说明这一点。我再次更新,很抱歉我很难表达我的观点