def fit(self, X, Y):
        n = len(X)
        self.carts = []
        # the basic value of prediction, so that there can be 'residual'
        self.basic_pred = line_search(partial(self._loss_of_const, Y), min(Y),
                                      max(Y))

        cur_pred = np.zeros_like(Y) + self.basic_pred
        residual = -self.gradient_function(Y, cur_pred)
        for i in range(self.steps):
            if self.verbose:
                print(f'step {i}')
                print(f'Current pred is {cur_pred}')
                print(f'Current residual is {residual}')
            cart = RegressionCART(verbose=False, max_depth=self.max_depth)
            cart.fit(X, residual)
            self.carts.append(cart)
            # regression trees use l2 loss as loss function,
            # the return value leaf nodes should be recorrect
            leaf2label = defaultdict(list)
            for i, x in enumerate(X):
                leaf = cart._query_leaf(cart.root, x)
                leaf2label[leaf].append(i)
            for leaf in leaf2label:
                data_ind = np.stack(leaf2label[leaf])
                leafY = Y[data_ind]
                leaf_cur_pred = cur_pred[data_ind]
                leaf.label = line_search(
                    lambda c: self.loss_function(leafY, leaf_cur_pred + c),
                    -1e9, 1e9)

            # update the incremental prediction
            inc_pred = cart.predict(X)
            cur_pred += inc_pred
            residual = -self.gradient_function(Y, cur_pred)
    def _update_policy_network(self, state_batch_tensor, advantages, action_batch_tensor):
        action_mean_old, action_std_old = self.policy_network(state_batch_tensor)
        old_normal_dist = Normal(action_mean_old, action_std_old)
        # get the corresponding probability from the beta distribution...
        old_action_prob = old_normal_dist.log_prob(action_batch_tensor).sum(dim=1, keepdim=True)
        old_action_prob = old_action_prob.detach()
        action_mean_old = action_mean_old.detach()
        action_std_old = action_std_old.detach()
        # here will calculate the surrogate object
        surrogate_loss = self._get_surrogate_loss(state_batch_tensor, advantages, action_batch_tensor, old_action_prob)
        # compute the surrogate gradient -> g, Ax = g, where A is the Fisher Information Matrix...
        surrogate_grad = torch.autograd.grad(surrogate_loss, self.policy_network.parameters())
        flat_surrogate_grad = torch.cat([grad.view(-1) for grad in surrogate_grad]).data
        # use the conjugated gradient to calculate the scaled direction(natrual gradient)
        natural_grad = conjugated_gradient(self._fisher_vector_product, -flat_surrogate_grad, 10, \
                                            state_batch_tensor, action_mean_old, action_std_old)
        # calculate the scale ratio...
        non_scale_kl = 0.5 * (natural_grad * self._fisher_vector_product(natural_grad, state_batch_tensor, \
                                                            action_mean_old, action_std_old).sum(0, keepdim=True)) 
        scale_ratio = torch.sqrt(non_scale_kl / self.args.max_kl)
        final_natural_grad = natural_grad / scale_ratio[0]

        # calculate the expected improvement rate...
        expected_improvement = (-flat_surrogate_grad * natural_grad).sum(0, keepdim=True) / scale_ratio[0]
        # get the flat param ...
        prev_params = torch.cat([param.data.view(-1) for param in self.policy_network.parameters()])
        # start to do the line search..
        success, new_params = line_search(self.policy_network, self._get_surrogate_loss, prev_params, \
                                final_natural_grad, expected_improvement, state_batch_tensor, advantages, action_batch_tensor, old_action_prob)
        # set the params to the models...
        set_flat_params_to(self.policy_network, new_params)

        return surrogate_loss.item()
