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()
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)
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))
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
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))
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))
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)
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