Advertisement
nordlaender

CGRU

Nov 3rd, 2016
465
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.56 KB | None | 0 0
  1. import numpy as np
  2. from keras import backend as K
  3. from keras import initializations, activations
  4. from keras.engine import InputSpec
  5. from keras.layers.recurrent import Recurrent
  6.  
  7.  
  8. # copied from the keras github source. removed lots of unnecessary (for me) code
  9.  
  10. # assuming a 2D Convolution was run by hand before this layer.
  11. # please note that this has no variables of its own.
  12. # TODO: incorporate the 2D Convolution into this layer
  13.  
  14. class CGRU(Recurrent):
  15.     def __init__(self,
  16.                  init='glorot_uniform', inner_init='orthogonal',
  17.                  activation='tanh', inner_activation='hard_sigmoid', **kwargs):
  18.  
  19.         self.init = initializations.get(init)
  20.         self.inner_init = initializations.get(inner_init)
  21.         self.activation = activations.get(activation)
  22.         self.inner_activation = activations.get(inner_activation)
  23.  
  24.         # removing the regularizers and the dropout
  25.  
  26.         super(CGRU, self).__init__(**kwargs)
  27.  
  28.         # TODO: it's not very elegant to just overwrite this. Maybe there is a better way ?
  29.         # this seems necessary in order to accept 5 input dimensions
  30.         # (samples, timesteps, features, x, y)
  31.         self.input_spec = [InputSpec(ndim=5)]
  32.  
  33.     def build(self, input_shape):
  34.         self.input_spec = [InputSpec(shape=input_shape)]
  35.         self.input_dim = (3, input_shape[2], input_shape[3])
  36.  
  37.         # moved here from the constructor. The layer does not change the input dimension
  38.         # it does change the number of features: 3 features are used for 3 gates, there is one output
  39.         self.output_dim = [1, input_shape[2], input_shape[3]]
  40.  
  41.         if self.stateful:
  42.             self.reset_states()
  43.         else:
  44.             # initial states: all-zero tensor of shape (output_dim)
  45.             self.states = [None]
  46.  
  47.     def reset_states(self):
  48.         # TODO: the state must become 2D. am I doing this right ?
  49.         # TODO: assuming that the first dimension is batch_size, I'm now hardcoding for 2D images and th layout
  50.         assert self.stateful, 'Layer must be stateful.'
  51.  
  52.         input_shape = self.input_spec[0].shape
  53.         if not input_shape[0]:
  54.             raise Exception('If a RNN is stateful, a complete ' +
  55.                             'input_shape must be provided (including batch size).')
  56.         if hasattr(self, 'states'):
  57.             K.set_value(self.states[0],
  58.                         np.zeros((input_shape[0], self.input_shape[2], self.input_shape[3])))
  59.         else:
  60.             self.states = [K.zeros((input_shape[0], self.input_shape[2], self.input_shape[3]))]
  61.  
  62.     def preprocess_input(self, x):
  63.         # here was a distinction between cpu and gpu. for starters I'll just use the gpu code
  64.         return x
  65.  
  66.     def step(self, x, states):
  67.         h_tm1 = states[0]  # previous memory
  68.         # the original code produces z, r, and hh.
  69.         # I would like to use the values produced by the convolution instead
  70.         # just drop all of the code above and slice the input
  71.  
  72.         # TODO: the three features per coordinate are a hard requirement. How can I enforce this ?
  73.  
  74.         z = self.inner_activation(x[:, 0, :, :])
  75.         r = self.inner_activation(x[:, 1, :, :])
  76.         hh = self.activation(x[:, 2, :, :])
  77.  
  78.         h = z * h_tm1 + (1 - z) * hh
  79.         return h, [h]
  80.  
  81.     def get_constants(self, x):
  82.         constants = []
  83.  
  84.         # TODO: this is copied from the GRU. I've no idea what exactly it does.
  85.         constants.append([K.cast_to_floatx(1.) for _ in range(3)])
  86.         constants.append([K.cast_to_floatx(1.) for _ in range(3)])
  87.         return constants
  88.  
  89.     def get_initial_states(self, x):
  90.         initial_state = K.zeros_like(x)  # (samples, timesteps, input_dim) where input_dim = (3, x_dim, y_dim)
  91.         initial_state = K.sum(initial_state, axis=(1, 2))  # (samples, x_dim, y_dim)
  92.         return [initial_state]
  93.  
  94.     def get_output_shape_for(self, input_shape):
  95.         # TODO: this is hardcoding for th layout
  96.         return (input_shape[0], input_shape[1], 1, input_shape[3], input_shape[4])
  97.  
  98.     def get_config(self):
  99.         config = {'output_dim': self.output_dim,
  100.                   'init': self.init.__name__,
  101.                   'inner_init': self.inner_init.__name__,
  102.                   'activation': self.activation.__name__,
  103.                   'inner_activation': self.inner_activation.__name__}
  104.  
  105.         # removed the various regularizers and dropouts.
  106.         # surely this isn't needed if not present ?
  107.         base_config = super(CGRU, self).get_config()
  108.         return dict(list(base_config.items()) + list(config.items()))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement