コード例 #1
0
def thompson_sampling(
    bufferx,
    objective_weights,
    regression_models,
    param_space,
    scalarization_method,
    objective_limits,
    model_type,
    classification_model=None,
    number_of_cpus=0,
):
    """
    Multi-objective thompson sampling acquisition function as detailed in https://arxiv.org/abs/1805.12168.
    :param bufferx: a list of tuples containing the points to predict and scalarize.
    :param objective_weights: a list containing the weights for each objective.
    :param regression_models: the surrogate models used to evaluate points.
    :param param_space: a space object containing the search space.
    :param scalarization_method: a string indicating which scalarization method to use.
    :param objective_limits: a dictionary with estimated minimum and maximum values for each objective.
    :param number_of_cpus: an integer for the number of cpus to be used in parallel.
    :return: a list of scalarized values for each point in bufferx.
    """
    tmp_objective_limits = copy.deepcopy(objective_limits)
    model_predictions = {}

    t0 = datetime.datetime.now()
    model_predictions = models.sample_model_posterior(
        bufferx, regression_models, model_type, param_space
    )
    number_of_predictions = len(model_predictions[list(model_predictions.keys())[0]])

    if classification_model != None:
        classification_prediction_results = models.model_probabilities(
            bufferx, classification_model, param_space
        )
        feasible_parameter = param_space.get_feasible_parameter()[0]
        true_value_index = (
            classification_model[feasible_parameter].classes_.tolist().index(True)
        )
        feasibility_indicator = classification_prediction_results[feasible_parameter][
            :, true_value_index
        ]
    else:
        feasibility_indicator = [
            1
        ] * number_of_predictions  # if no classification model is used, then all points are feasible

    if scalarization_method == "linear":
        scalarized_predictions = np.zeros(number_of_predictions)
        for objective in regression_models:
            scalarized_predictions += (
                objective_weights[objective] * model_predictions[objective]
            )
        scalarized_predictions = scalarized_predictions * feasibility_indicator
    # The paper does not propose this, I applied their methodology to the original tchebyshev to get the approach below
    # Important: since this was not proposed in the paper, their proofs and bounds for the modified_tchebyshev may not be valid here.
    elif scalarization_method == "tchebyshev":
        scalarized_predictions = np.zeros(number_of_predictions)
        scalarized_values = np.zeros(number_of_predictions)
        total_values = np.zeros(number_of_predictions)
        for objective in regression_models:
            scalarized_values = objective_weights[objective] * np.absolute(
                model_predictions[objective]
            )
            total_values += scalarized_values
            scalarized_predictions = np.maximum(
                scalarized_values, scalarized_predictions
            )
        scalarized_predictions += 0.05 * total_values
        scalarized_predictions = scalarized_predictions * feasibility_indicator
    elif scalarization_method == "modified_tchebyshev":
        scalarized_predictions = np.full((number_of_predictions), float("inf"))
        reciprocated_weights = reciprocate_weights(objective_weights)
        for objective in regression_models:
            scalarized_value = reciprocated_weights[objective] * np.absolute(
                model_predictions[objective]
            )
            # TODO scalarized_predictions2 not defined
            scalarized_predictions = np.minimum(
                scalarized_value, scalarized_predictions
            )
        scalarized_predictions = scalarized_predictions * feasibility_indicator
        scalarized_predictions = (
            -scalarized_predictions
        )  # We will minimize later, but we want to maximize instead, so we invert the sign
    else:
        print("Error: unrecognized scalarization method:", scalarization_method)
        raise SystemExit

    return scalarized_predictions, tmp_objective_limits
