2017-01-08 2 views
11

Я хочу использовать MomentumOptimizer в Tensorflow. Однако, поскольку этот оптимизатор использует некоторую внутреннюю переменную, пытаясь использовать его без инициализации этой переменной дает ошибку:Как инициализировать только переменные Optimizer в Tensorflow?

FailedPreconditionError (see above for traceback): Attempting to use uninitialized value Variable_2/Momentum

Это может быть легко решена путем инициализации всех переменных, например:

tf.global_variables_initializer().run()

Тем не менее, я не хочу инициализировать все переменные - только те из Оптимизатора. Есть какой-либо способ сделать это?

ответ

9

Вы можете фильтровать переменные по имени и только инициализировать их. IE

momentum_initializers = [var.initializer for var in tf.global_variables() if 'Momentum' in var.name] 
sess.run(momentum_initializers) 
2

tf.variables_initializer кажется предпочтительным способом инициализировать определенный набор переменных:

var_list = [var for var in tf.global_variables() if 'Momentum' in var.name] 
var_list_init = tf.variables_initializer(var_list) 
... 
sess = tf.Session() 
sess.run(var_list_init) 
+0

Он должен быть: var_list = [вар для вара в tf.global_variables(), если 'Momentum' в var.name] –

+1

@ MichaelPresečan фиксированный, спасибо! –

10

Оба текущие ответы вроде работают путем фильтрации имя переменной, используя строку «Momentum». Но это очень хрупкое с двух сторон:

  1. Он может молча (повторно) инициализировать некоторые другие переменные, которые вы на самом деле не хотите сбросить! Либо просто из-за конфликта имен, либо потому, что у вас есть более сложный граф и, например, оптимизируйте разные части отдельно.
  2. Он будет работать только для одного конкретного оптимизатора и как вы узнаете имена, которые нужно искать для других?
  3. Бонус: обновление до тензорного потока может бесшумно сломайте свой код.

К счастью, абстрактный Optimizer класса tensorflow имеет механизм для этого, эти дополнительных переменных оптимизатора называются "slots", и вы можете получить все имена слотов оптимизатора, используя get_slot_names() метод:

opt = tf.train.MomentumOptimizer(...) 
print(opt.get_slot_names()) 
# prints ['momentum'] 

И вы может получить переменную, соответствующую прорезь для конкретного (обучаемый) переменной v с использованием метода get_slot(var, slot_name):

opt.get_slot(some_var, 'momentum') 

Собирает все это вместе, вы можете создать цит, который инициализирует состояние оптимизатора следующим образом:

var_list = # list of vars to optimize, e.g. 
      # tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES) 
opt = tf.train.MomentumOptimizer(0.1, 0.95) 
step_op = opt.minimize(loss, var_list=var_list) 
reset_opt_op = tf.variables_initializer([opt.get_slot(var, name) for name in opt.get_slot_names() for var in var_list]) 

Это будет действительно только сбросить правильные переменное и быть устойчивыми по оптимизаторам.

За исключением одного unfortunate caveat: AdamOptimizer. Это также поддерживает счетчик того, как часто он называется. Это означает, что вы должны действительно серьезно думать о том, что вы здесь делаете, но для полноты вы можете получить дополнительные состояния как opt._get_beta_accumulators(). Возвращенный список должен быть добавлен в список в приведенной выше строке reset_opt_op.

2

здания от ответа LucasB в о AdamOptimizer, этой функции принимает AdamOptimizer экземпляра adam_opt, который имеет свои Variables создал (один из этих двух называются: adam_opt.minimize(loss, var_list=var_list) или adam_opt.apply_gradients(zip(grads, var_list)) Функция создает Op, что при вызове, повторно инициализирует оптимизатор. переменные для пройденных переменного, а также глобального состояния счета

def adam_variables_initializer(adam_opt, var_list): 
    adam_vars = [adam_opt.get_slot(var, name) 
       for name in adam_opt.get_slot_names() 
       for var in var_list if var is not None] 
    adam_vars.extend(list(adam_opt._get_beta_accumulators())) 
    return tf.variables_initializer(adam_vars) 

например.

opt = tf.train.AdamOptimizer(learning_rate=1e-4) 
fit_op = opt.minimize(loss, var_list=var_list) 
reset_opt_vars = adam_variables_initializer(opt, var_list) 
+1

В моем случае список adam_vars может содержать переменные типа None, не уверен, есть ли элегантный способ его решить ... в настоящее время я просто фильтрую их все –

+0

@TamakiSakura hm какие? Я обновил ответ с помощью фильтра в понимании списка – eqzx

+0

'' '[adam_opt.get_slot (var, name) для имени в adam_opt.get_slot_names() для var в var_list]' '' part, я уверен, что мой var_list не содержит Никто. То, что я сейчас делаю, очень уродливо: '' 'adam_vars = filter (lambda x: x не None, adam_vars)' '' перед вызовом '' 'tf.variables_initalizer''' –

0

Чтобы устранить проблему None просто сделать:

self.opt_vars = [opt.get_slot(var, name) for name in opt.get_slot_names() 
        for var in self.vars_to_train 
        if opt.get_slot(var, name) is not None] 
Смежные вопросы