В чем разница между variable_scope
и name_scope
? В руководстве по работе с variable_scope
неявно открывает name_scope
. Я также заметил, что создание переменной в name_scope
автоматически расширяет ее имя именем области. Так в чем же разница?
В чем разница между variable_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
.