В чем разница между variable_scope и name_scope?

В чем разница между variable_scope и name_scope? В руководстве по работе с variable_scope неявно открывает name_scope. Я также заметил, что создание переменной в name_scope автоматически расширяет ее имя именем области. Так в чем же разница?

Ответ 1

У меня возникли проблемы с пониманием разницы между variable_scope и name_scope (они выглядели почти одинаково), прежде чем я попытался визуализировать все, создав простой пример:

import tensorflow as tf
def scoping(fn, scope1, scope2, vals):
    with fn(scope1):
        a = tf.Variable(vals[0], name='a')
        b = tf.get_variable('b', initializer=vals[1])
        c = tf.constant(vals[2], name='c')
        with fn(scope2):
            d = tf.add(a * b, c, name='res')

        print '\n  '.join([scope1, a.name, b.name, c.name, d.name]), '\n'
    return d

d1 = scoping(tf.variable_scope, 'scope_vars', 'res', [1, 2, 3])
d2 = scoping(tf.name_scope,     'scope_name', 'res', [1, 2, 3])

with tf.Session() as sess:
    writer = tf.summary.FileWriter('logs', sess.graph)
    sess.run(tf.global_variables_initializer())
    print sess.run([d1, d2])
    writer.close()

Здесь я создаю функцию, которая создает некоторые переменные и константы и группирует их в области (в зависимости от типа I). В этой функции я также печатаю имена всех переменных. После этого я выполняю график, чтобы получить значения полученных значений и сохранить файлы событий, чтобы исследовать их в тензограмме. Если вы запустите это, вы получите следующее:

scope_vars
  scope_vars/a:0
  scope_vars/b:0
  scope_vars/c:0
  scope_vars/res/res:0 

scope_name
  scope_name/a:0
  b:0
  scope_name/c:0
  scope_name/res/res:0 

Вы видите аналогичную схему, если вы открываете TB (как видите, b находится вне прямоугольника scope_name): введите описание изображения здесь


Это дает вам ответ:

Теперь вы видите, что tf.variable_scope() добавляет префикс к именам всех переменных (независимо от того, как вы их создаете), ops, константы. С другой стороны, tf.name_scope() игнорирует переменные, созданные с помощью tf.get_variable(), потому что предполагается, что вы знаете, какую переменную и в какой области вы хотели использовать.

Хорошая документация по Обмен переменными сообщает вам, что

tf.variable_scope(): управляет пространствами имен для имен, переданных в tf.get_variable().

В той же документации содержится более подробная информация о том, как работает переменная Scope и когда она полезна.

Ответ 2

Когда вы создаете переменную с tf.get_variable вместо tf.Variable, Tensorflow начнет проверять имена варов, созданных с помощью того же метода, чтобы увидеть, столкнулись ли они. Если они это сделают, будет сделано исключение. Если вы создали var с tf.get_variable, и вы пытаетесь изменить префикс имен переменных с помощью диспетчера контекстов tf.name_scope, это не помешает Tensorflow для создания исключения. Только контекстный менеджер tf.variable_scope будет эффективно изменять имя вашего var в этом случае. Или если вы хотите повторно использовать переменную, вы должны вызвать scope.reuse_variables() перед созданием var во второй раз.

В заключение, tf.name_scope просто добавьте префикс ко всем тензорам, созданным в этой области (кроме варов, созданных с помощью tf.get_variable), и tf.variable_scope добавьте префикс к переменным, созданным с помощью tf.get_variable.

Ответ 3

tf.variable_scope представляет собой эволюцию tf.name_scope для обработки повторного использования Variable. Как вы заметили, он делает больше, чем tf.name_scope, поэтому нет реальной причины использовать tf.name_scope: неудивительно, что разработчик TF советует просто использовать tf.variable_scope.

Мое понимание того, что tf.name_scope все еще лежит, заключается в том, что в поведении этих двух tf.variable_scope есть тонкая несовместимость, что делает tf.variable_scope недействительной заменой tf.name_scope.