def test_merging(self):
        """
        The problem is multivariate response, some mergers, with 2 hidden layers.
        
        Test that the predictions get good enough MSE.
        """

        #Generate some data
        p = 20
        q = 2
        n = 1000
        rng = np.random.RandomState(rng_seed)
        X, w, y = gen_data(rng=rng, n=n, p=p, q=q)

        #Get ann with mergers
        to_merge = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14],
                    [15, 16, 17, 18, 19]]
        ann = artificial_neural_net(in_size=p,
                                    out_size=q,
                                    h=2,
                                    h_size=4,
                                    eta=0.0001,
                                    to_merge=to_merge,
                                    lambda_l1=0,
                                    lambda_l2=0)

        self.assertTrue(np.shape(ann.layers[0].w.get_value())[0] == 4)

        for i in range(500):
            for g in range(q):
                #Get the current datum
                j = i % n
                x_i = np.reshape(X[j, :], [1, p])
                y_i = np.reshape(y[j, g], [1, 1])

                #Get the cost gradient
                ann.grad_on(x_i, y_i, g)

        #Split up some of merges
        ann.split(0)
        ann.split(1)
        ann.split(2)
        ann.split(3)

        self.assertTrue(np.shape(ann.layers[0].w.get_value())[0] == 20)

        for i in range(iters):
            for g in range(q):
                #Get the current datum
                j = i % n
                x_i = np.reshape(X[j, :], [1, p])
                y_i = np.reshape(y[j, g], [1, 1])

                #Get the cost gradient
                ann.grad_on(x_i, y_i, g)

        #See if we're close enough
        mse = np.mean(np.square(ann.predict(X) - y))
        self.assertGreater(thresh, mse)
    def test_linear_regression(self):
        """
        The problem is univariate response, no mergers, no hidden layers.
        
        Test that the estimated coefs are close enough to the truth
        """

        #Generate some data
        p = 20
        q = 1
        n = 1000
        rng = np.random.RandomState(rng_seed)
        X, w, y = gen_data(rng=rng, n=n, p=p, q=q)

        #Get ann
        ann = artificial_neural_net(in_size=p,
                                    out_size=q,
                                    h=0,
                                    h_size=0,
                                    eta=0.0001,
                                    lambda_l1=0,
                                    lambda_l2=0)

        #Do sgd
        for i in range(iters):
            #Get the current datum
            j = i % n
            x_i = np.reshape(X[j, :], [1, p])
            y_i = np.reshape(y[j, 0], [1, 1])

            #Get the cost gradient
            ann.grad_on(x_i, y_i, 0)

        #See if we're close enough
        self.assertGreater(
            thresh,
            np.linalg.norm(ann.layers[0].w.get_value() - w, np.float('inf')))
    def test_multiple_output_accuracy(self):
        """
        The problem is multivariate response, no mergers, with 2 hidden layers.
        
        Test that the predictions get good enough MSE.
        """

        #Generate some data
        p = 2
        q = 2
        n = 1000
        rng = np.random.RandomState(rng_seed)
        X, w, y = gen_data(rng=rng, n=n, p=p, q=q)

        #Get ann
        ann = artificial_neural_net(in_size=p,
                                    out_size=q,
                                    h=2,
                                    h_size=4,
                                    eta=0.0001,
                                    lambda_l1=0,
                                    lambda_l2=0)

        for i in range(iters):
            for g in range(q):
                #Get the current datum
                j = i % n
                x_i = np.reshape(X[j, :], [1, p])
                y_i = np.reshape(y[j, g], [1, 1])

                #Get the cost gradient
                ann.grad_on(x_i, y_i, g)

        #See if we're close enough
        mse = np.mean(np.square(ann.predict(X) - y))
        self.assertGreater(thresh, mse)
    def test_neural_net(self):
        """
        The problem is univariate response, no mergers, with 2 hidden layers.
        
        Test that our train MSE is small enough
        """

        #Generate some data
        p = 20
        q = 1
        n = 1000
        rng = np.random.RandomState(rng_seed)
        X, w, y = gen_data(rng=rng, n=n, p=p, q=q)

        #Get ann
        ann = artificial_neural_net(in_size=p,
                                    out_size=q,
                                    h=2,
                                    h_size=4,
                                    eta=0.0001,
                                    lambda_l1=0,
                                    lambda_l2=0)

        #Do sgd
        for i in range(iters):
            #Get the current datum
            j = i % n
            x_i = np.reshape(X[j, :], [1, p])
            y_i = np.reshape(y[j, 0], [1, 1])

            #Get the cost gradient
            ann.grad_on(x_i, y_i, 0)

        #See if we're close enough
        mse = np.mean(np.square(ann.predict(X) - y))
        self.assertGreater(thresh, mse)
    def __init__(self, state_size, action_size, eps_l = 0.1, eps_dyn = 0.9, \
        eps_decay = 100, h = 2, h_size = 4, eta = 0.0001, max_err = 10.0, to_merge = [], \
        M = 100, lambda_l1 = 0.1, lambda_l2 = 0.1, mem_size = 5000, replay_size = 100):
        """
        :type state_size: uint
        :param state_size: Dimensionality of the state space
        
        :type action_size: int
        :param action_size: How many actions to choose between?
        
        :type eps_l: float
        :param epsilon: asymptotic low value of epsilon for eps-greedy policy.
        
        :type eps_dyn: float
        :param eps_dyn: shrinking part of epsilon; goes to zero asymptotically
        
        :type eps_decay: float
        :param eps_decay: inverse decay rate for epsilon; smaller is faster decay.
        
        :type h: uint
        :param h: Number of hidden layers in neural net.
        
        :type h_size: uint
        :param h_size: Nodes per layer in hidden layers
        
        :type eta: float
        :param eta: Learning rate for sgd in neural net. If params are exploding, try reducing.
        
        :type max_err: float
        :param max_err: Maximum absolute gradient allowed in sgd. If params are exploding, try reducing.
        
        :type to_merge: list
        :param to_merge: List of lists, containing input dimensions to be confounded at first.
        
        :type M: int
        :param M: Every M updates, reclone the network.
        
        :type lambda_l1: float
        :param lambda_l1: nonneg coefficient for l1 regularization term
        
        :type lambda_l2: float
        :param lambda_l2: nonneg coefficient for l2 regularization term
        
        :type mem_size: int
        :param mem_size: How many memories to store for experience replay?
        
        :type replay_size: int
        :param replay_size: How many experience replays to do after each turn?
        """
        #Store the action space
        self.action_size = action_size

        #Store the clone iterations
        self.M = M

        #Set up epsilon
        self.epsilon_low = eps_l
        self.epsilon_dyn = eps_dyn
        self.exploration_decay = eps_decay
        self.epsilon = eps_l + eps_dyn

        #Create ANN
        rng = np.random.RandomState()
        self.ann = artificial_neural_net(state_size, self.action_size, h = h, \
            h_size = h_size, eta = eta, max_err = max_err, to_merge = to_merge, \
            rng = rng, lambda_l1 = lambda_l1, lambda_l2 = lambda_l2)

        #Clone (deep copy) ANN. Cloned network is used in building the target for sgd.
        self.ann_clone = self.ann.clone()

        #Initialize turn counter
        self.turn_counter = 0

        #Set to false if you want to set epsilon to zero.
        self.exploring = True

        #For experience replay
        self.memory = []
        self.mem_size = mem_size
        self.replay_size = replay_size
    def test_multiple_output_function(self):
        """
        The problem is multivariate response, no mergers, with no hidden layers.
        
        Test that only what should change does change.
        """

        #Generate some data
        p = 2
        q = 2
        n = 1000
        rng = np.random.RandomState(rng_seed)
        X, w, y = gen_data(rng=rng, n=n, p=p, q=q)

        #Get ann
        ann = artificial_neural_net(in_size=p,
                                    out_size=q,
                                    h=0,
                                    h_size=0,
                                    eta=0.0001,
                                    lambda_l1=0,
                                    lambda_l2=0)

        #Do sgd to learn the first response coefs, make sure it doesn't touch the second
        g = 0

        first_coefs_init = ann.layers[0].w.get_value()[:, 0]
        second_coefs_init = ann.layers[0].w.get_value()[:, 1]

        for i in range(500):
            #Get the current datum
            j = i % n
            x_i = np.reshape(X[j, :], [1, p])
            y_i = np.reshape(y[j, g], [1, 1])

            #Get the cost gradient
            ann.grad_on(x_i, y_i, g)

        #Make sure that the ones we sgd'd on changed and the others didn't.
        self.assertTrue(
            np.alltrue(first_coefs_init != ann.layers[0].w.get_value()[:, 0]))
        self.assertTrue(
            np.alltrue(second_coefs_init == ann.layers[0].w.get_value()[:, 1]))

        ## Same thing but for the other columns
        g = 1

        first_coefs_init = ann.layers[0].w.get_value()[:, 0]
        second_coefs_init = ann.layers[0].w.get_value()[:, 1]

        for i in range(500):
            #Get the current datum
            j = i % n
            x_i = np.reshape(X[j, :], [1, p])
            y_i = np.reshape(y[j, g], [1, 1])

            #Get the cost gradient
            ann.grad_on(x_i, y_i, g)

        #Make sure that the ones we sgd'd on changed and the others didn't.
        self.assertTrue(
            np.alltrue(first_coefs_init == ann.layers[0].w.get_value()[:, 0]))
        self.assertTrue(
            np.alltrue(second_coefs_init != ann.layers[0].w.get_value()[:, 1]))