Tensorflow'da isim kapsamının ve değişken kapsamın farkı nedir?


276

Bu işlevler arasındaki farklar nelerdir?

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

Değişkenler oluşturan bir op tanımlamak için bir bağlam yöneticisi döndürür. Bu bağlam yöneticisi, verilen değerlerin aynı grafikten olduğunu doğrular, grafiğin varsayılan grafik olmasını sağlar ve bir ad kapsamı ve bir değişken kapsamı zorlar.


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

Bir Python op tanımlarken kullanılacak bağlam yöneticisini döndürür. Bu bağlam yöneticisi, verilen değerlerin aynı grafikten olduğunu doğrular, grafiğin varsayılan grafik olmasını sağlar ve bir ad kapsamı zorlar.


tf.name_scope(name)

İçin sarıcı Graph.name_scope()varsayılan grafiğini kullanarak. Daha Graph.name_scope()fazla ayrıntı için bakınız.


tf.variable_scope(name_or_scope, reuse=None, initializer=None)

Değişken kapsamı için bir bağlam döndürür. Değişken kapsamı, yeni değişkenler oluşturmaya ve önceden oluşturulmuş olanları paylaşmaya izin verirken, yanlışlıkla oluşturmama veya paylaşmamaya izin verir. Ayrıntılar için Değişken Kapsamı Nasıl Yapılır'a bakın, burada sadece birkaç temel örnek sunuyoruz.


Yanıtlar:


377

Değişken paylaşımına kısa bir girişle başlayalım. TensorFlowKodun farklı kısımlarına erişilen değişkenlerin çevresindeki değişkene referanslar vermeden paylaşılmasına olanak tanıyan bir mekanizmadır .

Yöntem tf.get_variable, bu ada sahip yeni bir değişken oluşturmak veya daha önce oluşturulmuş olanı almak için değişken adı olarak bağımsız değişken olarak kullanılabilir. Bu, tf.Variableher çağrıldığında yeni bir değişken oluşturacak olan yapıcıyı kullanmaktan farklıdır (ve böyle bir ada sahip bir değişken zaten varsa değişken adına bir sonek ekleyebilir).

Değişken paylaşım mekanizmasının amacı için ayrı bir kapsam tipi (değişken kapsam) getirilmiştir.

Sonuç olarak, iki farklı kapsam türüne sahibiz:

Her iki kapsam da tüm işlemler üzerinde ve etki kullanılarak oluşturulan değişkenlerde aynı etkiye sahiptir; tf.Variableyani kapsam, işleme veya değişken adına bir önek olarak eklenir.

Ancak, ad kapsamı tarafından yoksayılır tf.get_variable. Bunu aşağıdaki örnekte görebiliriz:

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_variableBir kapsamda kullanarak erişilen bir değişkeni yerleştirmenin tek yolu , aşağıdaki örnekte olduğu gibi bir değişken kapsamı kullanmaktır:

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

Bu, değişkenleri farklı ad kapsamlarında bile programın farklı bölümlerinde kolayca paylaşmamızı sağlar:

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

GÜNCELLEME

Versiyon r0.11 itibariyle op_scopeve variable_op_scopehem edilir kaldırılmış ve yerini name_scopeve variable_scope.


41
Açık açıklama için teşekkürler. Doğal olarak, bir takip sorusu " Tensorflow neden bu kafa karıştırıcı benzer mekanizmaların ikisine birden sahip? Neden bunları scopeetkili bir şekilde yapan tek bir yöntemle değiştirmiyorsunuz variable_scope?"
John

8
Kavramsal olarak variable_scopevs arasındaki ayrımın neden gerekli olduğunu anladığımı sanmıyorum name_scope. Eğer bir değişken ( tf.Variableveya ile herhangi bir şekilde tf.get_variable) yaratırsa , kapsamı veya tam adını belirtirsek her zaman elde edebilmemiz gerektiğine inanıyorum. Neden biri kapsam adı şey göz ardı ederken, diğeri anlamıyorum anlamıyorum. Bu garip davranışın mantığını anlıyor musunuz?
Charlie Parker