コード例 #2
0
def EI(
    bufferx,
    data_array,
    objective_weights,
    regression_models,
    param_space,
    scalarization_method,
    objective_limits,
    iteration_number,
    model_type,
    classification_model=None,
    number_of_cpus=0,
):
    """
    Compute a multi-objective EI acquisition function on bufferx.
    The mean and variance of the predictions are computed as defined by Hutter et al.: https://arxiv.org/pdf/1211.0906.pdf
    :param bufferx: a list of tuples containing the points to predict and scalarize.
    :param data_array: a dictionary containing the previously run points and their function values.
    :param objective_weights: a list containing the weights for each objective.
    :param regression_models: the surrogate models used to evaluate points.
    :param param_space: a space object containing the search space.
    :param scalarization_method: a string indicating which scalarization method to use.
    :param evaluations_per_optimization_iteration: how many configurations to return.
    :param objective_limits: a dictionary with estimated minimum and maximum values for each objective.
    :param iteration_number: an integer for the current iteration number, used to compute the beta
    :param classification_model: the surrogate model used to evaluate feasibility constraints
    :param number_of_cpus: an integer for the number of cpus to be used in parallel.
    :return: a list of scalarized values for each point in bufferx.
    """
    augmentation_constant = 0.05
    prediction_means = {}
    prediction_variances = {}
    number_of_predictions = len(bufferx)
    tmp_objective_limits = copy.deepcopy(objective_limits)

    prediction_means, prediction_variances = models.compute_model_mean_and_uncertainty(
        bufferx, regression_models, model_type, param_space, var=True
    )

    if classification_model != None:
        classification_prediction_results = models.model_probabilities(
            bufferx, classification_model, param_space
        )
        feasible_parameter = param_space.get_feasible_parameter()[0]
        true_value_index = (
            classification_model[feasible_parameter].classes_.tolist().index(True)
        )
        feasibility_indicator = classification_prediction_results[feasible_parameter][
            :, true_value_index
        ]
    else:
        feasibility_indicator = [
            1
        ] * number_of_predictions  # if no classification model is used, then all points are feasible

    data_array_scalarization, tmp_objective_limits = compute_data_array_scalarization(
        data_array, objective_weights, tmp_objective_limits, scalarization_method
    )

    if scalarization_method == "linear":
        scalarized_predictions = np.zeros(number_of_predictions)
        scalarized_value = 0
        for objective in regression_models:
            if (
                tmp_objective_limits[objective][1] - tmp_objective_limits[objective][0]
                == 0
            ):
                difference_obj = 1
            else:
                difference_obj = (
                    tmp_objective_limits[objective][1]
                    - tmp_objective_limits[objective][0]
                )
            f_min = 1 - (
                min(data_array[objective]) - tmp_objective_limits[objective][0]
            ) / (difference_obj)
            x_std = np.sqrt(prediction_variances[objective])
            x_mean = 1 - prediction_means[objective]
            v = (x_mean - f_min) / x_std
            objective_ei = (x_mean - f_min) * stats.norm.cdf(
                v
            ) + x_std * stats.norm.pdf(v)
            scalarized_predictions += objective_ei * objective_weights[objective]
        scalarized_predictions = -1 * scalarized_predictions * feasibility_indicator
    # The paper does not propose this, I applied their methodology to the original tchebyshev to get the approach below
    # Important: since this was not proposed in the paper, their proofs and bounds for the modified_tchebyshev may not be valid here.
    elif scalarization_method == "tchebyshev":
        scalarized_predictions = np.zeros(number_of_predictions)
        total_value = np.zeros(number_of_predictions)
        for objective in regression_models:
            if (
                tmp_objective_limits[objective][1] - tmp_objective_limits[objective][0]
                == 0
            ):
                difference_obj = 1
            else:
                difference_obj = (
                    tmp_objective_limits[objective][1]
                    - tmp_objective_limits[objective][0]
                )
            f_min = 1 - (
                min(data_array[objective]) - tmp_objective_limits[objective][0]
            ) / (difference_obj)
            x_std = np.sqrt(prediction_variances[objective])
            x_mean = 1 - prediction_means[objective]
            v = (x_mean - f_min) / x_std
            scalarized_value = objective_weights[objective] * (
                (1 - prediction_means[objective] - f_min) * stats.norm.cdf(v)
                + x_std * stats.norm.pdf(v)
            )
            scalarized_predictions = np.maximum(
                scalarized_value, scalarized_predictions
            )
            total_value += scalarized_value
        scalarized_predictions = (
            -1
            * (scalarized_predictions + total_value * augmentation_constant)
            * feasibility_indicator
        )
    elif scalarization_method == "modified_tchebyshev":
        scalarized_predictions = np.full((number_of_predictions), float("inf"))
        reciprocated_weights = reciprocate_weights(objective_weights)
        for objective in regression_models:
            if (
                tmp_objective_limits[objective][1] - tmp_objective_limits[objective][0]
                == 0
            ):
                difference_obj = 1
            else:
                difference_obj = (
                    tmp_objective_limits[objective][1]
                    - tmp_objective_limits[objective][0]
                )
            f_min = 1 - (
                min(data_array[objective]) - tmp_objective_limits[objective][0]
            ) / (difference_obj)
            x_std = np.sqrt(prediction_variances[objective])
            x_mean = 1 - prediction_means[objective]
            v = (x_mean - f_min) / x_std
            scalarized_value = reciprocated_weights[objective] * (
                (x_mean - f_min) * stats.norm.cdf(v) + x_std * stats.norm.pdf(v)
            )
            scalarized_predictions = np.minimum(
                scalarized_value, scalarized_predictions
            )
        scalarized_predictions = scalarized_predictions * feasibility_indicator
    else:
        print("Error: unrecognized scalarization method:", scalarization_method)
        raise SystemExit

    return scalarized_predictions, tmp_objective_limits
