2016-07-23 14 views
19

Chcę kawałek kodu, który tworzy zmienną w zasięgu, jeśli nie istnieje, i dostęp do zmiennej, jeśli już istnieje. Potrzebuję go, aby być tym samym kodem, ponieważ będzie on wywoływany wiele razy.Zakres zmiennej Tensorflow: ponowne użycie, jeśli zmienna istnieje

Jednak Tensorflow mnie potrzebuje, aby określić, czy chcę, aby utworzyć lub ponownego użycia zmiennej, tak:

with tf.variable_scope("foo"): #create the first time 
    v = tf.get_variable("v", [1]) 

with tf.variable_scope("foo", reuse=True): #reuse the second time 
    v = tf.get_variable("v", [1]) 

Jak mogę dostać to, aby dowiedzieć się, czy chcesz utworzyć lub używać go automatycznie? Oznacza to, że powyższe dwa bloki kodu muszą być takie same i mieć uruchomiony program.

Odpowiedz

14

A ValueError jest wywoływany w get_variable() podczas tworzenia nowej zmiennej, której kształt nie jest zadeklarowany lub gdy narusza ponowne użycie podczas tworzenia zmiennych. W związku z tym, można spróbować to:

def get_scope_variable(scope_name, var, shape=None): 
    with tf.variable_scope(scope_name) as scope: 
     try: 
      v = tf.get_variable(var, shape) 
     except ValueError: 
      scope.reuse_variables() 
      v = tf.get_variable(var) 
    return v 

v1 = get_scope_variable('foo', 'v', [1]) 
v2 = get_scope_variable('foo', 'v') 
assert v1 == v2 

pamiętać, że poniższe działa również:

v1 = get_scope_variable('foo', 'v', [1]) 
v2 = get_scope_variable('foo', 'v', [1]) 
assert v1 == v2 
+2

Czy istnieje sposób to zrobić z zakresu najwyższego poziomu (czyli bez zakres)? – holdenlee

+2

@holdenlee Tak, wystarczy ustawić zakres na '''' (tzn. Pusty ciąg) –

+0

['tf.make_template'] (https://www.tensorflow.org/versions/master/api_docs/python/tf/make_template) jest również przydatny do tworzenia nowych zmiennych, jeśli nie istnieją i cicho je ponownie wykorzystują. – xolodec

12

Chociaż używając "try ... except ..." klauzula działa, myślę, że bardziej elegancki i utrzymaniu sposób oddzielny byłby proces inicjalizacji zmiennych z procesem "ponownego użycia".

def initialize_variable(scope_name, var_name, shape): 
    with tf.variable_scope(scope_name) as scope: 
     v = tf.get_variable(var_name, shape) 
     scope.reuse_variable() 

def get_scope_variable(scope_name, var_name): 
    with tf.variable_scope(scope_name, reuse=True): 
     v = tf.get_variable(var_name) 
    return v 

Ponieważ często musimy tylko inicjować zmienne, ale używać ich wielokrotnie, dzieląc dwa procesy, dzięki czemu kod staje się czystszy. W ten sposób nie będziemy musieli przechodzić przez klauzulę "try" za każdym razem, aby sprawdzić, czy zmienna została już utworzona, czy nie.

0

możemy napisać nasz abstrakcji nad tf.varaible_scope niż wykorzystuje reuse=None na pierwsze wezwanie i wykorzystuje reuse=True na zaproszeniach konsekwencji:

def variable_scope(name_or_scope, *args, **kwargs): 
    if isinstance(name_or_scope, str): 
    scope_name = tf.get_variable_scope().name + '/' + name_or_scope 
    elif isinstance(name_or_scope, tf.Variable): 
    scope_name = name_or_scope.name 

    if scope_name in variable_scope.scopes: 
    kwargs['reuse'] = True 
    else: 
    variable_scope.scopes.add(scope_name) 

    return tf.variable_scope(name_or_scope, *args, **kwargs) 
variable_scope.scopes = set() 

Zastosowanie:

with variable_scope("foo"): #create the first time 
    v = tf.get_variable("v", [1]) 

with variable_scope("foo"): #reuse the second time 
    v = tf.get_variable("v", [1]) 
5

Nowa opcja AUTO_REUSE załatwia sprawę.

Od tf.variable_scope API docs: jeśli reuse=tf.AUTO_REUSE, tworzymy zmienne, jeśli nie istnieją, i zwracamy je w inny sposób.

Podstawowe przykład dzielenia zmiennej AUTO_REUSE:

def foo(): 
    with tf.variable_scope("foo", reuse=tf.AUTO_REUSE): 
    v = tf.get_variable("v", [1]) 
    return v 

v1 = foo() # Creates v. 
v2 = foo() # Gets the same, existing v. 
assert v1 == v2