在 TensorFlow 中有什么方法可以只初始化未初始化的变量吗?

In TensorFlow is there any way to just initialize uninitialised variables?

TensorFlow 中初始化变量的标准方式是

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

经过 运行 一段时间的学习后,我创建了一组新的变量,但是一旦我初始化它们,它就会重置我所有现有的变量。目前我的解决方法是保存我需要的所有变量,然后在 tf.initalize_all_variables 调用后重新应用它们。这可行,但有点丑陋和笨重。我在文档中找不到这样的东西...

有谁知道有什么好的方法可以只初始化未初始化的变量吗?

没有优雅*的方式来枚举图中未初始化的变量。但是,如果您有权访问新的变量对象——我们称它们为 v_6v_7v_8——您可以使用 tf.initialize_variables():[=17= 有选择地初始化它们]

init_new_vars_op = tf.initialize_variables([v_6, v_7, v_8])
sess.run(init_new_vars_op)

* 可以使用反复试验的过程来识别未初始化的变量,如下所示:

uninitialized_vars = []
for var in tf.all_variables():
    try:
        sess.run(var)
    except tf.errors.FailedPreconditionError:
        uninitialized_vars.append(var)

init_new_vars_op = tf.initialize_variables(uninitialized_vars)
# ...

...但是,我不会宽恕这种行为:-)。

更新: TensorFlow 0.9 有一个新方法 "fixes" 所有这些 但前提是你使用 VariableScope with reuse set to True. tf.report_uninitialized_variables可以与 sess.run( tf.initialize_variables( list( tf.get_variable(name) for name in sess.run( tf.report_uninitialized_variables( tf.all_variables( ) ) ) ) ) )

在一行中使用

或更智能地指定您希望初始化的变量:

def guarantee_initialized_variables(session, list_of_variables = None):
    if list_of_variables is None:
        list_of_variables = tf.all_variables()
    uninitialized_variables = list(tf.get_variable(name) for name in
                                   session.run(tf.report_uninitialized_variables(list_of_variables)))
    session.run(tf.initialize_variables(uninitialized_variables))
    return unintialized_variables

这仍然比实际知道哪些变量被初始化和未被初始化并正确处理这些变量更不理想,但是在像 optim 类 这样的误导情况下(见下文)它可能很难避免。

另请注意,tf.initialize_variables 无法计算 tf.report_uninitialized_variables,因此它们都必须在会话上下文中 运行 才能工作。


有一种不优雅但简洁的方法可以做到这一点。在引入新变量之前 运行 temp = set(tf.all_variables()) 和之后 运行 sess.run(tf.initialize_variables(set(tf.all_variables()) - temp))。这些一起只会初始化在分配临时值后创建的任何变量。

我一直在玩迁移学习,所以我也想要一种快速的方法,但这是我能找到的最好方法。特别是在使用 AdamOptimizer 之类的东西时,它不会让您轻松(或任何,我不确定)访问它使用的变量。所以下面实际上出现在我的代码中。 (我明确地初始化了新层的变量,并且 运行 它一次以显示迁移学习之前的初始错误。只是为了完整性检查。)

temp = set(tf.all_variables())
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#I honestly don't know how else to initialize ADAM in TensorFlow.
sess.run(tf.initialize_variables(set(tf.all_variables()) - temp))

它解决了我所有的问题。

编辑: states the proper way to fix my problem. Theoretically, you should use tf.train.Optimizer.get_slot_names and tf.train.Optimizer.get_slot

optim = tf.train.AdadeltaOptimizer(1e-4)
loss = cross_entropy(y,yhat)
train_step = optim.minimize(loss)
sess.run(tf.initialize_variables([optim.get_slot(loss, name)
                                  for name in optim.get_slot_names()])

然而,这给了我 AttributeError: 'NoneType' object has no attribute 'initializer'。当我弄清楚我做错了什么时,我会进行编辑,所以你不要犯我的错误。

对于@Poik 提到的案例,当优化器创建变量以致无法直接访问它们时,更简洁的解决方案是使用tf.train.Optimizer.get_slot

一些优化器子类,例如 MomentumOptimizerAdagradOptimizer 分配和管理与要训练的变量关联的附加变量。这些被称为插槽。您可以使用 tf.train.Optimizer.get_slot_names() 获取优化器具有的所有插槽名称,然后使用 tf.train.Optimizer.get_slot 获取为这些插槽分配的变量。

我想出了一个适用于 TensorFlow r0.11 的方法:

def get_uninitialized_variables(variables=None):
    """Get uninitialized variables as a list.

    Parameters
    ----------
    variables : collections.Iterable[tf.Variable]
        Return only uninitialized variables within this collection.
        If not specified, will return all uninitialized variables.

    Returns
    -------
    list[tf.Variable]
    """
    sess = tf.get_default_session()
    if variables is None:
        variables = tf.all_variables()
    else:
        variables = list(variables)
    init_flag = sess.run(
        tf.pack([tf.is_variable_initialized(v) for v in variables]))
    return [v for v, f in zip(variables, init_flag) if not f]

我认为最简单的方法是先创建所有训练运算符,然后再初始化变量。

比如我用Adam Optimizer解决了layer-wise pretraining的问题,方法如下:

 # create an optimizer
 pretrain_optimizer =  tf.train.AdamOptimizer(learning_rate=learning_rate)

 # Make an array of the trainers for all the layers
 trainers=[pretrain_optimizer.minimize(loss_reconstruction(ae.run_less_layers(ae._input_, i+1), ae.run_less_layers(ae._input_, i+1, is_target=True)), global_step=tf.contrib.framework.get_or_create_global_step(), name='Layer_wise_optimizer_'+str(i)) for i in xrange(len(ae_shape) - 2)]

 # Initialize all the variables
 sess.run(tf.global_variables_initializer())

TF does not have a function that does exactly what you want,不过你可以随便写一个:

import tensorflow as tf

def initialize_uninitialized(sess):
    global_vars          = tf.global_variables()
    is_initialized   = sess.run([tf.is_variable_initialized(var) for var in global_vars])
    not_initialized_vars = [v for (v, f) in zip(global_vars, is_initialized) if not f]
    
    print [str(i.name) for i in not_initialized_vars] # only for testing
    if len(not_initialized_vars):
        sess.run(tf.variables_initializer(not_initialized_vars))

这里我提取全部global variables, iterate all of them and check whether they are already initialized. After this I get a list of uninitialized variables which I initialize。我还打印了我将要初始化以用于调试目的的变量。


您可以轻松验证它是否按预期工作:

a = tf.Variable(3, name='my_var_a')
b = tf.Variable(4, name='my_var_b')

sess = tf.Session()
initialize_uninitialized(sess)
initialize_uninitialized(sess)

c = tf.Variable(5, name='my_var_a') # the same name, will be resolved to different name
d = tf.Variable(6, name='my_var_d')
initialize_uninitialized(sess)

print '\n\n', sess.run([a, b, c, d])

这将在初始化之前打印所有未初始化的变量,最后一个 sess.run 将确保说服您所有变量都已初始化。


您也可以使用tf.report_uninitialized_variables() to write a similar function. A sketch of it is

顺便说一句,如果你只想初始化一个尚未使用 tf.global_variables_initializer() 初始化的张量(例如 tf.Variable),那么你可以在 sess.run() 如下例所示:

In [196]: weights = tf.Variable(tf.zeros(shape=(3, 4)), name='weights')

In [197]: with tf.Session() as sess:
     ...:     sess.run(weights.initializer)
     ...:     print(weights.eval())
     ...:     

# the result
[[ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]]