def predict_G(self,xTest,eval_MSE=True): """ compute predictive mean and variance Input Parameters ---------- xTest: the testing points Returns ------- mean, var """ if len(xTest.shape)==1: # 1d xTest=xTest.reshape((-1,self.X.shape[1])) # prevent singular matrix ur = unique_rows(self.X) X=self.X[ur] #Y=self.Y[ur] #G=self.G[ur] #print("only SE kernel is implemented") Euc_dist=euclidean_distances(xTest,xTest) KK_xTest_xTest=np.exp(-np.square(Euc_dist)/self.lengthscale)+np.eye(xTest.shape[0])*self.noise_delta Euc_dist_test_train=euclidean_distances(xTest,X) KK_xTest_xTrain=np.exp(-np.square(Euc_dist_test_train)/self.lengthscale) meanG=np.dot(KK_xTest_xTrain,self.alphaG)+np.sqrt(2*self.fstar) # non zero prior mean v=np.linalg.solve(self.L,KK_xTest_xTrain.T) varG=KK_xTest_xTest-np.dot(v.T,v) return meanG.ravel(),np.diag(varG)
def fit(self,X,Y,fstar=None,IsOptimize=0): """ Fit Gaussian Process model Input Parameters ---------- x: the observed points y: the outcome y=f(x) """ ur = unique_rows(X) X=X[ur] Y=Y[ur] self.X=X self.Y=Y if fstar is not None: self.fstar=fstar self.G=np.sqrt(2.0*(fstar-Y)) #self.G=np.log(1.0*(fstar-Y)) # print("only SE kernel is implemented!") #Euc_dist=euclidean_distances(X,X) if IsOptimize: self.hyper['lengthscale']=self.optimise() # optimise GP hyperparameters #self.hyper['epsilon'],self.hyper['lengthscale'],self.noise_delta=self.optimise() # optimise GP hyperparameters self.KK_x_x=self.mycov(self.X,self.X,self.hyper)+np.eye(len(X))*self.noise_delta #self.KK_x_x=np.exp(-np.square(Euc_dist)/self.lengthscale)+np.eye(len(X))*self.noise_delta if np.isnan(self.KK_x_x).any(): #NaN print("nan in KK_x_x") self.L=np.linalg.cholesky(self.KK_x_x) # no zero mean # zero mean if self.IsZeroMean: tempG=np.linalg.solve(self.L,self.G) else: tempG=np.linalg.solve(self.L,self.G-np.sqrt(2*self.fstar)) #self.alpha=np.linalg.solve(self.L.T,temp) self.alphaG=np.linalg.solve(self.L.T,tempG)
def select_next_point_bk(self): """ Main optimization method. Input parameters ---------- gp_params: parameter for Gaussian Process Returns ------- x: recommented point for evaluation """ fstar_scaled = (self.fstar - np.mean(self.Y_ori)) / np.std(self.Y_ori) # init a new Gaussian Process if self.IsTGP == 1: self.gp = TransformedGP(self.scaleSearchSpace, verbose=self.verbose, IsZeroMean=self.IsZeroMean) # Find unique rows of X to avoid GP from breaking ur = unique_rows(self.X) self.gp.fit(self.X[ur], self.Y[ur], fstar_scaled) else: self.gp = GaussianProcess(self.scaleSearchSpace, verbose=self.verbose) ur = unique_rows(self.X) self.gp.fit(self.X[ur], self.Y[ur]) # check if the surrogate hit the optimum value f*, check if UCB and LCB cover the fstar x_ucb, y_ucb = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name="ucb", IsReturnY=True, fstar_scaled=fstar_scaled) x_lcb, y_lcb = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name="lcb", IsReturnY=True, IsMax=False) if y_lcb > fstar_scaled or y_ucb < fstar_scaled: # f* > ucb self.gp.IsZeroMean = True self.IsZeroMean = True if self.verbose == 1: print("y_lcb={} y_ucb={} fstar_scaled={:.4f}".format( y_lcb, y_ucb, fstar_scaled)) print("ZeroMean") else: self.gp.IsZeroMean = False self.IsZeroMean = False # optimize GP parameters after 3*dim iterations if len(self.Y) % (3 * self.dim) == 0: self.gp.optimise() # Set acquisition function start_opt = time.time() # run the acquisition function for the first time to get xstar x_max = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name=self.acq_name, fstar_scaled=fstar_scaled) if np.any(np.abs((self.X - x_max)).sum(axis=1) <= (self.dim * 1e-5)): if self.verbose == 1: print("{} x_max is repeated".format(self.acq_name)) # lift up the surrogate function self.gp.IsZeroMean = True self.IsZeroMean = True self.gp = TransformedGP(self.scaleSearchSpace, verbose=self.verbose, IsZeroMean=self.IsZeroMean) ur = unique_rows(self.X) self.gp.fit(self.X[ur], self.Y[ur], fstar_scaled) x_max = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name=self.acq_name, fstar_scaled=fstar_scaled) # record the optimization time finished_opt = time.time() elapse_opt = finished_opt - start_opt self.time_opt = np.hstack((self.time_opt, elapse_opt)) # store X self.X = np.vstack((self.X, x_max.reshape((1, -1)))) # compute X in original scale x_max_ori = self.Xscaler.inverse_transform( np.reshape(x_max, (-1, self.dim))) self.X_ori = np.vstack((self.X_ori, x_max_ori)) # evaluate Y using original X #self.Y = np.append(self.Y, self.f(temp_X_new_original)) Y_ori = self.f(x_max_ori) self.Y_ori = np.append(self.Y_ori, Y_ori) # update Y after change Y_ori self.Y = (self.Y_ori - np.mean(self.Y_ori)) / np.std(self.Y_ori) return x_max
def select_next_point(self): """ select the next point to evaluate ------- x: recommented point for evaluation """ fstar_scaled = (self.fstar - np.mean(self.Y_ori)) / np.std(self.Y_ori) # init a new Gaussian Process if self.IsTGP == 1: self.gp = TransformedGP(self.scaleSearchSpace, verbose=self.verbose, IsZeroMean=self.IsZeroMean) # Find unique rows of X to avoid GP from breaking ur = unique_rows(self.X) self.gp.fit(self.X[ur], self.Y[ur], fstar_scaled) else: self.gp = GaussianProcess(self.scaleSearchSpace, verbose=self.verbose) ur = unique_rows(self.X) self.gp.fit(self.X[ur], self.Y[ur]) self.gp.set_optimum_value(fstar_scaled) # optimize GP parameters after 3*dim iterations if len(self.Y) % (3 * self.dim) == 0: self.gp.optimise() # check if the surrogate hit the optimum value f*, check if UCB and LCB cover the fstar x_ucb, y_ucb = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name="ucb", IsReturnY=True, fstar_scaled=fstar_scaled) x_lcb, y_lcb = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name="lcb", IsReturnY=True, IsMax=False) #start_opt=time.time() if y_ucb < fstar_scaled: # f* > ucb we initially use EI with the vanilla GP until the fstar is covered by the upper bound x_max = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name="ei") self.marker.append(0) if self.verbose == 1: print("y_lcb={} y_ucb={} fstar_scaled={:.4f}".format( y_lcb, y_ucb, fstar_scaled)) print("EI") else: # perform TransformGP and ERM/CBM self.marker.append(1) self.IsTGP = 1 x_max=acq_max_with_name(gp=self.gp,SearchSpace=self.scaleSearchSpace,acq_name=self.acq_name, \ fstar_scaled=fstar_scaled) if np.any(np.abs((self.X - x_max)).sum(axis=1) <= (self.dim * 1e-5)): if self.verbose == 1: print("{} x_max is repeated".format(self.acq_name)) # lift up the surrogate function self.gp.IsZeroMean = True self.IsZeroMean = True self.gp = TransformedGP(self.scaleSearchSpace, verbose=self.verbose, IsZeroMean=self.IsZeroMean) ur = unique_rows(self.X) self.gp.fit(self.X[ur], self.Y[ur], fstar_scaled) x_max = acq_max_with_name(gp=self.gp, SearchSpace=self.scaleSearchSpace, acq_name=self.acq_name, fstar_scaled=fstar_scaled) # store X self.X = np.vstack((self.X, x_max.reshape((1, -1)))) # compute X in original scale x_max_ori = self.Xscaler.inverse_transform( np.reshape(x_max, (-1, self.dim))) self.X_ori = np.vstack((self.X_ori, x_max_ori)) # evaluate Y using original X #self.Y = np.append(self.Y, self.f(temp_X_new_original)) Y_ori = self.f(x_max_ori) self.Y_ori = np.append(self.Y_ori, Y_ori) # update Y after change Y_ori self.Y = (self.Y_ori - np.mean(self.Y_ori)) / np.std(self.Y_ori) return x_max