Какая разница в области имен и области переменных в тензорном потоке?
Каковы различия между этими функциями?
tf.variable_op_scope(values, name, default_name, initializer=None)
Возвращает менеджер контекста для определения op, который создает переменные. Этот менеджер контекста проверяет, что заданные значения взяты из одного и того же графика, гарантирует, что этот граф является графиком по умолчанию, и нажимает область имени и область переменных.
tf.op_scope(values, name, default_name=None)
Возвращает контекстный менеджер для использования при определении операции Python. Этот менеджер контекста проверяет, что заданные значения взяты из одного и того же графика, гарантирует, что этот граф является графиком по умолчанию, и нажимает область имени.
tf.name_scope(name)
Обертка для Graph.name_scope()
с использованием графика по умолчанию. Подробнее см. Graph.name_scope()
.
tf.variable_scope(name_or_scope, reuse=None, initializer=None)
Возвращает контекст для области переменных. Область переменной позволяет создавать новые переменные и делиться уже созданными, обеспечивая при этом проверки, чтобы не создавать или делиться случайно. Подробнее см. В разделе "Область видимости переменных", здесь мы приводим лишь несколько базовых примеров.
Ответы
Ответ 1
Пусть начнется краткое введение в обмен переменных. Это механизм в TensorFlow
который позволяет использовать переменные, доступные в разных частях кода, без передачи ссылок на переменную вокруг.
Метод tf.get_variable
может использоваться с именем переменной в качестве аргумента либо для создания новой переменной с таким именем, либо для получения той, которая была создана ранее. Это отличается от использования конструктора tf.Variable
который будет создавать новую переменную каждый раз, когда она вызывается (и потенциально добавляет суффикс к имени переменной, если переменная с таким именем уже существует).
Для механизма обмена переменными используется отдельный тип области (область переменных).
В результате мы получаем два разных типа областей:
Обе области действия имеют одинаковый эффект для всех операций, а также для переменных, созданных с использованием tf.Variable
, т. tf.Variable
Область будет добавлена в качестве префикса к имени операции или переменной.
Однако область имен игнорируется tf.get_variable
. Мы видим, что в следующем примере:
with tf.name_scope("my_scope"):
v1 = tf.get_variable("var1", [1], dtype=tf.float32)
v2 = tf.Variable(1, name="var2", dtype=tf.float32)
a = tf.add(v1, v2)
print(v1.name) # var1:0
print(v2.name) # my_scope/var2:0
print(a.name) # my_scope/Add:0
Единственный способ размещения переменной, доступной с помощью tf.get_variable
в области видимости, - использовать область переменных, как в следующем примере:
with tf.variable_scope("my_scope"):
v1 = tf.get_variable("var1", [1], dtype=tf.float32)
v2 = tf.Variable(1, name="var2", dtype=tf.float32)
a = tf.add(v1, v2)
print(v1.name) # my_scope/var1:0
print(v2.name) # my_scope/var2:0
print(a.name) # my_scope/Add:0
Это позволяет легко обменивать переменные в разных частях программы, даже в разных областях имен:
with tf.name_scope("foo"):
with tf.variable_scope("var_scope"):
v = tf.get_variable("var", [1])
with tf.name_scope("bar"):
with tf.variable_scope("var_scope", reuse=True):
v1 = tf.get_variable("var", [1])
assert v1 == v
print(v.name) # var_scope/var:0
print(v1.name) # var_scope/var:0
ОБНОВИТЬ
Начиная с версии r0.11, op_scope
и variable_op_scope
обе устарели и заменены на name_scope
и variable_scope
.
Ответ 2
И variable_op_scope, и op_scope теперь устарели и не должны использоваться вообще.
Что касается двух других, у меня также были проблемы с пониманием разницы между 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()
Здесь я создаю функцию, которая создает некоторые переменные и константы и группирует их по областям (в зависимости от предоставленного мной типа). В этой функции я также печатаю имена всех переменных. После этого я выполняю график, чтобы получить значения результирующих значений и сохранить файлы событий, чтобы исследовать их в TensorBoard. Если вы запустите это, вы получите следующее:
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
Вы увидите похожий шаблон, если откроете TensorBoard (как вы видите, b
находится вне прямоangularьника scope_name
):
![]()
Это дает вам ответ:
Теперь вы видите, что tf.variable_scope()
добавляет префикс к именам всех переменных (независимо от того, как вы их создаете), ops, констант. С другой стороны, tf.name_scope()
игнорирует переменные, созданные с помощью tf.get_variable()
, поскольку предполагает, что вы знаете, какую переменную и в какой области вы хотите использовать.
Хорошая документация по совместному использованию переменных говорит вам, что
tf.variable_scope()
: управляет пространствами имен для имен, переданных в tf.get_variable()
.
Эта же документация содержит более подробную информацию о том, как работает Variable Scope и когда это полезно.
Ответ 3
Пространства имен - это способ организации имен переменных и операторов иерархическим образом (например, "scopeA/scopeB/scopeC/op1")
-
tf.name_scope
создает пространство имен для операторов в графе по умолчанию. -
tf.variable_scope
создает пространство имен для переменных и операторов в графе по умолчанию.
-
tf.op_scope
же, как tf.name_scope
, но для графика, в котором были созданы указанные переменные.
-
tf.variable_op_scope
же, как tf.variable_scope
, но для графика, в котором были созданы указанные переменные.
Ссылки на источники, приведенные выше, помогают устранить эту проблему.
В этом примере показано, что все типы областей определяют пространства имен как для переменных, так и для операторов со следующими отличиями:
- области, определенные
tf.variable_op_scope
или tf.variable_scope
, совместимы с tf.get_variable
(он игнорирует две другие области) -
tf.op_scope
и tf.variable_op_scope
просто выберите граф из списка указанных переменных, чтобы создать область действия. Помимо их поведения, равного tf.name_scope
и tf.variable_scope
соответственно -
tf.variable_scope
и variable_op_scope
добавьте указанный или инициализатор по умолчанию.
Ответ 4
Что касается API r0.11, op_scope
и variable_op_scope
обе устарели. name_scope
и variable_scope
могут быть вложенными:
with tf.name_scope('ns'):
with tf.variable_scope('vs'): #scope creation
v1 = tf.get_variable("v1",[1.0]) #v1.name = 'vs/v1:0'
v2 = tf.Variable([2.0],name = 'v2') #v2.name= 'ns/vs/v2:0'
v3 = v1 + v2 #v3.name = 'ns/vs/add:0'
Ответ 5
Давайте сделаем это просто: просто используйте tf.variable_scope
. Цитирование разработчика TF,:
В настоящее время мы рекомендуем всем использовать variable_scope
и не использовать name_scope
, за исключением внутреннего кода и библиотек.
Помимо того факта, что функциональность variable_scope
в основном расширяет возможности name_scope
, рассмотрим, как они не так хорошо играют вместе:
with tf.name_scope('foo'):
with tf.variable_scope('bar'):
x = tf.get_variable('x', shape=())
x2 = tf.square(x**2, name='x2')
print(x.name)
# bar/x:0
print(x2.name)
# foo/bar/x2:0
Придерживаясь только variable_scope
, вы избегаете некоторых головных болей из-за такого рода несовместимости.
Ответ 6
Вы можете рассматривать их как две группы: variable_op_scope
и op_scope
принимают набор переменных в качестве входных данных и предназначены для создания операций. Разница заключается в том, как они влияют на создание переменных с помощью tf.get_variable
:
def mysum(a,b,name=None):
with tf.op_scope([a,b],name,"mysum") as scope:
v = tf.get_variable("v", 1)
v2 = tf.Variable([0], name="v2")
assert v.name == "v:0", v.name
assert v2.name == "mysum/v2:0", v2.name
return tf.add(a,b)
def mysum2(a,b,name=None):
with tf.variable_op_scope([a,b],name,"mysum2") as scope:
v = tf.get_variable("v", 1)
v2 = tf.Variable([0], name="v2")
assert v.name == "mysum2/v:0", v.name
assert v2.name == "mysum2/v2:0", v2.name
return tf.add(a,b)
with tf.Graph().as_default():
op = mysum(tf.Variable(1), tf.Variable(2))
op2 = mysum2(tf.Variable(1), tf.Variable(2))
assert op.name == 'mysum/Add:0', op.name
assert op2.name == 'mysum2/Add:0', op2.name
обратите внимание на имя переменной v
в двух примерах.
для tf.name_scope
и tf.variable_scope
:
with tf.Graph().as_default():
with tf.name_scope("name_scope") as scope:
v = tf.get_variable("v", [1])
op = tf.add(v, v)
v2 = tf.Variable([0], name="v2")
assert v.name == "v:0", v.name
assert op.name == "name_scope/Add:0", op.name
assert v2.name == "name_scope/v2:0", v2.name
with tf.Graph().as_default():
with tf.variable_scope("name_scope") as scope:
v = tf.get_variable("v", [1])
op = tf.add(v, v)
v2 = tf.Variable([0], name="v2")
assert v.name == "name_scope/v:0", v.name
assert op.name == "name_scope/Add:0", op.name
assert v2.name == "name_scope/v2:0", v2.name
Подробнее о области переменных вы можете узнать в учебнике.
Аналогичный вопрос был перед перед переполнением стека.
Ответ 7
Из последнего раздела этой страницы документации tensorflow: Имена ops в tf.variable_scope()
[...], когда мы делаем with tf.variable_scope("name")
, это неявно открывает a tf.name_scope("name")
. Например:
with tf.variable_scope("foo"):
x = 1.0 + tf.get_variable("v", [1])
assert x.op.name == "foo/add"
Области имен можно открыть в дополнение к области переменных, а затем они будут влиять только на имена операционных систем, но не на переменные.
with tf.variable_scope("foo"):
with tf.name_scope("bar"):
v = tf.get_variable("v", [1])
x = 1.0 + v
assert v.name == "foo/v:0"
assert x.op.name == "foo/bar/add"
При открытии области переменной с использованием захваченного объекта вместо строки мы не изменяем текущую область имен для ops.