':type rng: numpy random generator
:param rng: numpy random generator used to sample weights
:type n_in: int
:param n_in: number of input units
:type n_out: int
:param n_out: number of output units
: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 rank_n_approx: int
:param rank_n_approx: It applies to the first layer only. If
positive and larger than 0, the first weight matrix is
factorized into two matrices. The first one goes from input to
`rank_n_approx` hidden units, the second from `rank_n_approx` to
the number of units on the second layer
:type rank_n_activ: string or function
:param rank_n_activ: Function that is applied on on the intermediary
layer formed from factorizing the first weight matrix (Q: do we
need this?)
: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 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 sum_over_time: bool
:param sum_over_time: flag, stating if, when computing the cost, we
should take the sum over time, or the mean. If you have variable
length sequences, please take the sum over time
:type additional_inputs: None or list of ints
:param additional_inputs: dimensionality of each additional input
: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_in, n_out, scale, sparsity, rank_n_approx=0, rank_n_activ='lambda    x:    x', weight_noise=False, init_fn='sample_weights_classic', bias_fn='init_bias', bias_scale=0.0, sum_over_time=True, additional_inputs=None, grad_scale=1.0, name=None):

    self.grad_scale = grad_scale
    assert (rank_n_approx >= 0), 'Please    enter    a    valid    rank_n_approx'
    self.rank_n_approx = rank_n_approx
    if (type(rank_n_activ) is str):
        rank_n_activ = eval(rank_n_activ)
    self.rank_n_activ = rank_n_activ
    super(CostLayer, self).__init__(n_in, n_out, rng, name)
    self.trng = RandomStreams(self.rng.randint(int(1000000.0)))
    self.scale = scale
    if isinstance(bias_fn, str):
        self.bias_fn = eval(bias_fn)
    else:
        self.bias_fn = bias_fn
    self.bias_scale = bias_scale
    self.sum_over_time = sum_over_time
    self.weight_noise = weight_noise
    self.sparsity = sparsity
    if (self.sparsity < 0):
        self.sparsity = n_out
    if (type(init_fn) is str):
        init_fn = eval(init_fn)
    self.init_fn = init_fn
    self.additional_inputs = additional_inputs
    self._init_params()
