Source code for PyALAF.acfn_discrete

# Author: Mirko Fischer
# Date: 12.08.2024
# Version: 0.1
# License: MIT license

"""Acquisition function implementation for discrete values as an input an no further use of maximum finding algorithms."""

import numpy as np
import pandas as pd
from scipy.stats import norm
import matplotlib.pyplot as plt

from sklearn.preprocessing import MinMaxScaler


[docs] def UCB(f, uncertainty, alpha=0.5): ucb = f + alpha * uncertainty return ucb
[docs] def EI(f, uncertainty, opt, max=True, alpha=0.5): if max == False: f_min = np.min(f) cdf = norm.cdf((f_min - f - alpha) / uncertainty) pdf = norm.pdf((f_min - f - alpha) / uncertainty) ei = (f_min - f - alpha) * cdf + uncertainty * pdf else: f_max = np.max(f) cdf = norm.cdf((f - f_max - alpha) / uncertainty) pdf = norm.pdf((f - f_max - alpha) / uncertainty) ei = (f - f_max - alpha) * cdf + uncertainty * pdf return ei
[docs] def POI(f, uncertainty, opt, alpha, max=True): if max == False: f_min = np.min(f) probs = norm.cdf((f_min - f - alpha) / (uncertainty + 1e-9)) else: f_max = np.max(f) probs = norm.cdf((f - f_max - alpha) / (uncertainty + 1e-9)) return probs
[docs] def UIDAL(I_act, grid, uncertainty, alpha=1): # print(grid.shape) # print(grid) # print(uncertainty) n_pool = len(grid) n_samples = len(I_act) w = np.zeros([n_pool, n_samples]) SiD = np.zeros(n_pool) Z = np.zeros(n_pool) SW = np.ones(n_pool) xs = grid[I_act] for i in range(n_samples): dist = np.sum((grid - xs[i]) ** 2, axis=-1) # Distances between xs[i] and all other data points w[0 : I_act[i], i] = np.exp(-dist[0 : I_act[i]]) / dist[0 : I_act[i]] w[I_act[i], i] = 0 w[I_act[i] + 1 :, i] = np.exp(-dist[I_act[i] + 1 :]) / dist[I_act[i] + 1 :] SiD[0 : I_act[i]] += 1 / dist[0 : I_act[i]] SiD[I_act[i] + 1 :] += 1 / dist[I_act[i] + 1 :] mask = np.ones(n_pool, dtype=bool) mask[I_act] = False Z[mask] = np.arctan(1 / SiD)[mask] * 2 / np.pi SW[mask] = np.sum(w[mask][:, 0 : len(grid)], axis=1) v = w[:, 0 : len(grid)] / SW.reshape(-1, 1) vk = np.sum(v * uncertainty.reshape(-1, 1), axis=1) ideal = vk + alpha * Z return ideal
[docs] def IDEAL(I_act, grid, mean, y_true, alpha=1): n_pool = len(grid) n_samples = len(I_act) xmin = np.min(grid, axis=0) xmax = np.max(grid, axis=0) # print(xmin) # print(xmax) # print('Grid Old') # print(grid) grid = 2 / (xmax - xmin) * (grid - (xmax + xmin) / 2) # print('Grid') # print(grid) w = np.zeros([n_pool, n_samples]) SiD = np.zeros(n_pool) Z = np.zeros(n_pool) SW = np.ones(n_pool) xs = grid[I_act] Y_act = y_true[I_act] if len(mean.shape) == 1: mean = mean.reshape(-1, 1) Yhat = mean Ymax = np.max(Y_act) Ymin = np.min(Y_act) Ymax += 1.0e-8 Yscale = (Ymax - Ymin) / 2.0 dY2 = (2 * Yscale) ** 2 # print('Distances') for i in range(n_samples): dist = np.sum((grid - xs[i]) ** 2, axis=-1) w[0 : I_act[i], i] = np.exp(-dist[0 : I_act[i]]) / dist[0 : I_act[i]] w[I_act[i] + 1 :, i] = np.exp(-dist[I_act[i] + 1 :]) / dist[I_act[i] + 1 :] SiD[0 : I_act[i]] += 1 / dist[0 : I_act[i]] SiD[I_act[i] + 1 :] += 1 / dist[I_act[i] + 1 :] mask = np.ones(n_pool, dtype=bool) mask[I_act] = False Z = np.arctan(1 / SiD) * 2 / np.pi SW = np.sum(w[:, 0 : len(grid)], axis=1) mask_inverse = np.zeros(n_pool, dtype=bool) mask_inverse[I_act] = True ff = np.zeros(n_pool) ny = mean.shape[1] # print(ny) # print(w.shape) # print(SW.reshape(-1, 1).shape) # print(Yhat[:, np.newaxis].shape) # print(Y_act.shape) # print((Yhat[:,0,np.newaxis]-Y_act)) for i in range(ny): vk = w / SW.reshape(-1, 1) ff += np.sum(vk * ((Yhat[:, i, np.newaxis] - Y_act) ** 2), axis=1) / dY2 ff += alpha * Z ff[I_act] = 0 # print('New') # print(w) # print(Z) # print(SW) # if n_pool > 50: # plt.plot(grid, vk) # plt.plot(grid[I_act], y_true[I_act]) # plt.show() return ff
[docs] def GSx(I_act, grid): n_samples = len(I_act) n_pool = len(grid) xs = grid[I_act] min_dist = np.zeros(n_pool) distances = np.zeros((n_pool, n_samples)) if len(grid.shape) == 1: for i in range(n_samples): dist = (grid - xs[i]) ** 2 distances[:, i] = dist else: for i in range(n_samples): dist = np.sum((grid - xs[i]) ** 2, axis=-1) distances[:, i] = dist min_dist = np.min(distances, axis=-1) return min_dist
[docs] def GSy(mean, ys): n_samples = len(ys) n_pool = len(mean) min_dist = np.zeros(n_pool) distances = np.zeros((n_pool, n_samples)) if len(mean.shape) == 1: for i in range(n_samples): dist = (mean - ys[i]) ** 2 distances[:, i] = dist else: for i in range(n_samples): dist = np.sum((mean - ys[i]) ** 2, axis=-1) distances[:, i] = dist min_dist = np.min(distances, axis=-1) return min_dist
[docs] def iGS(I_act, grid, mean, ys): gsx = GSx(I_act, grid) gsy = GSy(mean, ys) return gsx * gsy
[docs] def SGSx(I_act, grid, std, alpha=0.5): gsx = GSx(I_act, grid) sgsx = np.power(std, alpha) * np.power(gsx, (1 - alpha)) return sgsx
[docs] def QBC(x, models): if len(x.shape) == 1: x = x.reshape(1, -1) n_models = len(models) n_pool = len(x) mean_qbc = np.zeros((n_models, n_pool)) # bootstrapping approach to train models for i in range(n_models): m = models[i].predict(x) mean_qbc[i] = m result = np.zeros(n_pool) for i in range(n_pool): result[i] = np.sum(mean_qbc[:, i] - np.mean(mean_qbc[:, i])) return result