':type rng: numpy random generator
:param rng: numpy random generator
:type n_in: int
:param n_in: number of inputs units
:type n_hids: list of ints
:param n_hids: Number of hidden units on each layer of the MLP
:type activation: string/function or list of
:param activation: Activation function for the embedding layers. If
a list it needs to have a value for each layer. If not, the same
activation will be applied to all layers
:type scale: float or list of
:param scale: depending on the initialization function, it can be
the standard deviation of the Gaussian from which the weights
are sampled or the largest singular value. If a single value it
will be used for each layer, otherwise it has to have one value
for each layer
:type sparsity: int or list of
:param sparsity: if a single value, it will be used for each layer,
otherwise it has to be a list with as many values as layers. If
negative, it means the weight matrix is dense. Otherwise it
means this many randomly selected input units are connected to
an output unit
:type weight_noise: bool
:param weight_noise: If true, the model is used with weight noise
(and the right shared variable are constructed, to keep track of the
noise)
:type dropout: float
:param dropout: the probability with which hidden units are dropped
from the hidden layer. If set to 1, dropout is not used
:type init_fn: string or function
:param init_fn: function used to initialize the weights of the
layer. We recommend using either `sample_weights_classic` or
`sample_weights` defined in the utils
:type bias_fn: string or function
:param bias_fn: function used to initialize the biases. We recommend
using `init_bias` defined in the utils
:type bias_scale: float
:param bias_scale: argument passed to `bias_fn`, depicting the scale
of the initial bias
:type grad_scale: float or theano scalar
:param grad_scale: factor with which the gradients with respect to
the parameters of this layer are scaled. It is used for
differentiating between the different parameters of a model.
:type name: string
:param name: name of the layer (used to name parameters). NB: in
this library names are very important because certain parts of the
code relies on name to disambiguate between variables, therefore
each layer should have a unique name.'

def __init__(self, rng, n_hids=[500, 500], activation=[TT.tanh, TT.tanh], scale=0.01, sparsity=(-1), activ_noise=0.0, weight_noise=False, dropout=1.0, init_fn='sample_weights', bias_fn='init_bias', bias_scale=0.0, grad_scale=1.0, profile=0, name=None):

    self.grad_scale = grad_scale
    if (type(n_hids) not in (list, tuple)):
        n_hids = [n_hids]
    n_layers = len(n_hids)
    if (type(scale) not in (list, tuple)):
        scale = ([scale] * n_layers)
    if (type(sparsity) not in (list, tuple)):
        sparsity = ([sparsity] * n_layers)
    for (idx, sp) in enumerate(sparsity):
        if (sp < 0):
            sparsity[idx] = n_hids[idx]
    if (type(activation) not in (list, tuple)):
        activation = ([activation] * n_layers)
    if (type(bias_scale) not in (list, tuple)):
        bias_scale = ([bias_scale] * (n_layers - 1))
    if (type(bias_fn) not in (list, tuple)):
        bias_fn = ([bias_fn] * (n_layers - 1))
    if (type(init_fn) not in (list, tuple)):
        init_fn = ([init_fn] * n_layers)
    for dx in xrange(n_layers):
        if (dx < (n_layers - 1)):
            if ((type(bias_fn[dx]) is str) or (type(bias_fn[dx]) is unicode)):
                bias_fn[dx] = eval(bias_fn[dx])
        if ((type(init_fn[dx]) is str) or (type(init_fn[dx]) is unicode)):
            init_fn[dx] = eval(init_fn[dx])
        if ((type(activation[dx]) is str) or (type(activation[dx]) is unicode)):
            activation[dx] = eval(activation[dx])
    self.scale = scale
    self.n_layers = n_layers
    self.sparsity = sparsity
    self.activation = activation
    self.n_hids = n_hids
    self.bias_scale = bias_scale
    self.bias_fn = bias_fn
    self.init_fn = init_fn
    self.weight_noise = weight_noise
    self.activ_noise = activ_noise
    self.profile = profile
    self.dropout = dropout
    assert (rng is not None), 'random    number    generator    should    not    be    empty!'
    super(RecurrentMultiLayer, self).__init__(n_hids[0], n_hids[(-1)], rng, name)
    self.trng = RandomStreams(self.rng.randint(int(1000000.0)))
    self.params = []
    self._init_params()
