def integral_mean_uniform(num_samples: int, model: VanillaBayesianQuadrature): bounds = model.integral_bounds.bounds samples = _sample_uniform(num_samples, bounds) gp_mean_at_samples, _ = model.predict(samples) differences = np.array([x[1] - x[0] for x in bounds]) volume = np.prod(differences) return np.mean(gp_mean_at_samples) * volume
def bq_loop(config, ai_model=None): user_function, integral_bounds = eval(config.name)() lb = integral_bounds[0][0] # lower bound ub = integral_bounds[0][1] # upper bound data_dim = config.data_dim init_num_data = config.init_num_data interval_std = config.interval_std interval = np.zeros((1, data_dim)) std = np.zeros((1, data_dim)) mean = np.zeros((1, data_dim)) integral_bounds_scaled = integral_bounds.copy() for ii in range(data_dim): interval[0, ii] = integral_bounds[ii][1] - integral_bounds[ii][0] std[0, ii] = interval[0, ii] / interval_std mean[0, ii] = (integral_bounds[ii][1] + integral_bounds[ii][0]) / 2 integral_bounds_scaled[ii] = ((integral_bounds[ii] - mean[0, ii]) / std[0, ii]).tolist() lb_scaled = integral_bounds_scaled[0][0] # lower bound ub_scaled = integral_bounds_scaled[0][1] # upper bound lb = integral_bounds[0][0] # lower bound ub = integral_bounds[0][1] # upper bound results_list = [None] * config.repeated_runs npr = np.random.RandomState(config.seed) for kk in tqdm(range(config.repeated_runs)): integral_mean_list = np.zeros(config.bq_iter + 1) integral_std_list = np.zeros(config.bq_iter + 1) #initialize data points X_init = (npr.rand(init_num_data, data_dim) - 0.5) * interval + mean Y_init = user_function.f(X_init) X_init_norm = (X_init - mean) / std Y_init_norm, mean_Y, std_Y = standardize(Y_init) X = X_init_norm Y = Y_init_norm X[np.abs(X) < 1.0e-5] = 1.0e-5 #normalized function function_norm = lambda x: (user_function.f(x * std + mean) - mean_Y ) / std_Y if data_dim == 1: ground_truth = univariate_approximate_ground_truth_integral( function_norm, (lb_scaled, ub_scaled))[0] elif data_dim == 2: ground_truth = bivariate_approximate_ground_truth_integral( function_norm, integral_bounds_scaled)[0] #Set up Emukit_BO_BQ_GP_Model emukit_gp_model = Emukit_BO_BQ_GP_Model(X_init_norm, Y_init_norm, config, ai_model) emukit_gp_model.optimize() emukit_gp_model.set_kernel() emukit_quad_kern = QuadratureKernelCustom(emukit_gp_model, integral_bounds_scaled) emukit_model = BaseGaussianProcessCustomModel(kern=emukit_quad_kern, gp_model=emukit_gp_model) emukit_method = VanillaBayesianQuadrature(base_gp=emukit_model, X=X, Y=Y) #set up Bayesian quadrature if config.plot: x_plot = np.linspace(integral_bounds_scaled[0][0], integral_bounds_scaled[0][1], 300)[:, None] y_plot = function_norm(x_plot) mu_plot, var_plot = emukit_method.predict(x_plot) plt.figure(figsize=FIGURE_SIZE) plt.plot(X_init_norm, Y_init_norm, "ro", markersize=10, label="Observations") plt.plot(x_plot, y_plot, "k", label="The Integrand") plt.plot(x_plot, mu_plot, "C0", label="Model") plt.fill_between(x_plot[:, 0], mu_plot[:, 0] + np.sqrt(var_plot)[:, 0], mu_plot[:, 0] - np.sqrt(var_plot)[:, 0], color="C0", alpha=0.6) plt.fill_between(x_plot[:, 0], mu_plot[:, 0] + 2 * np.sqrt(var_plot)[:, 0], mu_plot[:, 0] - 2 * np.sqrt(var_plot)[:, 0], color="C0", alpha=0.4) plt.fill_between(x_plot[:, 0], mu_plot[:, 0] + 3 * np.sqrt(var_plot)[:, 0], mu_plot[:, 0] - 3 * np.sqrt(var_plot)[:, 0], color="C0", alpha=0.2) plt.legend(loc=2, prop={'size': LEGEND_SIZE}) plt.xlabel(r"$x$") plt.ylabel(r"$f(x)$") plt.grid(True) plt.xlim(lb_scaled, ub_scaled) plt.show() initial_integral_mean, initial_integral_variance = emukit_method.integrate( ) integral_mean_list[0] = initial_integral_mean integral_std_list[0] = np.sqrt(initial_integral_variance) if config.plot: x_plot_integral = np.linspace( initial_integral_mean - 3 * np.sqrt(initial_integral_variance), initial_integral_mean + 3 * np.sqrt(initial_integral_variance), 200) y_plot_integral_initial = 1/np.sqrt(initial_integral_variance * 2 * np.pi) * \ np.exp( - (x_plot_integral - initial_integral_mean)**2 / (2 * initial_integral_variance) ) plt.figure(figsize=FIGURE_SIZE) plt.plot(x_plot_integral, y_plot_integral_initial, "k", label="initial integral density") plt.axvline(initial_integral_mean, color="red", label="initial integral estimate", \ linestyle="--") plt.axvline(ground_truth, color="blue", label="ground truth integral", \ linestyle="--") plt.legend(loc=2, prop={'size': LEGEND_SIZE}) plt.xlabel(r"$F$") plt.ylabel(r"$p(F)$") plt.grid(True) plt.xlim(np.min(x_plot_integral), np.max(x_plot_integral)) plt.show() print('The initial estimated integral is: ', round(initial_integral_mean, 4)) print('with a credible interval: ', round(2 * np.sqrt(initial_integral_variance), 4), '.') print('The ground truth rounded to 2 digits for comparison is: ', round(ground_truth, 4), '.') for ii in range(config.bq_iter): time_count = 0 result = {} ivr_acquisition = IntegralVarianceReduction(emukit_method) space = ParameterSpace(emukit_method.reasonable_box_bounds. convert_to_list_of_continuous_parameters()) num_steps = 200 num_init_points = 5 optimizer = LocalSearchAcquisitionOptimizer( space, num_steps, num_init_points) x_new, _ = optimizer.optimize(ivr_acquisition) y_new = function_norm(x_new) X = np.append(X, x_new, axis=0) Y = np.append(Y, y_new, axis=0) X[np.abs(X) < 1.0e-5] = 1.0e-5 emukit_method.set_data(X, Y) start_time = time.time() emukit_model.optimize() time_count = time_count + time.time() - start_time integral_mean, integral_variance = emukit_method.integrate() integral_mean_list[ii + 1] = integral_mean integral_std_list[ii + 1] = np.sqrt(integral_variance) if config.plot: mu_plot_final, var_plot_final = emukit_method.predict(x_plot) y_plot_integral = 1/np.sqrt(integral_variance * 2 * np.pi) * \ np.exp( - (x_plot_integral - integral_mean)**2 / (2 * integral_variance) ) plt.figure(figsize=FIGURE_SIZE) plt.plot(x_plot_integral, y_plot_integral_initial, "gray", label="initial integral density") plt.plot(x_plot_integral, y_plot_integral, "k", label="new integral density") plt.axvline(initial_integral_mean, color="gray", label="initial integral estimate", linestyle="--") plt.axvline(integral_mean, color="red", label="new integral estimate", linestyle="--") plt.axvline(ground_truth, color="blue", label="ground truth integral", \ linestyle="--") plt.legend(loc=2, prop={'size': LEGEND_SIZE}) plt.xlabel(r"$F$") plt.ylabel(r"$p(F)$") plt.grid(True) plt.xlim(np.min(x_plot_integral), np.max(x_plot_integral)) plt.show() plt.figure(figsize=FIGURE_SIZE) plt.plot(emukit_model.X, emukit_model.Y, "ro", markersize=10, label="Observations") plt.plot(x_plot, y_plot, "k", label="The Integrand") plt.plot(x_plot, mu_plot_final, "C0", label="Model") plt.fill_between( x_plot[:, 0], mu_plot_final[:, 0] + np.sqrt(var_plot_final)[:, 0], mu_plot_final[:, 0] - np.sqrt(var_plot_final)[:, 0], color="C0", alpha=0.6) plt.fill_between( x_plot[:, 0], mu_plot_final[:, 0] + 2 * np.sqrt(var_plot_final)[:, 0], mu_plot_final[:, 0] - 2 * np.sqrt(var_plot_final)[:, 0], color="C0", alpha=0.4) plt.fill_between( x_plot[:, 0], mu_plot_final[:, 0] + 3 * np.sqrt(var_plot_final)[:, 0], mu_plot_final[:, 0] - 3 * np.sqrt(var_plot_final)[:, 0], color="C0", alpha=0.2) plt.legend(loc=2, prop={'size': LEGEND_SIZE}) plt.xlabel(r"$x$") plt.ylabel(r"$f(x)$") plt.grid(True) plt.xlim(lb_scaled, ub_scaled) plt.show() print('The estimated integral is: ', round(integral_mean, 4)) print('with a credible interval: ', round(2 * np.sqrt(integral_variance), 4), '.') print('The ground truth rounded to 2 digits for comparison is: ', round(ground_truth, 4), '.') integral_error_list = np.abs(integral_mean_list - ground_truth) result['integral_error_list'] = integral_error_list integral_error_list_scaledback = integral_error_list * std_Y.item() for jj in range(data_dim): integral_error_list_scaledback = integral_error_list_scaledback * std[ 0, jj] result[ 'integral_error_list_scaledback'] = integral_error_list_scaledback result['integral_std_list'] = integral_std_list result['time_elapsed'] = time_count results_list[kk] = result print(time_count) if config.plot: plt.figure(figsize=(12, 8)) plt.fill_between(np.arange(config.bq_iter + 1) + 1, integral_error_list - 0.2 * integral_std_list, integral_error_list + 0.2 * integral_std_list, color='red', alpha=0.15) plt.plot(np.arange(config.bq_iter + 1) + 1, integral_error_list, 'or-', lw=2, label='Estimated integral') plt.legend(loc=2, prop={'size': LEGEND_SIZE}) plt.xlabel(r"iteration") plt.ylabel(r"$f(x)$") plt.grid(True) plt.show() #end of one run return results_list