23
Bunun nedeni, değişken kapsamda, işlemleri tanımlamak için kullanılan geçerli ad kapsamından etkilenmeyen yeniden kullanılabilir değişkenler için ayrı kapsamlar tanımlanabilir.
Andrzej Pronobis

6
Merhaba , Bir değişken_skopundaki değişken adının neden her zaman bir 0 ile biteceğini açıklayabilir misiniz? Bu, değişken adlarının şunlar ile bitebileceği anlamına mı geliyor: 1,: 2, vb, bu nasıl olabilir?
James Fan

2
@JamesFan Her "bildirim" bir işlemdir, bu nedenle a = tf.Variable (.. name) dediğinizde bir tensörü geri alırsınız, ancak aslında bir işlem de oluşturur. a yazdırırsanız, tensörü a: 0 alırsınız. A.op yazdırırsanız, bu tensör değerini hesaplayacak işlemi alırsınız.
Robert Lugg

84

Hem variable_op_scope ve op_scope şimdi artık yok ve hiç kullanılmamalıdır.

Diğer iki ile ilgili olarak, basit bir örnek oluşturarak her şeyi görselleştirmeye çalışmadan önce değişken_scope ve name_scope (neredeyse aynı görünüyordu) arasındaki farkı anlamada problemler yaşadım :

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()

Burada bazı değişkenler ve sabitler oluşturan ve bunları kapsamları (sağlanan tipine bağlı olarak) gruplandıran bir işlev oluşturmak. Bu işlevde, tüm değişkenlerin adlarını da yazdırıyorum. Bundan sonra, elde edilen değerlerin değerlerini almak ve olay dosyalarını TensorBoard'da araştırmak için kaydetmek için grafiği yürütürüm. Bunu çalıştırırsanız, aşağıdakileri alırsınız:

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'u açarsanız benzer deseni görürsünüz (gördüğünüz gibi dikdörtgen bdışındadır scope_name):


Bu size cevap verir :

Artık tf.variable_scope()tüm değişkenlerin adlarına (nasıl oluşturursanız yaratın), ops, sabitlere bir önek eklediğini görüyorsunuz . Öte yandan , hangi değişkeni ve hangi kapsamda kullanmak istediğinizi bildiğinizi varsaydığı için tf.name_scope()oluşturulan değişkenleri yok sayar tf.get_variable().

Değişkenleri paylaşma hakkında iyi bir belge size şunu söyler:

tf.variable_scope(): Aktarılan adlar için ad alanlarını yönetir tf.get_variable().

Aynı dokümantasyon Değişken Kapsamının nasıl çalıştığı ve ne zaman yararlı olduğu hakkında daha fazla ayrıntı sağlar.


2
Örnek ve görsellerle muhteşem cevap, hadi bu cevabı onaylamış millet alalım!
David Parks

43

Ad alanları, değişkenler ve işleçler için adları hiyerarşik bir şekilde düzenlemenin bir yoludur (örneğin "scopeA / scopeB / scopeC / op1")

  • tf.name_scope varsayılan grafikteki işleçler için ad alanı oluşturur.
  • tf.variable_scope varsayılan grafikte hem değişkenler hem de işleçler için ad alanı oluşturur.

  • tf.op_scopeile aynıdır tf.name_scope, ancak belirtilen değişkenlerin oluşturulduğu grafik için.

  • tf.variable_op_scopeile aynıdır tf.variable_scope, ancak belirtilen değişkenlerin oluşturulduğu grafik için.

Yukarıdaki kaynaklara bağlantılar, bu dokümantasyon sorununu netleştirmemize yardımcı olur.

Bu örnek , tüm kapsam türlerinin hem değişkenler hem de işleçler için ad farklılıkları tanımladığını göstermektedir:

  1. ile tanımlanan tf.variable_op_scopeveya tf.variable_scopeile uyumlu olan tf.get_variablekapsamlar (diğer iki kapsamı yoksayar)
  2. tf.op_scopeve tf.variable_op_scopekapsam oluşturmak için belirtilen değişkenler listesinden bir grafik seçin. Davranışları dışında tf.name_scopeve tf.variable_scopebuna göre davranışları dışında
  3. tf.variable_scopeve variable_op_scopebelirtilen veya varsayılan başlatıcıyı ekleyin.