Ejemplo n.º 3
0
 def _update_network(self, mb_obs, mb_actions, mb_returns, mb_advs):
     mb_obs_tensor = torch.tensor(mb_obs, dtype=torch.float32)
     mb_actions_tensor = torch.tensor(mb_actions, dtype=torch.float32)
     mb_returns_tensor = torch.tensor(mb_returns,
                                      dtype=torch.float32).unsqueeze(1)
     mb_advs_tensor = torch.tensor(mb_advs,
                                   dtype=torch.float32).unsqueeze(1)
     # try to get the old policy and current policy
     values, _ = self.net(mb_obs_tensor)
     with torch.no_grad():
         _, pi_old = self.old_net(mb_obs_tensor)
     # get the surr loss
     surr_loss = self._get_surrogate_loss(mb_obs_tensor, mb_advs_tensor,
                                          mb_actions_tensor, pi_old)
     # comupte the surrogate gardient -> g, Ax = g, where A is the fisher information matrix
     surr_grad = torch.autograd.grad(surr_loss, self.net.actor.parameters())
     flat_surr_grad = torch.cat([grad.view(-1) for grad in surr_grad]).data
     # use the conjugated gradient to calculate the scaled direction vector (natural gradient)
     nature_grad = conjugated_gradient(self._fisher_vector_product,
                                       -flat_surr_grad, 10, mb_obs_tensor,
                                       pi_old)
     # calculate the scaleing ratio
     non_scale_kl = 0.5 * (nature_grad * self._fisher_vector_product(
         nature_grad, mb_obs_tensor, pi_old)).sum(0, keepdim=True)
     scale_ratio = torch.sqrt(non_scale_kl / self.args.max_kl)
     final_nature_grad = nature_grad / scale_ratio[0]
     # calculate the expected improvement rate...
     expected_improve = (-flat_surr_grad * nature_grad).sum(
         0, keepdim=True) / scale_ratio[0]
     # get the flat param ...
     prev_params = torch.cat(
         [param.data.view(-1) for param in self.net.actor.parameters()])
     # start to do the line search
     success, new_params = line_search(self.net.actor, self._get_surrogate_loss, prev_params, final_nature_grad, \
                             expected_improve, mb_obs_tensor, mb_advs_tensor, mb_actions_tensor, pi_old)
     set_flat_params_to(self.net.actor, new_params)
     # then trying to update the critic network
     inds = np.arange(mb_obs.shape[0])
     for _ in range(self.args.vf_itrs):
         np.random.shuffle(inds)
         for start in range(0, mb_obs.shape[0], self.args.batch_size):
             end = start + self.args.batch_size
             mbinds = inds[start:end]
             mini_obs = mb_obs[mbinds]
             mini_returns = mb_returns[mbinds]
             # put things in the tensor
             mini_obs = torch.tensor(mini_obs, dtype=torch.float32)
             mini_returns = torch.tensor(mini_returns,
                                         dtype=torch.float32).unsqueeze(1)
             values, _ = self.net(mini_obs)
             v_loss = (mini_returns - values).pow(2).mean()
             self.optimizer.zero_grad()
             v_loss.backward()
             self.optimizer.step()
     return surr_loss.item(), v_loss.item()
    def fit(self, p_data, feature):
        """
        optimize max entropy model with BFGS
        p_data: matrix of shape [nx, ny], possibility of all (x, y)
        feature: matrix of shape[nf, nx, ny], all the feature functions of all (x, y)
        """
        # nf is the number of feature functions, and the size of w
        self.nf, self.nx, self.ny = feature.shape
        self.feature = feature
        self.p_data = p_data
        self.p_data_x = p_data.sum(axis=-1)
        self.E_feature = (p_data[None, :, :] * feature).sum(axis=(1, 2))

        # initlaize optimizer
        self.w = np.random.rand(self.nf)
        B = np.eye(self.nf)
        g_next = self._g(self.w)
        g_norm = linalg.norm(g_next)
        # optimize
        for i in range(self.max_steps):
            g = g_next
            if self.verbose:
                print(f"Step {i}, L2 norm of gradient is {g_norm}")
            if g_norm < self.epsilon:
                break
            p = linalg.solve(B, -g)
            f_lambda = lambda x: self._f(self.w + x * p)
            lamda = line_search(f_lambda, 0, 100, epsilon=self.epsilon)
            delta_w = lamda * p
            self.w += delta_w
            g_next = self._g(self.w)
            g_norm = linalg.norm(g_next)
            if g_norm < self.epsilon:
                print(f"L2 norm of gradient is {g_norm}, stop training...")
                break
            delta_g = g_next - g
            B_delta_w = B @ delta_w
            B += np.outer(delta_g, delta_g) / (delta_g @ delta_w) - \
                np.outer(B_delta_w, B_delta_w) / (B_delta_w.T @ delta_w)
        self.p_w = self._p_w(self.w)
