在 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))
。这将使您的示例与我的示例相同,只是您丢弃了所有 None
s。之后你能运行train_step
吗?当我运行它时,所有插槽都是None
,所以优化器仍未初始化,神经网络无法运行。
这是一个 simple function 的示例,它完全符合您的要求。
【参考方案1】:
没有优雅的*方法来枚举图中未初始化的变量。但是,如果您有权访问新的变量对象(我们称它们为 v_6
、v_7
和 v_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
。
一些优化器子类,例如MomentumOptimizer
和AdagradOptimizer
分配和管理与要训练的变量关联的其他变量。这些被称为插槽。您可以使用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() 有啥区别?
在 golang 中有 nil slice 和 empty slice 有啥意义?
在 TensorFlow 中,tf.identity 有啥用?
在 UIKit 中我们可以设置 label.numberOfLines = 0 当我们不知道文本将占用多少行时?在 SwiftUI 中有啥替代方法? [复制]