Как инициализировать только переменные Optimizer в Tensorflow?

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

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

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

tf.global_variables_initializer().run()

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

Ответ 1

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

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

Ответ 2

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

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

К счастью, у абстрактного Optimizer класса tensorflow есть механизм для этого, эти дополнительные переменные оптимизатора называются "слоты" , и вы можете получить все имена слотов оптимизатора, используя метод 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])

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

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

Ответ 3

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)

Ответ 4

Построение ответа 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)

Ответ 5

Чтобы устранить проблему "Нет", просто выполните:

  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]