2016-02-02 8 views
34

Standardowy sposób inicjalizacji zmiennych w TensorFlow jestW TensorFlow jest jakiś sposób na zainicjowanie niezainicjowanych zmiennych?

init = tf.initialize_all_variables() 
sess = tf.Session() 
sess.run(init) 

Po uruchomieniu jakąś naukę na chwilę utworzyć nowy zestaw zmiennych, ale kiedyś je zainicjować resetuje wszystkie moje istniejące zmienne. W tej chwili moim sposobem obejścia tego jest zapisanie wszystkich potrzebnych zmiennych, a następnie ponowne ich zastosowanie po wywołaniu tf.initalize_all_variables. To działa, ale jest trochę brzydkie i niezgrabne. Nie mogę znaleźć czegoś takiego w dokumentach ...

Czy ktoś wie o jakimkolwiek dobrym sposobie inicjowania tylko niezainicjowanych zmiennych?

+0

Tutaj jest przykładem [prostej funkcji] (http://stackoverflow.com/a/43601894/1090562), która robi dokładnie to, co chcesz. –

+0

Funkcja 'tf.train.Optimizer.minimize (loss)' jest [zdefiniowana jako w dokumentacji] (https://www.tensorflow.org/versions/r0.11/api_docs/python/train.html#Optimizer .minimize) 'optim.apply_gradients (optim.compute_gradients (loss))'.To sprawi, że twój przykład będzie taki sam jak mój, z wyjątkiem tego, że wyrzucisz wszystkie "Brak". Czy po tym możesz uruchomić 'train_step'? Kiedy go uruchomiłem, wszystkie gniazda były "Brak", więc optymalizator pozostał niezainicjowany i sieć neuronowa nie działała. – Poik

Odpowiedz

24

Nie ma eleganckiego sposobu na wyliczenie niezainicjowanych zmiennych na wykresie. Jednakże, jeśli masz dostęp do nowych obiektów zmiennych — nazwijmy je v_6, v_7 i v_8 — można selektywnie je zainicjować za pomocą tf.initialize_variables():

init_new_vars_op = tf.initialize_variables([v_6, v_7, v_8]) 
sess.run(init_new_vars_op) 

*   proces prób i błędów może być używane do identyfikacji niezainicjowanych zmiennych, jak następuje:

uninitialized_vars = [] 
for var in tf.all_variables(): 
    try: 
     sess.run(var) 
    except tf.errors.FailedPreconditionError: 
     uninitialized_vars.append(var) 

init_new_vars_op = tf.initialize_variables(uninitialized_vars) 
# ... 

... jednak nie poparłbym takiego zachowania :-).

+3

Tensorflow 0.9 ma funkcję tf.report_uninitialized_variables(), która może być przydatna. – user3391229

26

UPDATE: TensorFlow 0.9 ma nową metodę, która „naprawia” to wszystko ale tylko jeśli używasz VariableScope z reuse zestaw do True. tf.report_uninitialized_variables które mogą być wykorzystane w jednej linii z sess.run(tf.initialize_variables(list(tf.get_variable(name) for name in sess.run(tf.report_uninitialized_variables(tf.all_variables())))))

lub bardziej inteligentnie poprzez zdolność do określenia zmiennych można oczekiwać, aby być inicjowane:

def guarantee_initialized_variables(session, list_of_variables = None): 
    if list_of_variables is None: 
     list_of_variables = tf.all_variables() 
    uninitialized_variables = list(tf.get_variable(name) for name in 
            session.run(tf.report_uninitialized_variables(list_of_variables))) 
    session.run(tf.initialize_variables(uninitialized_variables)) 
    return unintialized_variables 

To wciąż mniej doskonały niż faktycznie wiedząc, które zmienne są i są nie zainicjalizowany i nie zajmujący się tym prawidłowo, ale w przypadku błędnego kierunku, jak klasy optim (patrz poniżej) może być trudno uniknąć.

Należy również zauważyć, że tf.initialize_variables nie można ocenić tf.report_uninitialized_variables, więc oba z nich muszą być uruchamiane w kontekście sesji do pracy.


Jest nieeleganckie, ale zwięzły sposób to zrobić. Przed wprowadzeniem nowych zmiennych uruchom temp = set(tf.all_variables()), a następnie uruchom sess.run(tf.initialize_variables(set(tf.all_variables()) - temp)). Te razem inicjują tylko zmienne utworzone po przypisaniu wartości temperatury.

Grałem z uczeniem transferu, więc chciałem zrobić to szybko, ale jest to najlepszy sposób, jaki mogłem znaleźć. Zwłaszcza gdy używa się rzeczy takich jak AdamOptimizer, co nie daje łatwego (lub innego, nie jestem pewien) dostępu do zmiennych, których używa. Tak więc poniższe pojawia się w moim kodzie. (I inicjowanie zmiennych nowej warstwy za jawnie, i uruchomić go raz, aby pokazać początkowy błąd przed nauką transferowego. Tylko dla sprawdzenia dokonywane.)

temp = set(tf.all_variables()) 
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) 
#I honestly don't know how else to initialize ADAM in TensorFlow. 
sess.run(tf.initialize_variables(set(tf.all_variables()) - temp)) 

