web-dev-qa-db-fra.com

Initialisation des matrices de poids Tensorflow RNN

J'utilise bidirectional_rnn avec GRUCell mais c'est une question générale concernant le RNN dans Tensorflow.

Je ne trouvais pas comment initialiser les matrices de poids (entrée masquée, masquée masquée). Sont-ils initialisés au hasard? en zéros? Sont-ils initialisés différemment pour chaque LSTM que je crée? 

EDIT: Une autre motivation pour cette question est de pré-former certains LSTM et d’utiliser leurs poids dans un modèle ultérieur. Je ne sais pas comment faire cela actuellement sans sauvegarder tous les états et restaurer le modèle entier.

Merci.

6
yoki

Comment initialiser les matrices de poids pour RNN?

Je crois que les gens utilisent l'initialisation normale aléatoire pour les matrices de poids pour RNN. Découvrez le exemple dans le TensorFlow GitHub Repo . Comme le cahier est un peu long, ils ont un modèle LSTM simple dans lequel ils utilisent tf.truncated_normal pour initialiser les poids et tf.zeros pour initialiser les biais (bien que j'aie essayé d'utiliser tf.ones pour initialiser les biais auparavant, ils semblent également fonctionner). Je crois que l’écart type est un hyperparamètre que vous pouvez régler vous-même. Parfois, l’initialisation des poids est importante pour le flux de gradient. Bien que, autant que je sache, LSTM lui-même est conçu pour traiter le problème de suppression de dégradé (et le découpage de dégradé aide à résoudre le problème de l'explosion de dégradé), vous n'avez donc peut-être pas besoin d'être super attentif à la configuration de std_dev dans LSTM ? J'ai lu des articles recommandant l'initialisation de Xavier ( doc de l'API TF pour l'initialiseur Xavier ) dans un contexte de réseau de neurones à convolution. Je ne sais pas si les gens l'utilisent dans RNN, mais j'imagine que vous pouvez même essayer ceux de RNN si vous voulez voir si cela vous aide. 

Passons maintenant à la réponse de @ Allen et à votre question suivante dans les commentaires.

Comment contrôler l'initialisation avec une portée variable?

Utilisation du modèle LSTM simple dans le bloc-notes bloc-notes python TensorFlow GitHub que j'ai lié à titre d'exemple. enter image description here Spécifiquement, si je veux re-factoriser la partie LSTM du code dans l'image ci-dessus en utilisant le contrôle de portée variable, je peux coder quelque chose comme suit ...

import tensorflow as tf
def initialize_LSTMcell(vocabulary_size, num_nodes, initializer):
    '''initialize LSTMcell weights and biases, set variables to reuse mode'''
    gates = ['input_gate', 'forget_gate', 'memory_cell', 'output_gate']
    with tf.variable_scope('LSTMcell') as scope:
        for gate in gates:
            with tf.variable_scope(gate) as gate_scope:
                wx = tf.get_variable("wx", [vocabulary_size, num_nodes], initializer)
                wt = tf.get_variable("wt", [num_nodes, num_nodes], initializer)
                bi = tf.get_variable("bi", [1, num_nodes, tf.constant_initializer(0.0)])
                gate_scope.reuse_variables() #this line can probably be omitted, b.z. by setting 'LSTMcell' scope variables to 'reuse' as the next line, it'll turn on the reuse mode for all its child scope variables
        scope.reuse_variables()

def get_scope_variables(scope_name, variable_names):
    '''a helper function to fetch variable based on scope_name and variable_name'''
    vars = {}
    with tf.variable_scope(scope_name, reuse=True):
        for var_name in variable_names
            var = tf.get_variable(var_name)
            vars[var_name] = var
    return vars

def LSTMcell(i, o, state):
    '''a function for performing LSTMcell computation'''
    gates = ['input_gate', 'forget_gate', 'memory_cell', 'output_gate']
    var_names = ['wx', 'wt', 'bi']
    gate_comp = {}
    with tf.variable_scope('LSTMcell', reuse=True):
        for gate in gates:
            vars = get_scope_variables(gate, var_names)
            gate_comp[gate] = tf.matmul(i, vars['wx']) + tf.matmul(o, vars['wt']) + vars['bi']
    state = tf.sigmoid(gate_comp['forget_gate']) * state + tf.sigmoid(gate_comp['input_gate']) * tf.tanh(gate_comp['memory_cell'])
    output = tf.sigmoid(gate_comp['output_gate']) * tf.tanh(state)
    return output, state

L'utilisation du code re-factorisé serait quelque chose comme suit ...

initialize_LSTMcell(volcabulary_size, num_nodes, tf.truncated_normal_initializer(mean=-0.1, stddev=.01))
#...Doing some computation...
LSTMcell(input_tensor, output_tensor, state)

Même si le code refactorisé peut sembler moins simple, l'utilisation du contrôle de variable de portée garantit l'encapsulation de la portée et permet des contrôles de variable flexibles (à mon avis du moins).

En pré-entraînement de certains LSTM et en utilisant leurs poids dans un modèle ultérieur. Comment faire cela sans sauvegarder tous les états et restaurer le modèle entier.

En supposant que vous ayez un modèle pré-entraîné figé et chargé, si vous voulez utiliser leurs 'wx', 'wt' et 'bi' figés, vous pouvez simplement trouver leurs noms de portée et noms de variable parent, puis récupérer les variables en utilisant une structure similaire dans get_scope_variables func. 

with tf.variable_scope(scope_name, reuse=True):
    var = tf.get_variable(var_name)

Voici un lien vers comprenant la portée de la variable et les variables de partage . J'espère que ceci est utile. 

9
Zhongyu Kuang

Les modèles RNN créeront leurs variables avec get_variable, et vous pouvez contrôler l'initialisation en encapsulant le code qui crée ces variables avec variable_scope et en lui passant un initialiseur par défaut . À moins que le RNN le spécifie explicitement ( en regardant le code , ce n'est pas le cas), uniform_unit_scaling_initializer est utilisé .

Vous devriez également pouvoir partager les poids de modèle en déclarant le deuxième modèle et en transmettant reuse = True à son variable_scope. Tant que les espaces de noms concordent, le nouveau modèle obtiendra les mêmes variables que le premier modèle.

5
Allen Lavoie

Un moyen simple d’initialiser tous les poids du noyau avec certains initialiseurs consiste à laisser l’initialiseur dans tf.variable_scope(). Par exemple: 

with tf.variable_scope('rnn', initializer=tf.variance_scaling_initializer()):
   basic_cell= tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
   outputs, state= tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
3
SJL