def __init__(self, num_cells, input_dim, seq_length, name, activation=tf.nn.tanh, dynamic=False, bidirectional=False): """ Parameters ---------- num_cells : int Number of neurons in the layer. input_dim : int Dimensionality of the input vectors, e.t. number of features. Dimensionality example: [batch_size, seq_length, num_features(this is input_dim in this case)]. seq_length : int Max length of the input sequences. activation : tensorflow function Activation function of the layer. dynamic : boolean Influences whether the layer will be working as dynamic RNN or static. The difference between static and dynamic is that in case of static TensorFlow builds static graph and the RNN will always go through each time step in the sequence. In case of dynamic TensorFlow will be creating RNN `in a while loop`, that is to say that using dynamic RNN you can pass sequences of variable length, but you have to provide list of sequences' lengthes. Currently API for using dynamic RNNs is not provided. WARNING! THIS PARAMETER DOESN'T PLAY ANY ROLE IF YOU'RE GONNA STACK RNN LAYERS. bidirectional : boolean Influences whether the layer will be bidirectional. WARNING! THIS PARAMETER DOES NOT PLAY ANY ROLE IF YOU ARE GOING TO STACK RNN LAYERS. """ self._num_cells = num_cells self._input_dim = input_dim self._f = activation cell = GRUCell(num_units=num_cells, activation=activation, dtype=tf.float32) cell.build(input_shape=[None, tf.Dimension(self._input_dim)]) params = cell.variables param_common_name = name + f'_{num_cells}_{input_dim}_{seq_length}' named_params_dict = {(param_common_name + '_' + str(i)): param for i, param in enumerate(params)} super().__init__( cells=cell, params=params, named_params_dict=named_params_dict, name=name, seq_length=seq_length, dynamic=dynamic, bidirectional=bidirectional )
class GRULayer(MakiLayer): def __init__(self, num_cells, input_dim, seq_length, name, activation=tf.nn.tanh, dynamic=False, bidirectional=False): """ Parameters ---------- num_cells : int Number of neurons in the layer. input_dim : int Dimensionality of the input vectors, e.t. number of features. Dimensionality example: [batch_size, seq_length, num_features(this is input_dim in this case)]. seq_length : int Max length of the input sequences. activation : tensorflow function Activation function of the layer. dynamic : boolean Influences whether the layer will be working as dynamic RNN or static. The difference between static and dynamic is that in case of static TensorFlow builds static graph and the RNN will always go through each time step in the sequence. In case of dynamic TensorFlow will be creating RNN `in a while loop`, that is to say that using dynamic RNN you can pass sequences of variable length, but you have to provide list of sequences' lengthes. Currently API for using dynamic RNNs is not provided. WARNING! THIS PARAMETER DOESN'T PLAY ANY ROLE IF YOU'RE GONNA STACK RNN LAYERS. bidirectional : boolean Influences whether the layer will be bidirectional. WARNING! THIS PARAMETER DOESN'T PLAY ANY ROLE IF YOU'RE GONNA STACK RNN LAYERS. """ self.name = str(name) self.num_cells = num_cells self.input_dim = input_dim self.seq_length = seq_length self.dynamic = dynamic self.bidirectional = bidirectional self.f = activation self.cells = GRUCell(num_units=num_cells, activation=activation, dtype=tf.float32) # Responsible for being RNN whether bidirectional or vanilla self.cell_type = CellType.get_cell_type(bidirectional, dynamic) self.cells.build(inputs_shape=[None, tf.Dimension(self.input_dim)]) self.params = self.cells.variables self.param_common_name = self.name + f'_{num_cells}_{input_dim}_{seq_length}' self.named_params_dict = {(self.param_common_name + '_' + str(i)): param for i, param in enumerate(self.params)} def forward(self, X, is_training=False): if self.cell_type == CellType.Bidir_Dynamic: return bidirectional_dynamic_rnn(cell_fw=self.cells, cell_bw=self.cells, inputs=X, dtype=tf.float32) elif self.cell_type == CellType.Bidir_Static: X = tf.unstack(X, num=self.seq_length, axis=1) return static_bidirectional_rnn(cell_fw=self.cells, cell_bw=self.cells, inputs=X, dtype=tf.float32) elif self.cell_type == CellType.Dynamic: return dynamic_rnn(self.cells, X, dtype=tf.float32) elif self.cell_type == CellType.Static: X = tf.unstack(X, num=self.seq_length, axis=1) return static_rnn(self.cells, X, dtype=tf.float32) def get_params(self): return self.params def get_params_dict(self): return self.named_params_dict def to_dict(self): return { 'type': 'GRULayer', 'params': { 'num_cells': self.num_cells, 'input_dim': self.input_dim, 'seq_length': self.seq_length, 'name': self.name, 'dynamic': self.dynamic, 'bidirectional': self.bidirectional, 'activation': ActivationConverter.activation_to_str(self.f) } }