web-dev-qa-db-fra.com

Dans TensorFlow, y a-t-il un moyen d'initialiser des variables non initialisées?

La méthode standard d’initialisation des variables dans TensorFlow est la suivante:

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

Après avoir effectué quelques apprentissages pendant un certain temps, je crée un nouvel ensemble de variables, mais une fois que je les ai initialisées, toutes les variables existantes sont réinitialisées. Pour le moment, il faut sauvegarder toutes les variables dont j'ai besoin, puis les réappliquer après l'appel tf.initalize_all_variables. Cela fonctionne mais est un peu moche et maladroit. Je ne trouve rien de tel dans la documentation ...

Est-ce que quelqu'un connaît un bon moyen d'initialiser les variables non initialisées? 

42
Daniel Slater

Il n’existe pas de moyen élégant * d’énumérer les variables non initialisées dans un graphique. Toutefois, si vous avez accès aux nouveaux objets variables - appelons-les v_6, v_7 et v_8 - vous pouvez les initialiser de manière sélective à l'aide de tf.initialize_variables() :

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

* Un processus d'essai et d'erreur pourrait être utilisé pour identifier les variables non initialisées, comme suit:

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)
# ...

... Cependant, je ne tolérerais pas un tel comportement :-).

31
mrry

UPDATE: TensorFlow 0.9 utilise une nouvelle méthode qui "corrige" tout cela mais uniquement si vous utilisez un VariableScope avec reuse défini sur True. tf.report_uninitialized_variables pouvant être utilisé sur une ligne avec sess.run( tf.initialize_variables( list( tf.get_variable(name) for name in sess.run( tf.report_uninitialized_variables( tf.all_variables( ) ) ) ) ) )

ou plus intelligemment grâce à la possibilité de spécifier les variables que vous comptez initialiser:

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

C’est encore moins idéal que de savoir quelles variables sont et ne sont pas initialisées et de s’en occuper correctement, mais dans le cas d’une erreur de direction comme les classes optim (voir ci-dessous), il peut être difficile de l’éviter.

Notez également que tf.initialize_variables ne peut pas évaluer tf.report_uninitialized_variables. Ils doivent donc être exécutés tous les deux dans le contexte de la session pour fonctionner.


Il existe un moyen inélégant mais concis de le faire. Avant d'introduire vos nouvelles variables, exécutez temp = set(tf.all_variables()), puis sess.run(tf.initialize_variables(set(tf.all_variables()) - temp)). Ensemble, ils initialiseront uniquement les variables créées après l’affectation de la valeur temporaire.

Je jouais avec l'apprentissage par transfert, alors je voulais un moyen rapide de le faire aussi, mais c'est le meilleur moyen que j'ai pu trouver. Surtout lorsque vous utilisez des outils comme AdamOptimizer, qui ne vous donne pas un accès facile (ou incertain,) aux variables qu’il utilise. Donc, ce qui suit apparaît dans mon code. (J'initialise explicitement les variables de la nouvelle couche et je l'exécute une fois pour afficher l'erreur initiale avant le transfert de l'apprentissage. Juste pour un contrôle de cohérence.)

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

Et cela résout tous mes problèmes.

EDIT:@ La réponse de Lifu_Huang indique le moyen approprié pour résoudre mon problème. Théoriquement, vous devriez utiliser tf.train.Optimizer.get_slot_names et 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()])

Cela me donne cependant AttributeError: 'NoneType' object has no attribute 'initializer'. Je ferai des modifications lorsque je découvrirai ce que j'ai mal fait pour que vous ne commettiez pas mes erreurs.

31
Poik

TF n'a pas de fonction qui fait exactement ce que vous voulez , mais vous pouvez facilement en écrire une:

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

Ici, j'extrais toutes les variables globales , les itère toutes et vérifie si elles sont déjà initialisées . Après cela, je reçois une liste de variables non initialisées que je initialise . J'imprime également les variables que je vais initialiser à des fins de débogage.


Vous pouvez facilement vérifier que cela fonctionne comme prévu:

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

Cela imprimera toutes les variables unitialisées avant de les initialiser et le dernier sess.run s’assurera que toutes les variables sont initialisées.


Vous pouvez également utiliser tf.report_uninitialized_variables() pour écrire une fonction similaire. Un croquis de celui-ci est ici .

22
Salvador Dali

J'ai mis au point une méthode pour 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]
4
平芜泫

Dans le cas mentionné par @Poik, lorsque les variables sont créées par des optimiseurs de sorte à ne pas pouvoir y accéder directement, une solution plus propre consiste à utiliser tf.train.Optimizer.get_slot

Certaines sous-classes d'optimiseur, telles que MomentumOptimizer et AdagradOptimizer, allouent et gèrent des variables supplémentaires associées aux variables à former. Celles-ci s'appellent des fentes. Vous pouvez utiliser tf.train.Optimizer.get_slot_names() pour obtenir tous les noms d'emplacement d'un optimiseur, puis utiliser tf.train.Optimizer.get_slot pour obtenir la variable allouée pour ces emplacements.

4
Lifu Huang

Par ailleurs, si vous souhaitez initialiser un seul tenseur (par exemple, tf.Variable) qui n'a pas été initialisé à l'aide de tf.global_variables_initializer(), vous pouvez utiliser your_tensor.initializer dans sess.run() comme dans l'exemple suivant:

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.]]
1
kmario23

Je pense que le moyen le plus simple est de créer d'abord tous les opérateurs de formation, puis d'initialiser les variables.

Par exemple, j'ai résolu le problème de la pré-formation par couches avec Adam Optimizer de la manière suivante:

 # 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())
0
Taras Kucherenko