Область переменной Tensorflow: повторное использование, если существует переменная

Я хочу, чтобы часть кода создавала переменную в пределах области действия, если она не существует, и обращайтесь к переменной, если она уже существует. Мне нужно, чтобы это был тот же код, так как он будет вызываться несколько раз.

Однако Tensorflow мне нужно указать, хочу ли я создавать или повторно использовать переменную, например:

with tf.variable_scope("foo"): #create the first time
    v = tf.get_variable("v", [1])

with tf.variable_scope("foo", reuse=True): #reuse the second time
    v = tf.get_variable("v", [1])

Как я могу получить его, чтобы выяснить, следует ли его автоматически создавать или повторно использовать? Я хочу, чтобы эти два блока кода были одинаковыми и запускали программу.

Ответы

Ответ 1

ValueError вызывается в get_variable() когда создается новая переменная, а форма не объявляется, или при нарушении повторного использования во время создания переменной. Поэтому вы можете попробовать это:

def get_scope_variable(scope_name, var, shape=None):
    with tf.variable_scope(scope_name) as scope:
        try:
            v = tf.get_variable(var, shape)
        except ValueError:
            scope.reuse_variables()
            v = tf.get_variable(var)
    return v

v1 = get_scope_variable('foo', 'v', [1])
v2 = get_scope_variable('foo', 'v')
assert v1 == v2

Обратите внимание, что следующее также работает:

v1 = get_scope_variable('foo', 'v', [1])
v2 = get_scope_variable('foo', 'v', [1])
assert v1 == v2

ОБНОВИТЬ. Новый API теперь поддерживает автоматическое повторное использование:

def get_scope_variable(scope, var, shape=None):
    with tf.variable_scope(scope, reuse=tf.AUTO_REUSE):
        v = tf.get_variable(var, shape)
    return v

Ответ 2

Хотя использование предложения "try... except..." работает, я думаю, что более элегантный и удобный способ будет разделять процесс инициализации переменной с процессом "повторного использования".

def initialize_variable(scope_name, var_name, shape):
    with tf.variable_scope(scope_name) as scope:
        v = tf.get_variable(var_name, shape)
        scope.reuse_variable()

def get_scope_variable(scope_name, var_name):
    with tf.variable_scope(scope_name, reuse=True):
        v = tf.get_variable(var_name)
    return v

Так как часто нам нужно только инициализировать переменные, но повторно использовать/делиться им много раз, разделение этих двух процессов делает код чище. Также таким образом нам не нужно будет каждый раз выполнять предложение "try", чтобы проверить, была ли эта переменная уже создана или нет.

Ответ 3

Новая опция AUTO_REUSE делает свое дело.

Из документации API tf.variable_scope: если reuse=tf.AUTO_REUSE, мы создаем переменные, если они не существуют, и возвращаем их в противном случае.

Базовый пример совместного использования переменной AUTO_REUSE:

def foo():
  with tf.variable_scope("foo", reuse=tf.AUTO_REUSE):
    v = tf.get_variable("v", [1])
  return v

v1 = foo()  # Creates v.
v2 = foo()  # Gets the same, existing v.
assert v1 == v2

Ответ 4

Мы можем написать нашу абстракцию над tf.varaible_scope, чем использует reuse=None для первого вызова и использует reuse=True для последующих вызовов:

def variable_scope(name_or_scope, *args, **kwargs):
  if isinstance(name_or_scope, str):
    scope_name = tf.get_variable_scope().name + '/' + name_or_scope
  elif isinstance(name_or_scope, tf.Variable):
    scope_name = name_or_scope.name

  if scope_name in variable_scope.scopes:
    kwargs['reuse'] = True
  else:
    variable_scope.scopes.add(scope_name)

  return tf.variable_scope(name_or_scope, *args, **kwargs)
variable_scope.scopes = set()

Использование:

with variable_scope("foo"): #create the first time
    v = tf.get_variable("v", [1])

with variable_scope("foo"): #reuse the second time
    v = tf.get_variable("v", [1])