【问题标题】: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 的示例,它完全符合您的要求。

标签: python tensorflow


【解决方案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)
# ...

...但是,我不会容忍这种行为 :-)。

【讨论】:

【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2017-02-23
        • 2017-11-01
        • 2016-06-30
        • 1970-01-01
        • 1970-01-01
        • 2019-01-23
        • 1970-01-01
        • 2017-06-16
        • 2019-08-02
        相关资源
        最近更新 更多