tensorflow에서 이름 범위와 변수 범위의 차이점은 무엇입니까?


276

이 기능들의 차이점은 무엇입니까?

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

변수를 작성하는 op를 정의하기위한 컨텍스트 관리자를 리턴합니다. 이 컨텍스트 관리자는 제공된 값이 동일한 그래프에 있는지 확인하고 해당 그래프가 기본 그래프인지 확인하고 이름 범위 및 변수 범위를 푸시합니다.


tf.op_scope(values, name, default_name=None)

Python op를 정의 할 때 사용할 컨텍스트 관리자를 리턴합니다. 이 컨텍스트 관리자는 제공된 값이 동일한 그래프에 있는지 확인하고 해당 그래프가 기본 그래프인지 확인하고 이름 범위를 푸시합니다.


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.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
명확한 설명에 감사드립니다. 당연히, 질문까지 후속이 될 것 " Tensorflow이 혼동을 일으킬 정도로 유사 메커니즘의 양이 있는가? 왜 그냥 하나를 교체 scope효과적으로 수행 방법 variable_scope?"
John

8
나는 왜 variable_scope대의 구별 name_scope이 필요한지 개념적으로 이해하지 못한다고 생각 합니다. 하나는 (어떤 방법으로 변수를 만드는 경우 tf.Variable또는 tf.get_variable), 우리는 항상 우리가 범위 또는 전체 이름을 지정하면 얻을 수있을 것이 나에게 더 자연스러운 것 같다. 하나는 왜 스코프 이름을 무시하고 다른 하나는 무시하지 않습니다. 이 이상한 행동에 대한 합리성을 이해하십니까?
Charlie Parker

23
변수 범위를 사용하면 작업을 정의하는 데 사용되는 현재 이름 범위의 영향을받지 않는 재사용 가능한 변수에 대해 별도의 범위를 정의 할 수 있기 때문입니다.
Andrzej Pronobis

6
안녕하세요, variable_scope의 변수 이름이 항상 : 0으로 끝나는 이유를 설명 할 수 있습니까? 이것은 변수 이름이 : 1, : 2 등으로 끝나는 것을 의미하므로 어떻게 이런 일이 일어날 수 있습니까?
제임스 팬

2
@JamesFan 모든 "선언"은 연산이므로 a = tf.Variable (.. name)이라고 말하면 텐서를 반환하지만 실제로는 연산도 생성합니다. a를 인쇄하면 : 0으로 텐서가 표시됩니다. a.op를 인쇄하면 해당 텐서 값을 계산하는 작업이 수행됩니다.
Robert Lugg

84

variable_op_scopeop_scope 는 모두 더 이상 사용되지 않으며 전혀 사용해서는 안됩니다.

다른 두 가지에 관해서는 간단한 예제를 작성하여 모든 것을 시각화하려고 시도하기 전에 variable_scopename_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, constant가 표시됩니다. 반면에 사용하려는 변수와 범위를 알고 있다고 가정하므로 tf.name_scope()작성된 변수는 무시합니다 tf.get_variable().

변수 공유 에 대한 좋은 문서 는

tf.variable_scope():에 전달 된 이름의 네임 스페이스를 관리합니다 tf.get_variable().

동일한 문서에서 변수 범위의 작동 방식과 유용한시기에 대한 자세한 정보를 제공합니다.


2
예와 시각 자료로 멋진 답변을 해보자.
David Parks

43

네임 스페이스는 변수와 연산자의 이름을 계층 적으로 구성하는 방법입니다 (예 : "scopeA / scopeB / scopeC / op1")

  • tf.name_scope 기본 그래프에서 연산자의 네임 스페이스를 만듭니다.
  • tf.variable_scope 기본 그래프에서 변수와 연산자 모두에 대한 네임 스페이스를 만듭니다.

  • tf.op_scopetf.name_scope지정된 변수가 생성 된 그래프의 경우 와 동일 합니다.

  • tf.variable_op_scopetf.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_scopevariable_op_scope지정된 추가하거나 초기화 기본.

지정된 변수가 작성된 그래프의 경우 tf.variable_op_scope ([a, b], name, "mysum2")를 범위로 사용하여 fabrizioM에 의한 위의 예와 같은 의미입니까? 여기서 매개 변수 a와 b는이 함수의 영향을받지 않으며이 범위에 정의 된 변수는 영향을 받습니까?
Xiuyi Yang

두 가지 질문에 대한 답은 '예'입니다. 지정된 변수가 생성되고 수정되지 않은 그래프입니다.
Alexander Gorban

tf.name_scope 및 tf.variable_scope는 기본 그래프에서만 사용되지만 tf.Graph ()를 사용하여 그래프를 정의하고 구성 할 때 다른 두 함수 tf.op_scope 및 tf.variable_op_scope는 사용할 수 없습니다. 이 그래프!
Xiuyi Yang

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_scopevariable_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_scopeop_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_scopetf.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

학습서 에서 변수 범위에 대한 자세한 내용을 읽을 수 있습니다 . 비슷한 질문을했다 하기 전에 물어 스택 오버플로.


2

tensorflow 문서의이 페이지의 마지막 섹션에서 : ops의 이름tf.variable_scope()

[...] 우리가 할 때 with tf.variable_scope("name")이것은 암묵적으로을 엽니 다 tf.name_scope("name"). 예를 들면 다음과 같습니다.

with tf.variable_scope("foo"):
  x = 1.0 + tf.get_variable("v", [1])
assert x.op.name == "foo/add"

변수 범위와 함께 이름 범위를 열 수 있으며, 변수의 이름에는 영향을 미치지 않지만 op의 이름에만 영향을 미칩니다.

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 PronobisSalvador Dali자세한 내용이 Scope있습니다.

위에서 논의 된 Scope Functions 중 현재 (2020 년 2 월 17 일) 현재 활성화 된 것은 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 로의 마이그레이션에 대한 자세한 내용은이 마이그레이션 안내서 를 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.