Ejemplo n.º 5
0
    def extract(self,
                budget,
                steps=[],
                adaptive_oracle=False,
                baseline=False,
                epsilon=1e-2,
                reg_lambda=1e-16,
                eps_factor=0.99,
                epoch=100,
                print_epoch=10,
                batch_size=1,
                num_passes=1000,
                random_seed=0):

        numpy.random.seed(random_seed)

        assert not (adaptive_oracle and steps)

        if steps:
            step = steps[0]
        else:
            step = budget

        if not adaptive_oracle:
            X_ext = utils.gen_query_set(self.num_features(), step)
        else:
            X_ext = utils.line_search_oracle(self.num_features(), step,
                                             self.query)

        model = None
        idx = 0
        while budget > 0:
            idx += 1
            budget -= step

            y_ext = self.query(X_ext)

            if not baseline:
                y_ext_p = self.query_probas(X_ext)
            else:
                num_classes = len(self.get_classes())
                y_ext_p = numpy.zeros((len(y_ext), num_classes))
                y_ext_p[numpy.arange(len(y_ext)), y_ext] = 1

            print y_ext_p

            print '{}'.format(-numpy.mean(y_ext_p * numpy.log(y_ext_p)))

            model = build_model(X_ext,
                                y_ext_p,
                                epsilon=epsilon,
                                reg_lambda=reg_lambda,
                                num_passes=num_passes,
                                eps_factor=eps_factor,
                                epoch=epoch,
                                print_epoch=print_epoch,
                                batch_size=batch_size,
                                warm_start=model)

            mtype = "base" if baseline else "extr"
            mode = "adapt-local" if steps \
                else "adapt-oracle" if adaptive_oracle \
                else "passive"
            save(
                model, 'experiments/inversion/{}/models/{}_{}_{}.pkl'.format(
                    self.dataset, mode, mtype, len(X_ext)))

            if budget > 0:
                step = steps[idx] - steps[idx - 1]
                X_local = utils.gen_query_set(n=X_repr.shape[1],
                                              test_size=1000)
                Y_local = predict(model, X_local)

                assert len(pd.Series(Y_local).unique()) != 1

                adaptive_budget = (min(step, budget) * 3) / 4
                adaptive_budget += adaptive_budget % 2
                random_budget = min(step, budget) - adaptive_budget

                predict_func = lambda x: predict(model, x)
                samples = utils.line_search(X_local, Y_local,
                                            adaptive_budget / 2, predict_func)
                X_random = utils.gen_query_set(X_ext.shape[1], random_budget)
                X_ext = numpy.vstack((samples, X_random, X_ext))