コード例 #3
0
def ucb(
    bufferx,
    objective_weights,
    regression_models,
    param_space,
    scalarization_method,
    objective_limits,
    iteration_number,
    model_type,
    classification_model=None,
    number_of_cpus=0,
):
    """
    Multi-objective ucb acquisition function as detailed in https://arxiv.org/abs/1805.12168.
    The mean and variance of the predictions are computed as defined by Hutter et al.: https://arxiv.org/pdf/1211.0906.pdf
    :param bufferx: a list of tuples containing the points to predict and scalarize.
    :param objective_weights: a list containing the weights for each objective.
    :param regression_models: the surrogate models used to evaluate points.
    :param param_space: a space object containing the search space.
    :param scalarization_method: a string indicating which scalarization method to use.
    :param evaluations_per_optimization_iteration: how many configurations to return.
    :param objective_limits: a dictionary with estimated minimum and maximum values for each objective.
    :param iteration_number: an integer for the current iteration number, used to compute the beta
    :param classification_model: the surrogate model used to evaluate feasibility constraints
    :param number_of_cpus: an integer for the number of cpus to be used in parallel.
    :return: a list of scalarized values for each point in bufferx.
    """
    beta = np.sqrt(0.125 * np.log(2 * iteration_number + 1))
    augmentation_constant = 0.05
    prediction_means = {}
    prediction_variances = {}
    number_of_predictions = len(bufferx)
    tmp_objective_limits = copy.deepcopy(objective_limits)

    prediction_means, prediction_variances = models.compute_model_mean_and_uncertainty(
        bufferx, regression_models, model_type, param_space, var=True
    )

    if classification_model != None:
        classification_prediction_results = models.model_probabilities(
            bufferx, classification_model, param_space
        )
        feasible_parameter = param_space.get_feasible_parameter()[0]
        true_value_index = (
            classification_model[feasible_parameter].classes_.tolist().index(True)
        )
        feasibility_indicator = classification_prediction_results[feasible_parameter][
            :, true_value_index
        ]
    else:
        feasibility_indicator = [
            1
        ] * number_of_predictions  # if no classification model is used, then all points are feasible

    # Compute scalarization
    if scalarization_method == "linear":
        scalarized_predictions = np.zeros(number_of_predictions)
        beta_factor = 0
        for objective in regression_models:
            scalarized_predictions += (
                objective_weights[objective] * prediction_means[objective]
            )
            beta_factor += (
                objective_weights[objective] * prediction_variances[objective]
            )
        scalarized_predictions -= beta * np.sqrt(beta_factor)
        scalarized_predictions = scalarized_predictions * feasibility_indicator
    # The paper does not propose this, I applied their methodology to the original tchebyshev to get the approach below
    # Important: since this was not proposed in the paper, their proofs and bounds for the modified_tchebyshev may not be valid here.
    elif scalarization_method == "tchebyshev":
        scalarized_predictions = np.zeros(number_of_predictions)
        total_values = np.zeros(number_of_predictions)
        for objective in regression_models:
            scalarized_values = objective_weights[objective] * np.absolute(
                prediction_means[objective]
                - beta * np.sqrt(prediction_variances[objective])
            )
            total_values += scalarized_values
            scalarized_predictions = np.maximum(
                scalarized_values, scalarized_predictions
            )
        scalarized_predictions += augmentation_constant * total_values
        scalarized_predictions = scalarized_predictions * feasibility_indicator
    elif scalarization_method == "modified_tchebyshev":
        scalarized_predictions = np.full((number_of_predictions), float("inf"))
        reciprocated_weights = reciprocate_weights(objective_weights)
        for objective in regression_models:
            scalarized_value = reciprocated_weights[objective] * (
                prediction_means[objective]
                - beta * np.sqrt(prediction_variances[objective])
            )
            scalarized_predictions = np.minimum(
                scalarized_value, scalarized_predictions
            )
        scalarized_predictions = scalarized_predictions * feasibility_indicator
        scalarized_predictions = (
            -scalarized_predictions
        )  # We will minimize later, but we want to maximize instead, so we invert the sign
    else:
        print("Error: unrecognized scalarization method:", scalarization_method)
        raise SystemExit

    return scalarized_predictions, tmp_objective_limits