# Path: mla/neuralnet/activations.py
# def get_activation(name):
#     """Return activation function by name"""
#     try:
#         return globals()[name]
#     except Exception:
#         raise ValueError("Invalid activation function.")
# 
# Path: mla/neuralnet/parameters.py
# class Parameters(object):
#     def __init__(self, init="glorot_uniform", scale=0.5, bias=1.0, regularizers=None, constraints=None):
#         """A container for layer's parameters.
# 
#         Parameters
#         ----------
#         init : str, default 'glorot_uniform'.
#             The name of the weight initialization function.
#         scale : float, default 0.5
#         bias : float, default 1.0
#             Initial values for bias.
#         regularizers : dict
#             Weight regularizers.
#             >>> {'W' : L2()}
#         constraints : dict
#             Weight constraints.
#             >>> {'b' : MaxNorm()}
#         """
#         if constraints is None:
#             self.constraints = {}
#         else:
#             self.constraints = constraints
# 
#         if regularizers is None:
#             self.regularizers = {}
#         else:
#             self.regularizers = regularizers
# 
#         self.initial_bias = bias
#         self.scale = scale
#         self.init = get_initializer(init)
# 
#         self._params = {}
#         self._grads = {}
# 
#     def setup_weights(self, W_shape, b_shape=None):
#         if "W" not in self._params:
#             self._params["W"] = self.init(shape=W_shape, scale=self.scale)
#             if b_shape is None:
#                 self._params["b"] = np.full(W_shape[1], self.initial_bias)
#             else:
#                 self._params["b"] = np.full(b_shape, self.initial_bias)
#         self.init_grad()
# 
#     def init_grad(self):
#         """Init gradient arrays corresponding to each weight array."""
#         for key in self._params.keys():
#             if key not in self._grads:
#                 self._grads[key] = np.zeros_like(self._params[key])
# 
#     def step(self, name, step):
#         """Increase specific weight by amount of the step parameter."""
#         self._params[name] += step
# 
#         if name in self.constraints:
#             self._params[name] = self.constraints[name].clip(self._params[name])
# 
#     def update_grad(self, name, value):
#         """Update gradient values."""
#         self._grads[name] = value
# 
#         if name in self.regularizers:
#             self._grads[name] += self.regularizers[name](self._params[name])
# 
#     @property
#     def n_params(self):
#         """Count the number of parameters in this layer."""
#         return sum([np.prod(self._params[x].shape) for x in self._params.keys()])
# 
#     def keys(self):
#         return self._params.keys()
# 
#     @property
#     def grad(self):
#         return self._grads
# 
#     # Allow access to the fields using dict syntax, e.g. parameters['W']
#     def __getitem__(self, item):
#         if item in self._params:
#             return self._params[item]
#         else:
#             raise ValueError
# 
#     def __setitem__(self, key, value):
#         self._params[key] = value


import autograd.numpy as np
from autograd import elementwise_grad
from mla.neuralnet.activations import get_activation
from mla.neuralnet.parameters import Parameters
    @property
    def is_training(self):
        return self._train

    @is_training.setter
    def is_training(self, is_train=True):
        self._train = is_train

    @property
    def is_testing(self):
        return not self._train

    @is_testing.setter
    def is_testing(self, is_test=True):
        self._train = not is_test


class Dense(Layer, ParamMixin):
    def __init__(self, output_dim, parameters=None):
        """A fully connected layer.

        Parameters
        ----------
        output_dim : int
        """
        self._params = parameters
        self.output_dim = output_dim
        self.last_input = None

        if parameters is None:

# Path: mla/neuralnet/activations.py
# def get_activation(name):
#     """Return activation function by name"""
#     try:
#         return globals()[name]
#     except Exception:
#         raise ValueError("Invalid activation function.")
# 
# Path: mla/neuralnet/parameters.py
# class Parameters(object):
#     def __init__(self, init="glorot_uniform", scale=0.5, bias=1.0, regularizers=None, constraints=None):
#         """A container for layer's parameters.
# 
#         Parameters
#         ----------
#         init : str, default 'glorot_uniform'.
#             The name of the weight initialization function.
#         scale : float, default 0.5
#         bias : float, default 1.0
#             Initial values for bias.
#         regularizers : dict
#             Weight regularizers.
#             >>> {'W' : L2()}
#         constraints : dict
#             Weight constraints.
#             >>> {'b' : MaxNorm()}
#         """
#         if constraints is None:
#             self.constraints = {}
#         else:
#             self.constraints = constraints
# 
#         if regularizers is None:
#             self.regularizers = {}
#         else:
#             self.regularizers = regularizers
# 
#         self.initial_bias = bias
#         self.scale = scale
#         self.init = get_initializer(init)
# 
#         self._params = {}
#         self._grads = {}
# 
#     def setup_weights(self, W_shape, b_shape=None):
#         if "W" not in self._params:
#             self._params["W"] = self.init(shape=W_shape, scale=self.scale)
#             if b_shape is None:
#                 self._params["b"] = np.full(W_shape[1], self.initial_bias)
#             else:
#                 self._params["b"] = np.full(b_shape, self.initial_bias)
#         self.init_grad()
# 
#     def init_grad(self):
#         """Init gradient arrays corresponding to each weight array."""
#         for key in self._params.keys():
#             if key not in self._grads:
#                 self._grads[key] = np.zeros_like(self._params[key])
# 
#     def step(self, name, step):
#         """Increase specific weight by amount of the step parameter."""
#         self._params[name] += step
# 
#         if name in self.constraints:
#             self._params[name] = self.constraints[name].clip(self._params[name])
# 
#     def update_grad(self, name, value):
#         """Update gradient values."""
#         self._grads[name] = value
# 
#         if name in self.regularizers:
#             self._grads[name] += self.regularizers[name](self._params[name])
# 
#     @property
#     def n_params(self):
#         """Count the number of parameters in this layer."""
#         return sum([np.prod(self._params[x].shape) for x in self._params.keys()])
# 
#     def keys(self):
#         return self._params.keys()
# 
#     @property
#     def grad(self):
#         return self._grads
# 
#     # Allow access to the fields using dict syntax, e.g. parameters['W']
#     def __getitem__(self, item):
#         if item in self._params:
#             return self._params[item]
#         else:
#             raise ValueError
# 
#     def __setitem__(self, key, value):
#         self._params[key] = value


# Path: mla/neuralnet/layers/basic.py
import autograd.numpy as np
from autograd import elementwise_grad
from mla.neuralnet.activations import get_activation
from mla.neuralnet.parameters import Parameters

    @property
    def is_training(self):
        return self._train

    @is_training.setter
    def is_training(self, is_train=True):
        self._train = is_train

    @property
    def is_testing(self):
        return not self._train

    @is_testing.setter
    def is_testing(self, is_test=True):
        self._train = not is_test


class Dense(Layer, ParamMixin):
    def __init__(self, output_dim, parameters=None):
        """A fully connected layer.

        Parameters
        ----------
        output_dim : int
        """
        self._params = parameters
        self.output_dim = output_dim
        self.last_input = None

        if parameters is None:

            self._params = Parameters()