Ejemplo n.º 6
0
    def find_coeffs_adaptive(self, step, query_budget, baseline=False):
        """
        Extract the parameters, using adaptive learning - query
        the oracle with points nead the LOCAL decision boundary.
        :param step:
        :param query_budget:
        :param baseline:
        :return:
        """
        assert query_budget > 0
        k = len(self.classes)  # number of classes
        n = self.num_features()  # vector dimension

        X = self.gen_query_set(n, test_size=step)

        while query_budget > 0:
            query_budget -= step
            # print 'training with {} queries'.format(len(X))
            if baseline:
                model = self.baseline_model(X)
            else:
                Y = self.query_probas(X)
                w_opt, int_opt, _ = self.select_and_run_opti(k, n, X, Y)

            if baseline:
                predict_func = lambda x: model.predict(x)
                predict_func_p = lambda x: model.predict_proba(x)
            else:
                predict_func = lambda x: predict_classes(
                    x, w_opt, int_opt, self.get_classes())
                predict_func_p = lambda x: predict_probas(
                    x, w_opt, int_opt, self.multinomial)

            if query_budget > 0:
                X_local = self.gen_query_set(n, test_size=query_budget)
                Y_local = predict_func(X_local)

                if len(pd.Series(Y_local[0:100]).unique()) == 1 \
                        or callable(getattr(self, 'encode', None)):
                    # If we DO have an "encode" function
                    Y_local_p = predict_func_p(X_local)

                    if Y_local_p.ndim == 1 or Y_local_p.shape[1] == 1:
                        # Weird line:
                        # if Y_local_p.ndim == 1, then after hstack, Y_local_p is still one dimensional.
                        Y_local_p = np.hstack([1 - Y_local_p, Y_local_p])

                    # sort each column.
                    Y_local_p.sort()
                    # Second column - First column: how much we are certain about the prediction
                    scores = Y_local_p[:, -1] - Y_local_p[:, -2]

                    adaptive_budget = (min(step, query_budget) * 3) / 4
                    random_budget = min(step, query_budget) - adaptive_budget

                    # Take the indices of the lowest scores
                    indices = scores.argsort()[0:adaptive_budget]
                    # The rows with lowest scores.
                    samples = X_local[indices, :]
                    X_random = self.gen_query_set(n, random_budget)
                    samples = np.vstack((samples, X_random))
                else:
                    # If we DO NOT have an "encode" function
                    # reserve some budget for random queries
                    adaptive_budget = (min(step, query_budget) * 3) / 4
                    adaptive_budget += adaptive_budget % 2
                    random_budget = min(step, query_budget) - adaptive_budget
                    samples = utils.line_search(X_local[0:100], Y_local[0:100],
                                                adaptive_budget / 2,
                                                predict_func)
                    X_random = self.gen_query_set(n, random_budget)
                    samples = np.vstack((samples, X_random))

                assert len(samples) == min(step, query_budget)

                X = np.vstack((X, samples))

        if baseline:
            return model
        else:
            return w_opt, int_opt
Ejemplo n.º 7
0
    def train(self):

        start_time = time.time()

        self.episodes = self.env.generate_episodes(config.NUM_EPISODES, self)

        # Computing returns and estimating advantage function.
        for episode in self.episodes:
            episode["baseline"] = self.value_func.predict(episode)
            episode["returns"] = utils.discount(episode["rewards"],
                                                config.GAMMA)
            episode["advantage"] = episode["returns"] - episode["baseline"]

        # Updating policy.
        actions_dist_n = np.concatenate(
            [episode["actions_dist"] for episode in self.episodes])
        states_n = np.concatenate(
            [episode["states"] for episode in self.episodes])
        actions_n = np.concatenate(
            [episode["actions"] for episode in self.episodes])
        baseline_n = np.concatenate(
            [episode["baseline"] for episode in self.episodes])
        returns_n = np.concatenate(
            [episode["returns"] for episode in self.episodes])

        # Standardize the advantage function to have mean=0 and std=1.
        advantage_n = np.concatenate(
            [episode["advantage"] for episode in self.episodes])
        advantage_n -= advantage_n.mean()
        advantage_n /= (advantage_n.std() + 1e-8)

        # Computing baseline function for next iter.
        print(states_n.shape, actions_n.shape, advantage_n.shape,
              actions_dist_n.shape)
        feed = {
            self.policy.state: states_n,
            self.action: actions_n,
            self.advantage: advantage_n,
            self.policy.pi_theta_old: actions_dist_n
        }

        episoderewards = np.array(
            [episode["rewards"].sum() for episode in self.episodes])

        #print("\n********** Iteration %i ************" % i)

        self.value_func.fit(self.episodes)
        self.theta_old = self.current_theta()

        def fisher_vector_product(p):
            feed[self.flat_tangent] = p
            return self.session.run(self.fisher_vect_prod,
                                    feed) + config.CG_DAMP * p

        self.g = self.session.run(self.surr_loss_grad, feed_dict=feed)

        self.grad_step = utils.conjugate_gradient(fisher_vector_product,
                                                  -self.g)

        self.sAs = .5 * self.grad_step.dot(
            fisher_vector_product(self.grad_step))

        self.beta_inv = np.sqrt(self.sAs / config.MAX_KL)
        self.full_grad_step = self.grad_step / self.beta_inv

        self.negdot_grad_step = -self.g.dot(self.grad_step)

        def loss(th):
            self.set_theta(th)
            return self.session.run(self.surr_loss, feed_dict=feed)

        self.theta = utils.line_search(loss, self.theta_old,
                                       self.full_grad_step,
                                       self.negdot_grad_step / self.beta_inv)
        self.set_theta(self.theta)

        surr_loss_new = -self.session.run(self.surr_loss, feed_dict=feed)
        KL_old_new = self.session.run(self.KL, feed_dict=feed)
        entropy = self.session.run(self.entropy, feed_dict=feed)

        old_new_norm = np.sum((self.theta - self.theta_old)**2)

        if np.abs(KL_old_new) > 2.0 * config.MAX_KL:
            print("Keeping old theta")
            self.set_theta(self.theta_old)

        stats = {}
        stats["L2 of old - new"] = old_new_norm
        stats["Total number of episodes"] = len(self.episodes)
        stats["Average sum of rewards per episode"] = episoderewards.mean()
        stats["Entropy"] = entropy
        exp = utils.explained_variance(np.array(baseline_n),
                                       np.array(returns_n))
        stats["Baseline explained"] = exp
        stats["Time elapsed"] = "%.2f mins" % (
            (time.time() - start_time) / 60.0)
        stats["KL between old and new distribution"] = KL_old_new
        stats["Surrogate loss"] = surr_loss_new
        self.stats.append(stats)
        utils.write_dict(stats)
        save_path = self.saver.save(self.session, "./checkpoints/model.ckpt")
        print('Saved checkpoint to %s' % save_path)
        for k, v in stats.items():
            print(k + ": " + " " * (40 - len(k)) + str(v))