Belirtilen değişkenlerin oluşturulduğu grafik için? Bu, fabrizioM tarafından yukarıdaki örnek gibi, kapsam olarak tf.variable_op_scope ([a, b], name, "mysum2"), burada a ve b parametresi bu fonksiyondan etkilenmez ve bu kapsamda tanımlanan değişkenler etkilenir mi?
Xiuyi Yang

Her iki sorunun da cevabı evet: belirtilen değişkenlerin yaratıldığı ve değiştirilmediği grafik.
Alexander Gorban

Bu, tf.name_scope ve tf.variable_scope'un yalnızca varsayılan grafikte kullanıldığı, ancak tf.Graph () kullanarak bir grafiği açıkça tanımladığınız ve uyguladığınızda, diğer iki işlev tf.op_scope ve tf.variable_op_scope'un kullanılamadığı anlamına mı geliyor? bu grafik!
Xiuyi Yang

12

Basitleştirelim: sadece kullanın tf.variable_scope. Bir TF geliştiricisinden alıntı yaparak :

Şu anda, dahili kod ve kütüphaneler dışında herkesin kullanmasını variable_scopeve kullanmamasını öneririz name_scope.

variable_scopeİşlevselliğinin temelde bu özellikleri genişletmesinin yanı sıra, name_scopebirlikte nasıl bu kadar hoş oynamadıklarını düşünün:

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

Bağlı kalarak variable_scopenedeniyle uyumsuzluk bu tür sadece bazı baş ağrıları önlemek.


9

API r0.11'e gelince op_scopeve variable_op_scopeher ikisi de kullanımdan kaldırıldı . name_scopeve variable_scopeyuvalanabilir:

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

Bunları iki grup olarak düşünebilirsiniz: variable_op_scopeve op_scopegirdi olarak bir değişkenler kümesi alabilir ve işlemler oluşturmak için tasarlanmıştır. Fark şu değişkenlerin yaratılmasını nasıl etkilediğidir 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

viki örnekte değişkenin ismine dikkat edin .

tf.name_scopeve için aynı 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

Öğreticide değişken kapsam hakkında daha fazla bilgi edinebilirsiniz . Benzer bir soru, Stack Overflow'da daha önce sorulmuştu .


2

Tensorflow belgelerin Bu sayfanın son bölümde: ops Adlarıtf.variable_scope()

[...] bunu yaptığımızda with tf.variable_scope("name"), bu dolaylı olarak a'yı açar tf.name_scope("name"). Örneğin:

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

Ad kapsamları değişken bir kapsama ek olarak açılabilir ve daha sonra değişkenlerin adlarını etkiler, ancak değişkenleri etkilemez.

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"

Dize yerine yakalanan bir nesneyi kullanarak değişken bir kapsamı açarken, ops için geçerli ad kapsamını değiştirmeyiz.


2

Tensorflow 2.0 Uyumlu Cevap : İlgili Fonksiyonlar ile ilgili açıklamalar Andrzej Pronobisve Salvador Daliçok detaylı Scope.

Yukarıda tartışılan, şu anda aktif olan Kapsam Fonksiyonlarının (17 Şubat 2020) variable_scopeve name_scope.

Topluluğun yararına yukarıda tartıştığımız bu işlevler için 2.0 Uyumlu Çağrıları belirtmek.

1.x'deki fonksiyon :

tf.variable_scope

tf.name_scope

2.x'te Saygı Fonksiyonu :

tf.compat.v1.variable_scope

tf.name_scope( tf.compat.v2.name_scopetaşındıysa 1.x to 2.x)

1.x'ten 2.x'e geçiş hakkında daha fazla bilgi için lütfen bu Taşıma Kılavuzuna bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.