def testTorchModelPredict(self): torch_model = TorchModel() with self.assertRaises(NotImplementedError): torch_model.predict(np.array([0]))
def pareto_frontier_evaluator( model: TorchModel, objective_weights: Tensor, objective_thresholds: Optional[Tensor] = None, X: Optional[Tensor] = None, Y: Optional[Tensor] = None, Yvar: Optional[Tensor] = None, outcome_constraints: Optional[Tuple[Tensor, Tensor]] = None, ) -> Tuple[Tensor, Tensor, Tensor]: """Return outcomes predicted to lie on a pareto frontier. Given a model and a points to evaluate use the model to predict which points lie on the pareto frontier. Args: model: Model used to predict outcomes. objective_weights: A `m` tensor of values indicating the weight to put on different outcomes. For pareto frontiers only the sign matters. objective_thresholds: A tensor containing thresholds forming a reference point from which to calculate pareto frontier hypervolume. Points that do not dominate the objective_thresholds contribute nothing to hypervolume. X: A `n x d` tensor of features to evaluate. Y: A `n x m` tensor of outcomes to use instead of predictions. Yvar: A `n x m x m` tensor of input covariances (NaN if unobserved). outcome_constraints: A tuple of (A, b). For k outcome constraints and m outputs at f(x), A is (k x m) and b is (k x 1) such that A f(x) <= b. Returns: 3-element tuple containing - A `j x m` tensor of outcome on the pareto frontier. j is the number of frontier points. - A `j x m x m` tensor of predictive covariances. cov[j, m1, m2] is Cov[m1@j, m2@j]. - A `j` tensor of the index of each frontier point in the input Y. """ if X is not None: Y, Yvar = model.predict(X) elif Y is None or Yvar is None: raise ValueError( "Requires `X` to predict or both `Y` and `Yvar` to select a subset of " "points on the pareto frontier.") # Apply objective_weights to outcomes and objective_thresholds. # If objective_thresholds is not None use a dummy tensor of zeros. ( obj, weighted_objective_thresholds, ) = get_weighted_mc_objective_and_objective_thresholds( objective_weights=objective_weights, objective_thresholds=(objective_thresholds if objective_thresholds is not None else torch.zeros(objective_weights.shape)), ) Y_obj = obj(Y) indx_frontier = torch.arange(Y.shape[0], dtype=torch.long, device=Y.device) # Filter Y, Yvar, Y_obj to items that dominate all objective thresholds if objective_thresholds is not None: objective_thresholds_mask = (Y_obj >= weighted_objective_thresholds).all(dim=1) Y = Y[objective_thresholds_mask] Yvar = Yvar[objective_thresholds_mask] Y_obj = Y_obj[objective_thresholds_mask] indx_frontier = indx_frontier[objective_thresholds_mask] # Get feasible points that do not violate outcome_constraints if outcome_constraints is not None: cons_tfs = get_outcome_constraint_transforms(outcome_constraints) # pyre-ignore [16] feas = torch.stack([c(Y) <= 0 for c in cons_tfs], dim=-1).all(dim=-1) Y = Y[feas] Yvar = Yvar[feas] Y_obj = Y_obj[feas] indx_frontier = indx_frontier[feas] if Y.shape[0] == 0: # if there are no feasible points that are better than the reference point # return empty tensors return Y, Yvar, indx_frontier # calculate pareto front with only objective outcomes: frontier_mask = is_non_dominated(Y_obj) # Apply masks Y_frontier = Y[frontier_mask] Yvar_frontier = Yvar[frontier_mask] indx_frontier = indx_frontier[frontier_mask] return Y_frontier, Yvar_frontier, indx_frontier