I to rozwiązuje wszystkie moje problemy.

EDYTOWANIE:@Lifu_Huang's answer określa właściwy sposób rozwiązania mojego problemu. Teoretycznie, należy użyć tf.train.Optimizer.get_slot_names i tf.train.Optimizer.get_slot:

optim = tf.train.AdadeltaOptimizer(1e-4) 
loss = cross_entropy(y,yhat) 
train_step = optim.minimize(loss) 
sess.run(tf.initialize_variables([optim.get_slot(loss, name) 
            for name in optim.get_slot_names()]) 

To jednak daje mi AttributeError: 'NoneType' object has no attribute 'initializer'. Wprowadzę zmiany, gdy zorientuję się, co zrobiłem źle, więc nie popełniasz moich błędów.

+1

Odtworzono obiekt 'AttributeError: 'NoneType', który nie ma atrybutu" initializer ". – rafaelcosman

+2

Należy zauważyć, że pomimo gniazd, mogą istnieć inne zmienne utworzone przez optymalizator. 'AdamOptimizer' dla mnie również tworzy vars' [, ] 'które nie odpowiadają zmiennemu var, więc nie dostaniesz ich jako slotów. – Albert

4

W przypadku wspomnianego przypadku @Poik, gdy zmienne są tworzone przez optymalizatory, więc nie można uzyskać do nich dostępu bezpośrednio, czystszym rozwiązaniem jest użycie tf.train.Optimizer.get_slot.

Niektóre podklasy optymalizatora, takie jak MomentumOptimizer i AdagradOptimizer, przydzielają dodatkowe zmienne związane ze zmiennymi do zarządzania i zarządzają nimi. Są to tak zwane Automaty. Możesz użyć tf.train.Optimizer.get_slot_names(), aby uzyskać wszystkie nazwy slotów, które posiada optymalizator, a następnie użyć tf.train.Optimizer.get_slot, aby uzyskać zmienną przydzieloną dla tych gniazd.

+2

Ta odpowiedź nie jest jeszcze użyteczna, ponieważ 'tf.train.Optimizer.get_slot' zwraca' None' dla slotów, dopóki optymalizator nie utworzy wymaganych zmiennych, co stanie się, gdy 'minimize' zostanie uruchomiona po raz pierwszy. Obejście tego wymaga wywołania nieudokumentowanej funkcji 'tf.train.Optimizer._zeros_slot()' lub innych, których nigdy nie powinieneś robić, jeśli chcesz udokumentować wsparcie i móc korzystać z przyszłych aktualizacji TensorFlow. – Poik

+1

Należy zauważyć, że pomimo gniazd, mogą być inne vary utworzone przez optymalizator. 'AdamOptimizer' dla mnie również tworzy vars' [, ] 'które nie odpowiadają zmiennemu var, więc nie dostaniesz ich jako slotów. – Albert

4

mam wymyślić sposobu TensorFlow r0.11:

def get_uninitialized_variables(variables=None): 
    """Get uninitialized variables as a list. 

    Parameters 
    ---------- 
    variables : collections.Iterable[tf.Variable] 
     Return only uninitialized variables within this collection. 
     If not specified, will return all uninitialized variables. 

    Returns 
    ------- 
    list[tf.Variable] 
    """ 
    sess = tf.get_default_session() 
    if variables is None: 
     variables = tf.all_variables() 
    else: 
     variables = list(variables) 
    init_flag = sess.run(
     tf.pack([tf.is_variable_initialized(v) for v in variables])) 
    return [v for v, f in zip(variables, init_flag) if not f] 
0

Myślę, że najprostszym sposobem jest utworzenie wszystkich operatorów szkoleniowych pierwszy i zainicjować zmienne później.

Na przykład, rozwiązał problem warstwy mądry pretraining Adam Optimizer w następujący sposób:

# create an optimizer 
pretrain_optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) 

