5

code ci-dessous de l'unité de GRUCell tensorflow montre les opérations typiques pour obtenir un état caché mis à jour, lorsque l'état précédent caché est fourni en même temps que l'entrée de courant dans la séquence.Explication de la cellule GRU dans Tensorflow?

def __call__(self, inputs, state, scope=None): 
    """Gated recurrent unit (GRU) with nunits cells.""" 
    with vs.variable_scope(scope or type(self).__name__): # "GRUCell" 
     with vs.variable_scope("Gates"): # Reset gate and update gate. 
     # We start with bias of 1.0 to not reset and not update. 
     r, u = array_ops.split(1, 2, _linear([inputs, state], 
              2 * self._num_units, True, 1.0)) 
     r, u = sigmoid(r), sigmoid(u) 
     with vs.variable_scope("Candidate"): 
     c = self._activation(_linear([inputs, r * state], 
            self._num_units, True)) 
     new_h = u * state + (1 - u) * c 
return new_h, new_h 

Mais je ne vois pas weights et biases ici. par exemple. je crois comprendre que l'obtention r et u, il faudrait à multiplier les poids et les biais avec courant d'entrée et/ou de l'état caché pour obtenir un état caché mis à jour.

J'ai écrit une unité gru comme suit:

def gru_unit(previous_hidden_state, x): 
    r = tf.sigmoid(tf.matmul(x, Wr) + br) 
    z = tf.sigmoid(tf.matmul(x, Wz) + bz) 
    h_ = tf.tanh(tf.matmul(x, Wx) + tf.matmul(previous_hidden_state, Wh) * r) 
    current_hidden_state = tf.mul((1 - z), h_) + tf.mul(previous_hidden_state, z) 
    return current_hidden_state 

Ici je fais explicitement l'utilisation des poids et des biais Wx, Wr, Wz, Whbr, bh, bz, etc. soient mis à jour l'état caché. Ces poids et biais sont ce qui est appris/réglé après l'entraînement.

Comment puis-je utiliser intégré dans tensorflow GRUCell pour obtenir le même résultat que ci-dessus?

+0

Ils concaténer la '' r' et porte Z' de le faire en une seule fois, sauve le calcul. –

Répondre

3

Ils sont là que vous venez de ne les voyez pas dans ce code car la fonction _linear ajoute les poids et les préjugés.

r, u = array_ops.split(1, 2, _linear([inputs, state], 
              2 * self._num_units, True, 1.0)) 

...

def _linear(args, output_size, bias, bias_start=0.0, scope=None): 
    """Linear map: sum_i(args[i] * W[i]), where W[i] is a variable. 

    Args: 
    args: a 2D Tensor or a list of 2D, batch x n, Tensors. 
    output_size: int, second dimension of W[i]. 
    bias: boolean, whether to add a bias term or not. 
    bias_start: starting value to initialize the bias; 0 by default. 
    scope: VariableScope for the created subgraph; defaults to "Linear". 

    Returns: 
    A 2D Tensor with shape [batch x output_size] equal to 
    sum_i(args[i] * W[i]), where W[i]s are newly created matrices. 

    Raises: 
    ValueError: if some of the arguments has unspecified or wrong shape. 
    """ 
    if args is None or (nest.is_sequence(args) and not args): 
    raise ValueError("`args` must be specified") 
    if not nest.is_sequence(args): 
    args = [args] 

    # Calculate the total size of arguments on dimension 1. 
    total_arg_size = 0 
    shapes = [a.get_shape().as_list() for a in args] 
    for shape in shapes: 
    if len(shape) != 2: 
     raise ValueError("Linear is expecting 2D arguments: %s" % str(shapes)) 
    if not shape[1]: 
     raise ValueError("Linear expects shape[1] of arguments: %s" % str(shapes)) 
    else: 
     total_arg_size += shape[1] 

    # Now the computation. 
    with vs.variable_scope(scope or "Linear"): 
    matrix = vs.get_variable("Matrix", [total_arg_size, output_size]) 
    if len(args) == 1: 
     res = math_ops.matmul(args[0], matrix) 
    else: 
     res = math_ops.matmul(array_ops.concat(1, args), matrix) 
    if not bias: 
     return res 
    bias_term = vs.get_variable(
     "Bias", [output_size], 
     initializer=init_ops.constant_initializer(bias_start)) 
    return res + bias_term 
+0

Il semble donc que les poids et des biais sont créés à la demande, et sont partagés entre les pas de temps avec 'get_variable' qui retournera la même chose si elle est appelée dans la même scope.It variable n'est pas clair pour moi comment la matrice de poids est initialisé cependant. –

+0

Je pense qu'il est initialisé en utilisant l'initialiseur par défaut pour la portée variable actuelle. – chasep255

+0

Je pense que cela répond également à mon autre [question] (http://stackoverflow.com/questions/39302344/tensorflow-rnn-input-size) à propos de tensorflow rnns. –