Ejemplo n.º 8
0
    def extract(self,
                X_train,
                y_train,
                num_repr,
                budget,
                steps=[],
                adaptive_oracle=False,
                use_labels_only=False,
                gamma=1,
                epsilon=1e-2,
                reg_lambda=1e-16,
                eps_factor=0.99,
                epoch=100,
                print_epoch=10,
                batch_size=1,
                num_passes=1000,
                random_seed=0):
        """
        Extracts a logistic regression multilabl classifier with RBF kernel
         for self.query
        :param X_train: For plotting
        :param y_train:  For plotting
        :param num_repr: amount of vectors in the kernel base.
        :param budget: total amount of queries to the oracle.
        :param steps: monotoincally increasing list of queries amounts.
        :param adaptive_oracle: whether to query the oracle using line search,
            or use only random inputs.
        :param use_labels_only: Whether to use only the labels in training.
        :param gamma: coefficient for the RBF kernel
        :param epsilon: initial learining rate.
        :param reg_lambda: regularization coefficient.
        :param eps_factor: update factor for the learning rate.
        Once in every epoch:
            learning_rate *= eps_factor
        :param epoch: how many iterations over the whole training data count as a n epoch.
        :param print_epoch:
        :param batch_size:
        :param num_passes: how many iterations over the whole data should we do in each training.
        :param random_seed:
        :return:
        """
        numpy.random.seed(random_seed)

        assert not (adaptive_oracle and steps)

        if steps:
            step = steps[0]
        else:
            step = budget

        if not adaptive_oracle:
            X_ext = utils.gen_query_set(self.num_features(), step)
        else:
            X_ext = utils.line_search_oracle(self.num_features(), step,
                                             self.query)

        X_repr = utils.gen_query_set(self.num_features(), num_repr)

        model = None
        idx = 0
        while budget > 0:
            idx += 1
            budget -= step

            y_ext = self.query(X_ext)

            if not use_labels_only:
                y_ext_p = self.query_probas(X_ext)
            else:
                # When this a baseline, take the labels from the query result
                # as one-hot vectors to be the probability vectors.
                num_classes = len(self.get_classes())
                y_ext_p = numpy.zeros((len(y_ext), num_classes))
                y_ext_p[numpy.arange(len(y_ext)), y_ext] = 1

            print y_ext_p

            print '{} ({})'.format(
                self.calculate_loss(X_ext, y_ext_p, reg_lambda),
                self.calculate_loss(X_ext, y_ext_p, 0))
            print >> sys.stderr, self.calculate_loss(X_ext, y_ext_p,
                                                     reg_lambda)

            model = build_model(X_repr,
                                False,
                                X_ext,
                                y_ext_p,
                                gamma=gamma,
                                epsilon=epsilon,
                                reg_lambda=reg_lambda,
                                num_passes=num_passes,
                                eps_factor=eps_factor,
                                epoch=epoch,
                                print_epoch=print_epoch,
                                batch_size=batch_size,
                                warm_start=model)

            mtype = "base" if use_labels_only else "extr"
            mode = "adapt-local" if steps \
                else "adapt-oracle" if adaptive_oracle \
                else "passive"
            save(
                model, 'experiments/KLR/{}/models/{}_{}_{}.pkl'.format(
                    self.dataset, mode, mtype, len(X_ext)))

            if X_train is not None and X_train.shape[1] == 2:
                bounds = [-1.1, 1.1, -1.1, 1.1]
                filename = 'experiments/KLR/{}/plots/{}_{}_{}_{}_boundary'.\
                    format(self.dataset, mode, mtype, len(X_ext), random_seed)
                utils.plot_decision_boundary(lambda x: predict(model, x),
                                             X_train.values, y_train, bounds,
                                             filename)

                filename = 'experiments/KLR/{}/plots/{}_{}_{}_{}_boundary_ext'.\
                    format(self.dataset, mode, mtype, len(X_ext), random_seed)
                utils.plot_decision_boundary(lambda x: predict(model, x),
                                             X_ext, y_ext, bounds, filename)

            if budget > 0:
                step = steps[idx] - steps[idx - 1]
                X_local = utils.gen_query_set(n=X_repr.shape[1],
                                              test_size=1000)
                Y_local = predict(model, X_local)

                assert len(pd.Series(Y_local).unique()) != 1

                adaptive_budget = (min(step, budget) * 3) / 4
                adaptive_budget += adaptive_budget % 2
                random_budget = min(step, budget) - adaptive_budget

                predict_func = lambda x: predict(model, x)
                samples = utils.line_search(X_local, Y_local,
                                            adaptive_budget / 2, predict_func)
                X_random = utils.gen_query_set(X_ext.shape[1], random_budget)
                X_ext = numpy.vstack((samples, X_random, X_ext))
    def extract(self,
                X_train,
                y_train,
                num_repr,
                budget,
                steps=[],
                adaptive_oracle=False,
                baseline=False,
                gamma=1,
                epsilon=1e-2,
                reg_lambda=1e-16,
                eps_factor=0.99,
                epoch=100,
                print_epoch=10,
                batch_size=1,
                num_passes=1000,
                random_seed=0):

        numpy.random.seed(random_seed)

        assert not (adaptive_oracle and steps)

        if steps:
            step = steps[0]
        else:
            step = budget

        if not adaptive_oracle:
            X_ext = utils.gen_query_set(self.num_features(), step)
        else:
            X_ext = utils.line_search_oracle(self.num_features(), step,
                                             self.query)

        X_repr = utils.gen_query_set(self.num_features(), num_repr)

        model = None
        idx = 0
        while budget > 0:
            idx += 1
            budget -= step

            y_ext = self.query(X_ext)

            if not baseline:
                y_ext_p = self.query_probas(X_ext)
            else:
                num_classes = len(self.get_classes())
                y_ext_p = numpy.zeros((len(y_ext), num_classes))
                y_ext_p[numpy.arange(len(y_ext)), y_ext] = 1

            print y_ext_p

            print '{} ({})'.format(
                self.calculate_loss(X_ext, y_ext_p, reg_lambda),
                self.calculate_loss(X_ext, y_ext_p, 0))
            print >> sys.stderr, self.calculate_loss(X_ext, y_ext_p,
                                                     reg_lambda)

            model = build_model(X_repr,
                                False,
                                X_ext,
                                y_ext_p,
                                gamma=gamma,
                                epsilon=epsilon,
                                reg_lambda=reg_lambda,
                                num_passes=num_passes,
                                eps_factor=eps_factor,
                                epoch=epoch,
                                print_epoch=print_epoch,
                                batch_size=batch_size,
                                warm_start=model)

            mtype = "base" if baseline else "extr"
            mode = "adapt-local" if steps \
                else "adapt-oracle" if adaptive_oracle \
                else "passive"
            save(
                model, 'experiments/KLR/{}/models/{}_{}_{}.pkl'.format(
                    self.dataset, mode, mtype, len(X_ext)))

            if X_train is not None and X_train.shape[1] == 2:
                bounds = [-1.1, 1.1, -1.1, 1.1]
                filename = 'experiments/KLR/{}/plots/{}_{}_{}_{}_boundary'.\
                    format(self.dataset, mode, mtype, len(X_ext), random_seed)
                utils.plot_decision_boundary(lambda x: predict(model, x),
                                             X_train.values, y_train, bounds,
                                             filename)

                filename = 'experiments/KLR/{}/plots/{}_{}_{}_{}_boundary_ext'.\
                    format(self.dataset, mode, mtype, len(X_ext), random_seed)
                utils.plot_decision_boundary(lambda x: predict(model, x),
                                             X_ext, y_ext, bounds, filename)

            if budget > 0:
                step = steps[idx] - steps[idx - 1]
                X_local = utils.gen_query_set(n=X_repr.shape[1],
                                              test_size=1000)
                Y_local = predict(model, X_local)

                assert len(pd.Series(Y_local).unique()) != 1

                adaptive_budget = (min(step, budget) * 3) / 4
                adaptive_budget += adaptive_budget % 2
                random_budget = min(step, budget) - adaptive_budget

                predict_func = lambda x: predict(model, x)
                samples = utils.line_search(X_local, Y_local,
                                            adaptive_budget / 2, predict_func)
                X_random = utils.gen_query_set(X_ext.shape[1], random_budget)
                X_ext = numpy.vstack((samples, X_random, X_ext))
