В TensorFlow есть ли способ просто инициализировать неинициализированные переменные?
Стандартный способ инициализации переменных в TensorFlow -
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
После некоторого обучения некоторое время я создаю новый набор переменных, но как только я их инициализирую, он сбрасывает все мои существующие переменные. В настоящий момент мой путь к этому заключается в том, чтобы сохранить всю переменную, которая мне нужна, а затем повторно применить ее после вызова tf.initalize_all_variables. Это работает, но немного уродливо и неуклюже. Я не могу найти ничего подобного в документах...
Кто-нибудь знает какой-либо хороший способ просто инициализировать неинициализированные переменные?
Ответы
Ответ 1
Нет никакого изящного * способа перечисления неинициализированных переменных в графе. Однако, если у вас есть доступ к новым объектам переменной mdash, позвоните им 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)
# ...
... однако я бы не потворствовал такому поведению: -).
Ответ 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 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'
. Я сделаю изменения, когда выясню, что я сделал не так, поэтому вы не совершаете ошибок.
Ответ 3
TF не имеет функции, которая делает именно то, что вы хотите, но вы можете легко написать ее:
import tensorflow as tf
def initialize_uninitialized(sess):
global_vars = tf.global_variables()
is_not_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_not_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))
Здесь я извлекаю все глобальные переменные, повторяю их все и проверяю, являются ли они уже инициализированы. После этого я получаю список неинициализированных переменных, которые я 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()
для записи аналогичной функции. Эскиз этого здесь.
Ответ 4
Для случая, упомянутого в @Poik, когда переменные создаются оптимизаторами, так что к ним нельзя получить доступ напрямую, более чистым решением является использование tf.train.Optimizer.get_slot
.
Некоторые подклассы оптимизатора, такие как MomentumOptimizer
и AdagradOptimizer
выделяют и управляют дополнительными переменными, связанными с переменными для обучения. Они называются слотами. Вы можете использовать tf.train.Optimizer.get_slot_names()
, чтобы получить все имена слотов, которые есть у оптимизатора, и затем использовать tf.train.Optimizer.get_slot
для получения переменной, выделенной для этих слотов.
Ответ 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
Я думаю, что самый простой способ - сначала создать все тренировочные операторы и инициализировать переменные.
Например, я решил проблему многоуровневой предварительной обработки с помощью 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())
Ответ 7
Btw, если вы хотите инициализировать только один тензор (например, tf.Variable
), который не был инициализирован с помощью tf.global_variables_initializer()
, вы можете использовать your_tensor.initializer
в 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.]]