Яка різниця області імен і змінної області в tensorflow?


276

Які відмінності між цими функціями?

tf.variable_op_scope(values, name, default_name, initializer=None)

Повертає диспетчер контексту для визначення оп, який створює змінні. Цей менеджер контексту підтверджує, що задані значення є з одного графа, гарантує, що цей графік є графіком за замовчуванням, і висуває область імен та змінну область.


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)

Повертає контекст для змінної області. Змінна область дозволяє створювати нові змінні та обмінюватися вже створеними, надаючи чеки, щоб не створити або поділитись випадково. Докладніше див. Змінна сфера застосування Як, тут ми представляємо лише кілька основних прикладів.


Відповіді:


377

Почнемо з короткого вступу до спільного використання змінних. Це механізм, TensorFlowякий дозволяє обмінюватися змінними, доступ до яких здійснюється в різних частинах коду, без передачі посилань на змінну навколо.

Метод tf.get_variableможе використовуватися з іменем змінної як аргументом для створення нової змінної з таким ім'ям або для вилучення тієї, що була створена раніше. Це відрізняється від використання tf.Variableконструктора, який буде створювати нову змінну щоразу, коли вона викликається (і потенційно додавати суфікс до імені змінної, якщо змінна з таким ім'ям вже існує).

Саме з метою механізму розподілу змінних було введено окремий тип сфери (змінної області).

Як результат, ми маємо два різних типи приладів:

  • область ім'я , створена за допомогоюtf.name_scope
  • змінна область , створена за допомогоюtf.variable_scope

Обидва діапазони мають однаковий вплив на всі операції, а також на змінні, створені за допомогою 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.


41
Дякую за чітке пояснення. Звичайно, подальшим питанням було б " Чому у " Тенсдорфлоу "є обидва ці заплутано схожі механізми? Чому б не замінити їх лише одним scopeметодом, який ефективно працює variable_scope?"
Джон

8
Я не думаю, що я концептуально розумію, чому розмежування variable_scopeпроти vs name_scopeнавіть потрібне. Якщо хтось створює змінну (будь-яким способом з tf.Variableабо tf.get_variable), мені здається більш природним, що ми завжди маємо змогу її отримати, якщо вказати область чи повне ім'я. Я не розумію, чому один ігнорує річ з ім'ям області, а інший - ні. Ви розумієте раціональне для цієї дивної поведінки?
Чарлі Паркер

23
Причина полягає в тому, що за допомогою змінної області застосування можна визначити окремі області застосування змінних, що повторно використовуються, на які не впливає поточна область імен, яка використовується для визначення операцій.
Анджей Пронобіс

6
Привіт, чи можете ви пояснити, чому ім'я змінної у змінному_скопі завжди закінчується знаком: 0? Чи означає це, що можуть бути імена змінних, що закінчуються на: 1,: 2 тощо, тож як це може статися?
Джеймс Фан

2
@JamesFan Кожна «декларація» - це операція, тому, коли ви говорите a = tf.Variable (.. ім'я), ви отримуєте назад тензор, але він фактично також створює операцію. якщо ви надрукуєте a, ви отримаєте тензор з цифрою: 0. Якщо ви друкуєте a.op, ви отримаєте операцію, яка обчислить це тензорне значення.
Роберт Лугг

84

І перемінний_оп_скоп, і оп_скоп тепер застаріли і не повинні використовуватися взагалі.

Щодо інших двох, у мене також виникли проблеми з розумінням різниці між мінливим_скопом і 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, поза межамиscope_name прямокутним):


Це дає вам відповідь :

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

Гарна документація щодо змінних змінних говорить вам про це

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

Ця ж документація містить більш детальну інформацію про те, як працює змінна область застосування та коли вона є корисною.


2
Чудова відповідь на прикладі та візуалах, давайте давайте цю відповідь людям!
Девід Паркс

43

Простори імен - це спосіб упорядкування імен змінних та операторів ієрархічним способом (наприклад, "rangeA / obsegB / областьC / op1")

  • tf.name_scope створює простір імен для операторів у графіку за замовчуванням.
  • tf.variable_scope створює простір імен як для змінних, так і для операторів у графі за замовчуванням.

  • tf.op_scopeте ж саме tf.name_scope, але для графа, в якому були створені вказані змінні.

  • tf.variable_op_scopeте ж саме tf.variable_scope, але для графа, в якому були створені вказані змінні.

Посилання на джерела вище допомагають розкрити цю проблему з документацією.

Цей приклад показує, що всі типи областей визначають простори імен як для змінних, так і для операторів з наступними відмінностями:

  1. сфери, визначені tf.variable_op_scopeабоtf.variable_scope сумісні зtf.get_variable (він ігнорує два інші сфери)
  2. tf.op_scopeі tf.variable_op_scopeпросто виберіть графік зі списку вказаних змінних, щоб створити область для. За винятком їх поведінки, рівних tf.name_scopeтаtf.variable_scope відповідно
  3. tf.variable_scopeі variable_op_scopeдодайте вказаний або ініціалізатор за замовчуванням.

Для графіка, в якому були створені вказані змінні? Чи означає це, як наведений вище приклад fabrizioM, з tf.variable_op_scope ([a, b], ім'я, "mysum2") як область, тут параметри a і b не впливають на цю функцію, і змінні, визначені в цій області, впливають?
Xiuyi Ян

Відповідь на обидва запитання - так: графік, в якому були створені вказані змінні, і вони не модифікуються.
Олександр Горбань

Чи означає це, що tf.name_scope та tf.variable_scope використовуються лише у графіку за замовчуванням, але коли ви, очевидно, визначаєте та конституюєте графік за допомогою tf.Graph (), інші дві функції tf.op_scope та tf.variable_op_scope не можна використовувати в цей графік!
Xiuyi Ян

12

Зробимо це просто: просто використовуйте 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лише ви уникаєте головних болів через такого роду несумісності.


9

Що стосується 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'

8

Ви можете розглядати їх як дві групи: 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

Детальніше про змінні області ви можете прочитати в підручнику . Аналогічне запитання було задано раніше в Stack Overflow.


2

З останнього розділу цієї сторінки документації по tensorflow: Імена операцій в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.


2

Відповідь Tensorflow 2.0 : Пояснення Andrzej Pronobisта Salvador Daliдуже детальна інформація про функції, пов'язані з цим Scope.

З функцій Scope , описаних вище, які є активними , як зараз (17 лютого 2020) є variable_scopeіname_scope .

Вказуючи сумісні дзвінки 2.0 для цих функцій, про які ми говорили вище, на користь громади.

Функція в 1.x :

tf.variable_scope

tf.name_scope

Відповідна функція в 2.x :

tf.compat.v1.variable_scope

tf.name_scope( tf.compat.v2.name_scopeякщо мігрували з 1.x to 2.x)

Для отримання додаткової інформації про міграцію від 1.x до 2.x, перегляньте це Посібник з міграції .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.