Ejemplo n.º 10
0
    def extract(self, X_train, y_train, budget, steps=[],
                adaptive_oracle=False, baseline=False, epsilon=1e-1,
                num_passes=1000, reg_lambda=1e-8, eps_factor=0.99, epoch=100,
                print_loss=True, print_epoch=10, batch_size=20, random_seed=0):

        numpy.random.seed(random_seed)

        assert not (adaptive_oracle and steps)

        if steps:
            step = steps[0]
        else:
            step = budget

        if not adaptive_oracle:
            X_ext = utils.gen_query_set(X_train.shape[1], step)
        else:
            X_ext = utils.line_search_oracle(X_train.shape[1], step, self.query)

        idx = 0
        while budget > 0:
            idx += 1
            budget -= step

            y_ext = self.query(X_ext)

            if not baseline:
                y_ext_p = self.query_probas(X_ext)
            else:
                num_classes = len(self.get_classes())
                y_ext_p = numpy.zeros((len(y_ext), num_classes))
                y_ext_p[numpy.arange(len(y_ext)), y_ext] = 1

            # Loss with correct parameters:
            print self.calculate_loss(X_ext, y_ext_p, reg_lambda)
            print >> sys.stderr, self.calculate_loss(X_ext, y_ext_p, reg_lambda)

            model = build_model(self.hidden_nodes, X_ext, y_ext_p,
                                epsilon=epsilon, num_passes=num_passes,
                                reg_lambda=reg_lambda, epoch=epoch,
                                eps_factor=eps_factor, print_loss=print_loss,
                                print_epoch=print_epoch, batch_size=batch_size)

            m_type = "base" if baseline else "extr"
            mode = "adapt-local" if steps \
                else "adapt-oracle" if adaptive_oracle \
                else "passive"

            save(model, 'experiments/{}/models/{}_{}_{}_{}_{}.pkl'.
                 format(self.dataset, mode, m_type,
                        self.hidden_nodes, len(X_ext), random_seed))

            if X_train is not None and X_train.shape[1] == 2:
                bounds = [-1.1, 1.1, -1.1, 1.1]
                filename = 'experiments/{}/plots/{}_{}_{}_{}_{}_boundary'.\
                    format(self.dataset, mode, m_type,
                           self.hidden_nodes, len(X_ext), random_seed)
                utils.plot_decision_boundary(lambda x: predict(model, x),
                                             X_train.values, y_train,
                                             bounds, filename)

                filename = 'experiments/{}/plots/{}_{}_{}_{}_{}_boundary_ext'.\
                    format(self.dataset, mode, m_type,
                           self.hidden_nodes, len(X_ext), random_seed)
                utils.plot_decision_boundary(lambda x: predict(model, x),
                                             X_ext, y_ext, bounds, filename)

            if budget > 0:
                step = steps[idx] - steps[idx-1]
                X_local = utils.gen_query_set(n=X_ext.shape[1], test_size=1000)
                Y_local = predict(model, X_local)

                assert len(pd.Series(Y_local).unique()) != 1

                adaptive_budget = (min(step, budget)*3)/4
                adaptive_budget += adaptive_budget % 2
                random_budget = min(step, budget) - adaptive_budget

                predict_func = lambda x: predict(model, x)
                samples = utils.line_search(X_local, Y_local, adaptive_budget/2,
                                            predict_func)
                X_random = utils.gen_query_set(X_ext.shape[1], random_budget)
                X_ext = numpy.vstack((samples, X_random, X_ext))