# Make an array of the trainers for all the layers 
trainers=[pretrain_optimizer.minimize(loss_reconstruction(ae.run_less_layers(ae._input_, i+1), ae.run_less_layers(ae._input_, i+1, is_target=True)), global_step=tf.contrib.framework.get_or_create_global_step(), name='Layer_wise_optimizer_'+str(i)) for i in xrange(len(ae_shape) - 2)] 

# Initialize all the variables 
sess.run(tf.global_variables_initializer()) 
13

TF does not have a function that does exactly what you want, ale łatwo można napisać:

import tensorflow as tf 

def initialize_uninitialized(sess): 
    global_vars   = tf.global_variables() 
    is_not_initialized = sess.run([tf.is_variable_initialized(var) for var in global_vars]) 
    not_initialized_vars = [v for (v, f) in zip(global_vars, is_not_initialized) if not f] 

    print [str(i.name) for i in not_initialized_vars] # only for testing 
    if len(not_initialized_vars): 
     sess.run(tf.variables_initializer(not_initialized_vars)) 

Tutaj wyodrębnij wszystkie global variables, wykonaj iteracje wszystkich i sprawdź, czy są one are already initialized. Po tym otrzymuję listę niezainicjowanych zmiennych, które I initialize. Drukuję również zmienne, które mam zamiar zainicjować w celu debugowania.


Można łatwo sprawdzić, że działa zgodnie z oczekiwaniami:

a = tf.Variable(3, name='my_var_a') 
b = tf.Variable(4, name='my_var_b') 

sess = tf.Session() 
initialize_uninitialized(sess) 
initialize_uninitialized(sess) 

c = tf.Variable(5, name='my_var_a') # the same name, will be resolved to different name 
d = tf.Variable(6, name='my_var_d') 
initialize_uninitialized(sess) 

print '\n\n', sess.run([a, b, c, d]) 

To będzie drukować wszystkie zmienne unitialized przed inicjowanie ich i ostatni sess.run będzie upewnić się przekonać, że wszystkie zmienne są inicjowane .


Można również użyć tf.report_uninitialized_variables() napisać podobną funkcję. Szkicem tego jest here.

+0

Świetna odpowiedź. Masz mój głos. Czy użycie 'tf.report_uninitialized_variables()' byłoby lepszym rozwiązaniem? –

+0

@PaulO moim zdaniem oba podejścia są podobne i nie mogę powiedzieć, że którekolwiek z nich jest lepsze. –

1

Btw, jeśli chcesz zainicjować tylko jeden tensor (Na przykład: tf.Variable), który nie został zainicjowany przy użyciu tf.global_variables_initializer(), wówczas można użyć your_tensor.initializer w sess.run() jak w poniższym przykładzie:

In [196]: weights = tf.Variable(tf.zeros(shape=(3, 4)), name='weights') 

In [197]: with tf.Session() as sess: 
    ...:  sess.run(weights.initializer) 
    ...:  print(weights.eval()) 
    ...:  

# the result 
[[ 0. 0. 0. 0.] 
[ 0. 0. 0. 0.] 
[ 0. 0. 0. 0.]] 
Powiązane problemy