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

Posted

技术标签:

【中文标题】在 TensorFlow 中有啥方法可以初始化未初始化的变量吗?【英文标题】:In TensorFlow is there any way to just initialize uninitialised variables?在 TensorFlow 中有什么方法可以初始化未初始化的变量吗? 【发布时间】:2016-05-11 21:51:46 【问题描述】:

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

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

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

有谁知道初始化未初始化变量的好方法吗?

【问题讨论】:

tf.train.Optimizer.minimize(loss) 函数是 defined to be in the documentation optim.apply_gradients(optim.compute_gradients(loss))。这将使您的示例与我的示例相同,只是您丢弃了所有 Nones。之后你能运行train_step 吗?当我运行它时,所有插槽都是None,所以优化器仍未初始化,神经网络无法运行。 这是一个 simple function 的示例,它完全符合您的要求。 【参考方案1】:

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

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 具有可能有用的函数 tf.report_uninitialized_variables()。 tf.initialize_variables 已被弃用。使用等效的tensorflow.org/api_docs/python/tf/variables_initializer【参考方案2】:

更新:TensorFlow 0.9 有一种新方法可以“修复”所有这些问题但前提是您使用 VariableScope 并将 reuse 设置为 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))

它解决了我所有的问题。

编辑: @Lifu_Huang's answer 说明了解决我的问题的正确方法。理论上,你应该使用tf.train.Optimizer.get_slot_names和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'。当我发现我做错了什么时,我会进行修改,所以你不要犯我的错误。

【讨论】:

我转载了AttributeError: 'NoneType' object has no attribute 'initializer'问题。 请注意,尽管有插槽,但优化器可能会创建其他变量。 AdamOptimizer 对我来说还创建了不对应于可训练变量的变量 [<tf.Variable 'optimize/beta1_power:0' shape=() dtype=float32_ref>, <tf.Variable 'optimize/beta2_power:0' shape=() dtype=float32_ref>],因此您不会将它们作为插槽。【参考方案3】:

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,迭代所有它们并检查它们是否are already initialized。在此之后,我得到了一个未初始化的变量列表,我 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()写一个类似的函数。它的草图是here。

【讨论】:

很好的答案。你得到了我的选票。使用tf.report_uninitialized_variables() 会更好吗? @PaulO 在我看来这两种方法是相似的,我不能说它们中的任何一种更好。 那么第一个链接坏了。【参考方案4】:

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

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

【讨论】:

这个答案实际上还不能使用,因为tf.train.Optimizer.get_slot 为槽返回None,直到优化器创建所需的变量,这将在第一次运行minimize 时发生。解决此问题需要调用未记录的函数 tf.train.Optimizer._zeros_slot() 或其他函数,如果您想要记录的支持并能够使用 TensorFlow 的未来更新,则不应这样做。 请注意,尽管有插槽,但优化器可能会创建其他变量。 AdamOptimizer 对我来说还创建了与可训练变量不对应的变量 [<tf.Variable 'optimize/beta1_power:0' shape=() dtype=float32_ref>, <tf.Variable 'optimize/beta2_power:0' shape=() dtype=float32_ref>],因此您不会将它们作为插槽。【参考方案5】:

我想出了一个适用于 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]

【讨论】:

【参考方案6】:

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

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.]]

【讨论】:

【参考方案7】:

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

例如,我用 Adam Optimizer 解决了分层预训练的问题,方法如下:

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

【讨论】:

以上是关于在 TensorFlow 中有啥方法可以初始化未初始化的变量吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 TensorFlow 中,Session.run() 和 Tensor.eval() 有啥区别?

php中有啥方法可以选择包含相同单词的所有类

在 golang 中有 nil slice 和 empty slice 有啥意义?

在 TensorFlow 中,tf.identity 有啥用?

在 UIKit 中我们可以设置 label.numberOfLines = 0 当我们不知道文本将占用多少行时?在 SwiftUI 中有啥替代方法? [复制]

当我的 iOS 开发者帐户中有超过 100 台设备时,有啥方法可以添加更多 UDID?