from utils import line_search


class F:
    def __init__(self, n):
        self.n = n

    def __call__(self, x):
        return (x - self.n)**2


f = F(0)
epsilon = 1e-6
for i in range(-1000, 1000):
    f.n = i
    assert (abs(line_search(f, -2000, 2000, epsilon) - i) <= epsilon)
Ejemplo n.º 12
0
    def find_coeffs_adaptive(self, step, query_budget, baseline=False):
        assert query_budget > 0
        k = len(self.classes)  # number of classes
        n = self.num_features()  # vector dimension

        X = self.gen_query_set(n, test_size=step)

        while query_budget > 0:
            query_budget -= step
            # print 'training with {} queries'.format(len(X))
            if baseline:
                model = self.baseline_model(X)
            else:
                Y = self.query_probas(X)
                w_opt, int_opt, _ = self.select_and_run_opti(k, n, X, Y)

            if baseline:
                predict_func = lambda x: model.predict(x)
                predict_func_p = lambda x: model.predict_proba(x)
            else:
                predict_func = lambda x: predict_classes(
                    x, w_opt, int_opt, self.get_classes())
                predict_func_p = lambda x: predict_probas(
                    x, w_opt, int_opt, self.multinomial)

            if query_budget > 0:
                X_local = self.gen_query_set(n, test_size=query_budget)
                Y_local = predict_func(X_local)

                if len(pd.Series(Y_local[0:100]).unique()) == 1 \
                        or callable(getattr(self, 'encode', None)):
                    Y_local_p = predict_func_p(X_local)

                    if Y_local_p.ndim == 1 or Y_local_p.shape[1] == 1:
                        Y_local_p = np.hstack([1 - Y_local_p, Y_local_p])

                    Y_local_p.sort()
                    scores = Y_local_p[:, -1] - Y_local_p[:, -2]

                    adaptive_budget = (min(step, query_budget) * 3) / 4
                    random_budget = min(step, query_budget) - adaptive_budget

                    indices = scores.argsort()[0:adaptive_budget]
                    samples = X_local[indices, :]
                    X_random = self.gen_query_set(n, random_budget)
                    samples = np.vstack((samples, X_random))
                else:
                    # reserve some budget for random queries
                    adaptive_budget = (min(step, query_budget) * 3) / 4
                    adaptive_budget += adaptive_budget % 2
                    random_budget = min(step, query_budget) - adaptive_budget
                    samples = utils.line_search(X_local[0:100], Y_local[0:100],
                                                adaptive_budget / 2,
                                                predict_func)
                    X_random = self.gen_query_set(n, random_budget)
                    samples = np.vstack((samples, X_random))

                assert len(samples) == min(step, query_budget)

                X = np.vstack((X, samples))

        if baseline:
            return model
        else:
            return w_opt, int_opt