¿En qué orden se guardan los pesos en un kernel LSTM en Tensorflow?

Busqué en los pesos guardados para una LSTMCell en Tensorflow. Tiene un kernel grande y pesos de polarización.

Las dimensiones del núcleo son.

 (input_size + hidden_size)*(hidden_size*4) 

Ahora, por lo que entiendo, esto es encapsular 4 entradas a transformaciones afines de capa oculta, así como 4 transformaciones de capa oculta a oculta.

Entonces debería haber 4 matrices de tamaño

 input_size*hidden_size 

y 4 de tamaño

 hidden_size*hidden_size 

Alguien puede decirme o indicarme el código donde TF guarda esto, para que pueda romper la matriz del núcleo en matrices más pequeñas.

Las ponderaciones se combinan como se menciona en la otra respuesta, pero el orden es: donde c es el contexto y h es la historia.

 input_c, input_h new_input_c, new_input_h forget_c, forget_h output_c, output_h 

El código relevante está aquí.

 if self._state_is_tuple: c, h = state else: c, h = array_ops.split(value=state, num_or_size_splits=2, axis=one) gate_inputs = math_ops.matmul( array_ops.concat([inputs, h], 1), self._kernel) gate_inputs = nn_ops.bias_add(gate_inputs, self._bias) # i = input_gate, j = new_input, f = forget_gate, o = output_gate i, j, f, o = array_ops.split( value=gate_inputs, num_or_size_splits=4, axis=one) 

En tensorflow 1.5, las variables LSTM se definen en el método LSTMCell.build . El código fuente se puede encontrar en rnn_cell_impl.py :

 self._kernel = self.add_variable( _WEIGHTS_VARIABLE_NAME, shape=[input_depth + h_depth, 4 * self._num_units], initializer=self._initializer, partitioner=maybe_partitioner) self._bias = self.add_variable( _BIAS_VARIABLE_NAME, shape=[4 * self._num_units], initializer=init_ops.zeros_initializer(dtype=self.dtype)) 

Como puede ver, solo hay una [input_depth + h_depth, 4 * self._num_units] , no 8 matrices diferentes, y todas se multiplican simultáneamente en un lote.

Las puertas se definen de esta manera:

 i, j, f, o = array_ops.split(value=gate_inputs, num_or_size_splits=4, axis=one)