def acq_max_with_name(gp,
                      scalebounds,
                      acq_name="ei",
                      IsReturnY=False,
                      IsMax=True,
                      fstar_scaled=None):
    acq = {}
    acq['name'] = acq_name
    acq['dim'] = scalebounds.shape[0]
    acq['scalebounds'] = scalebounds
    if fstar_scaled:
        acq['fstar_scaled'] = fstar_scaled

    myacq = AcquisitionFunction(acq)
    if IsMax:
        x_max = acq_max(ac=myacq.acq_kind,
                        gp=gp,
                        bounds=scalebounds,
                        opt_toolbox='scipy')
    else:
        x_max = acq_min_scipy(ac=myacq.acq_kind, gp=gp, bounds=scalebounds)
    if IsReturnY == True:
        y_max = myacq.acq_kind(x_max, gp=gp)
        return x_max, y_max
    return x_max
Ejemplo n.º 2
0
    def init_with_data(self, init_X,init_Y):
        """      
        Input parameters
        ----------
        gp_params:            Gaussian Process structure      
        x,y:        # init data observations (in original scale)
        """

        # Turn it into np array and store.
        self.X_original=np.asarray(init_X)
        temp_init_point=np.divide((init_X-self.bounds[:,0]),self.max_min_gap)
        
        self.X_original = np.asarray(init_X)
        self.X = np.asarray(temp_init_point)
        
        self.Y_original = np.asarray(init_Y)
        #self.Y=(self.Y_original-np.mean(self.Y_original))/np.std(self.Y_original)        
        self.Y=(self.Y_original-np.mean(self.Y_original))/np.std(self.Y_original)
        
        # Set acquisition function
        self.acq_func = AcquisitionFunction(self.acq)
        
        # Find unique rows of X to avoid GP from breaking
        ur = unique_rows(self.X)
        self.gp.fit(self.X[ur], self.Y[ur])
Ejemplo n.º 3
0
    def acq_utility_cost(self):

        # generate a set of x* at T=MaxIter
        # instead of running optimization on the whole space, we will only operate on the region of interest
        # the region of interest in DRL is where the MaxEpisode

        # we find maximum of EI

        acq = {}
        acq['name'] = self.acq_name
        acq['dim'] = self.scaleSearchSpace.shape[0]
        acq['scaleSearchSpace'] = self.scaleSearchSpace

        if self.acq_name == 'ei_mu_max':  # using max of mean(x) as the incumbent

            # optimie the GP predictive mean function to find the max of mu
            x_mu_max, mu_max_val = acq_max_with_name(
                gp=self.gp,
                scaleSearchSpace=self.scaleSearchSpace,
                acq_name='mu',
                IsReturnY=True)
            acq['mu_max'] = mu_max_val

        myacq = AcquisitionFunction(acq)

        x_min = acq_min_scipy_kwargs(myfunc=self.utility_cost_evaluation,
                                     SearchSpace=self.scaleSearchSpace,
                                     acq_func=myacq,
                                     isDebug=False)

        if self.verbose == True:
            acq_val = self.utility_cost_evaluation(x_min, myacq, isDebug=False)
            print("selected point from acq func:", np.round(x_min, decimals=4),
                  "acq val=log(Utility/Cost)=", (-1) * np.round(
                      acq_val, decimals=4))  # since we minimize the acq func
            if np.round(acq_val, decimals=4) == 0:
                print("acq value =0")

        return x_min
Ejemplo n.º 4
0
    def suggest_nextpoint(self):  # logistic, time-cost, virtual
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.acq_name == 'random':
            x_max = [
                np.random.uniform(x[0], x[1], size=1) for x in self.SearchSpace
            ]
            x_max = np.asarray(x_max)
            x_max = x_max.T
            self.X_original = np.vstack((self.X_original, x_max))
            # evaluate Y using original X
            self.Y_original = np.append(self.Y_original, self.f(x_max))

            # update Y after change Y_original
            self.Y = (self.Y_original - np.mean(self.Y_original)) / np.std(
                self.Y_original)

            self.time_opt = np.hstack((self.time_opt, 0))
            return

        # init a new Gaussian Process
        #self.gp=ProductGaussianProcess(self.gp_params)
        self.gp = ProductGaussianProcess(self.scaleSearchSpace,
                                         verbose=self.verbose)

        self.gp.fit(self.X, self.T, self.Y, self.Y_curves)

        # optimize GP parameters after 3*d iterations
        if len(self.Y) % (3 * self.dim) == 0:

            hyper=[self.gp.hyper['lengthscale_x'],self.gp.hyper['lengthscale_t'], \
                   self.gp.logistic_hyper['midpoint'],self.gp.logistic_hyper['growth']]
            newlengthscale_x, newlengthscale_t, new_midpoint, new_growth = self.gp.optimize_lengthscale_logistic_hyper(
                hyper, self.gp.noise_delta)

            self.gp.hyper['lengthscale_x'] = newlengthscale_x
            self.gp.hyper['lengthscale_t'] = self.gp.hyper['lengthscale_t']
            self.gp.logistic_hyper['midpoint'] = new_midpoint
            self.gp.logistic_hyper['growth'] = new_growth
            if self.verbose:
                print("estimated lengthscale_x={}, estimated lengthscale_t={}".
                      format(newlengthscale_x, newlengthscale_t))

        # Set acquisition function
        start_opt = time.time()

        # linear regression is used to fit the cost - alternatively we can use GP

        acq = {}
        acq['name'] = self.acq_name
        acq['dim'] = self.scaleSearchSpace.shape[0]
        acq['scaleSearchSpace'] = self.scaleSearchSpace

        if self.acq_name == 'ei_mu_max':  # using max of mean(x) as the incumbent

            # optimie the GP predictive mean function to find the max of mu
            x_mu_max, mu_max_val = acq_max_with_name(
                gp=self.gp,
                scaleSearchSpace=self.scaleSearchSpace,
                acq_name='mu',
                IsReturnY=True)
            acq['mu_max'] = mu_max_val

        scaleSearchSpace = np.copy(self.scaleSearchSpace)
        scaleSearchSpace[-1, 0] = scaleSearchSpace[
            -1, 1]  # last dimension, set it to MaxIter

        #x_max_temp=acq_max_with_name(gp=self.gp,scaleSearchSpace=scaleSearchSpace,acq_name=self.acq_name)

        myacq = AcquisitionFunction(acq)
        #x_max = acq_max(ac=self.acq_func.acq_kind,gp=self.gp,bounds=self.scaleSearchSpace,opt_toolbox=self.opt_toolbox,seeds=self.xstars)
        x_max_temp = acq_max(ac=myacq.acq_kind,
                             gp=self.gp,
                             bounds=self.scaleSearchSpace)

        #        x_max_temp = acq_min_scipy_kwargs(myfunc=myacq.acq_kind,bounds=self.scaleSearchSpace,
        #                        acq_func=myacq, isDebug=False)

        #x_max_temp=self.acq_utility_cost()
        x_max = x_max_temp[:-1]
        x_max_t = x_max_temp[-1]

        # 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))))
        self.T = np.vstack((self.T, x_max_t.reshape((1, -1))))

        # compute X in original scale
        temp_X_new_original = x_max * self.max_min_gap[:
                                                       -1] + self.SearchSpace[:
                                                                              -1,
                                                                              0]
        self.X_original = np.vstack((self.X_original, temp_X_new_original))

        temp_T_new_original = x_max_t * self.max_min_gap[
            -1] + self.SearchSpace[-1, 0]
        self.T_original = np.vstack((self.T_original, temp_T_new_original))

        # evaluate Y using original X
        x_original_to_test = x_max_temp * self.max_min_gap + self.SearchSpace[:,
                                                                              0]

        y_original_curves, y_cost_original = self.f(x_original_to_test)

        #y_original_curves= self.f(x_original_to_test)
        #y_cost_original=y_original_curves

        y_original=transform_logistic(y_original_curves,self.gp.logistic_hyper['midpoint'],\
                                      self.gp.logistic_hyper['growth'],self.SearchSpace[-1,1])
        #y_original=y_original_curves
        self.Y_curves.append(y_original_curves)

        self.Y_original = np.append(self.Y_original, y_original)
        self.Y_cost_original = np.append(self.Y_cost_original, y_cost_original)

        # update Y after change Y_original
        self.Y = (self.Y_original - np.mean(self.Y_original)) / np.std(
            self.Y_original)

        #self.Y_cost=(self.Y_cost_original-np.mean(self.Y_cost_original))/np.std(self.Y_cost_original)

        if self.verbose:
            print("x={} t={} current y={:.4f}, ybest={:.4f}".format(
                self.X_original[-1], self.T_original[-1], self.Y_original[-1],
                self.Y_original.max()))
    def maximize_pvrs(self):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        if 'n_xstars' in self.acq:
            numXstar = self.acq['n_xstars']
        else:
            numXstar = 10 * self.dim

        # Set acquisition function
        start_opt = time.time()

        y_max = self.Y.max()

        # run the acquisition function for the first time to get xstar

        self.xstars = []
        # finding the xt of UCB

        numTheta = len(self.theta_vector)
        temp = []
        # finding the xt of Thompson Sampling
        for ii in range(numXstar):
            if self.theta_vector != []:
                # since the numXstar > len(theta_vector)

                index = np.random.randint(numTheta)
                #print index
                gp_params['theta'] = self.theta_vector[index]

            # init a new Gaussian Process
            self.gp = GaussianProcess(self.gp_params)
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

            xt_TS, y_xt_TS = acq_max_with_name(gp=self.gp,
                                               scalebounds=self.scalebounds,
                                               acq_name="thompson",
                                               IsReturnY=True)

            temp.append(xt_TS)
            # check if f* > y^max and ignore xt_TS otherwise
            #if y_xt_TS>=y_max:
            #self.xstars.append(xt_TS)

        if self.xstars == []:
            #print 'xt_suggestion is empty'
            # again perform TS and take all of them
            self.xstars = temp

        # check predictive variance before adding a new data points
        var_before = self.gp.compute_var(self.gp.X, self.xstars)
        var_before = np.mean(var_before)

        if self.xstar_accumulate == []:
            self.xstar_accumulate = np.asarray(self.xstars)
        else:
            self.xstar_accumulate = np.vstack(
                (self.xstar_accumulate, np.asarray(self.xstars)))

        accum_var_before = [
            self.gp.compute_var(self.gp.X, val)
            for idx, val in enumerate(self.xstar_accumulate)
        ]
        accum_var_before = np.mean(accum_var_before)

        self.gp.lengthscale_vector = self.theta_vector
        self.acq['xstars'] = self.xstars
        self.acq_func = AcquisitionFunction(self.acq)
        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)
        #xstars_array=np.asarray(self.acq_func.object.xstars)

        val_acq = -self.acq_func.acq_kind(x_max, self.gp)

        # check predictive variance after
        temp = np.vstack((self.gp.X, x_max))
        var_after = self.gp.compute_var(temp, self.xstars)
        var_after = np.mean(var_after)

        accum_var_after = [
            self.gp.compute_var(temp, val)
            for idx, val in enumerate(self.xstar_accumulate)
        ]
        accum_var_after = np.mean(accum_var_after)

        if self.PVRS_before_after == []:
            self.PVRS_before_after = np.asarray([var_before, var_after])
            self.accummulate_PVRS_before_after = np.asarray(
                [accum_var_before, accum_var_after])

        else:
            self.PVRS_before_after = np.vstack(
                (self.PVRS_before_after, np.asarray([var_before, var_after])))
            self.accummulate_PVRS_before_after = np.vstack(
                (self.accummulate_PVRS_before_after,
                 np.asarray([accum_var_before, accum_var_after])))

        #print "predictive variance before={:.12f} after={:.12f} val_acq={:.12f}".format(var_before,var_after,np.asscalar(val_acq))

        # check maximum variance
        var_acq = {}
        var_acq['name'] = 'pure_exploration'
        var_acq['dim'] = self.dim
        var_acq['scalebounds'] = self.scalebounds
        acq_var = AcquisitionFunction(var_acq)
        temp = acq_max(ac=acq_var.acq_kind,
                       gp=self.gp,
                       bounds=self.scalebounds,
                       opt_toolbox='scipy')

        # get the value f*
        #max_var_after=acq_var.acq_kind(temp,self.gp,y_max=y_max)
        #print "max predictive variance ={:.8f}".format(np.asscalar(max_var_after))

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            val_acq = self.acq_func.acq_kind(x_max, self.gp)
            self.stop_flag = 1
            print(
                "Stopping Criteria is violated. Stopping Criteria is {:.15f}".
                format(self.stopping_criteria))

        #mean,var=self.gp.predict(x_max, eval_MSE=True)
        #var.flags['WRITEABLE']=True
        #var[var<1e-20]=0
        #self.Tau_Xt= np.append(self.Tau_Xt,val_acq/var)

        # record the optimization time
        finished_opt = time.time()
        elapse_opt = finished_opt - start_opt
        self.time_opt = np.hstack((self.time_opt, elapse_opt))

        super(BayesOpt, self).augment_the_new_data(x_max)
    def maximize_e3i(self):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        # Set acquisition function
        start_opt = time.time()

        y_max = self.Y.max()

        # run the acquisition function for the first time to get xstar

        self.xstars = []
        # finding the xt of UCB

        y_max = np.max(self.Y)
        numXtar = 50 * self.dim
        #numXtar=20

        y_stars = []
        temp = []
        # finding the xt of Thompson Sampling
        for ii in range(numXtar):
            xt_TS, y_xt_TS = acq_max_with_name(gp=self.gp,
                                               scalebounds=self.scalebounds,
                                               acq_name="thompson",
                                               IsReturnY=True)

            y_stars.append(y_xt_TS)

            temp.append(xt_TS)
            # check if f* > y^max and ignore xt_TS otherwise
            #if y_xt_TS>=y_max:
            self.xstars.append(xt_TS)

        #y_stars=y_stars*np.std(self.Y_original)+np.mean(self.Y_original)
        #print "{:.5f} {:.6f}".format(np.mean(y_stars),np.std(y_stars))
        #print "ymax={:.5f}".format(np.max(self.Y))

        if self.acq['debug'] == 1:
            print('mean y*={:.4f}({:.8f}) y+={:.4f}'.format(
                np.mean(y_xt_TS), np.std(y_xt_TS), y_max))

        if self.xstars == []:
            #print 'xt_suggestion is empty'
            # again perform TS and take all of them
            self.xstars = temp

        self.acq['xstars'] = self.xstars
        self.acq['ystars'] = y_stars

        self.acq_func = AcquisitionFunction(self.acq)
        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)

        #xstars_array=np.asarray(self.acq_func.object.xstars)

        val_acq = self.acq_func.acq_kind(x_max, self.gp)

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            val_acq = self.acq_func.acq_kind(x_max, self.gp)
            self.stop_flag = 1
            print(
                "Stopping Criteria is violated. Stopping Criteria is {:.15f}".
                format(self.stopping_criteria))

        # record the optimization time
        finished_opt = time.time()
        elapse_opt = finished_opt - start_opt
        self.time_opt = np.hstack((self.time_opt, elapse_opt))

        super(BayesOpt, self).augment_the_new_data(x_max)
    def maximize(self):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        if self.acq['name'] == 'random':

            super(BayesOpt, self).generate_random_point()

            return

        # init a new Gaussian Process
        self.gp = GaussianProcess(self.gp_params)
        if self.gp.KK_x_x_inv == []:
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

        acq = self.acq

        # optimize GP parameters after 10 iterations
        if len(self.Y) % (2 * self.dim) == 0:
            self.gp, self.gp_params = super(BayesOpt,
                                            self).optimize_gp_hyperparameter()

        if self.acq['name'] == 'mes':
            self.maximize_mes()
            return
        if self.acq['name'] == 'pvrs':
            self.maximize_pvrs()
            return
        if self.acq['name'] == 'e3i':
            self.maximize_e3i()
            return
        if self.acq['name'] == 'ei_kov' or self.acq[
                'name'] == 'poi_kov' or self.acq['name'] == 'ei_fstar':
            self.acq['fstar_scaled'] = (self.acq['fstar'] - np.mean(
                self.Y_original)) / np.std(self.Y_original)

        # Set acquisition function
        start_opt = time.time()

        #y_max = self.Y.max()

        if 'xstars' not in globals():
            xstars = []

        self.xstars = xstars

        self.acq['xstars'] = xstars
        self.acq_func = AcquisitionFunction(self.acq)

        if acq['name'] == "ei_mu":
            #find the maximum in the predictive mean
            x_mu_max, y_max = acq_max_with_name(gp=self.gp,
                                                scalebounds=self.scalebounds,
                                                acq_name='mu',
                                                IsReturnY=True)

        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)

        val_acq = self.acq_func.acq_kind(x_max, self.gp)

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            #val_acq=self.acq_func.acq_kind(x_max,self.gp)

            self.stop_flag = 1
            #print "Stopping Criteria is violated. Stopping Criteria is {:.15f}".format(self.stopping_criteria)

        self.alpha_Xt = np.append(self.alpha_Xt, val_acq)

        mean, var = self.gp.predict(x_max, eval_MSE=True)
        var.flags['WRITEABLE'] = True
        var[var < 1e-20] = 0
        #self.Tau_Xt= np.append(self.Tau_Xt,val_acq/var)

        # record the optimization time
        finished_opt = time.time()
        elapse_opt = finished_opt - start_opt
        self.time_opt = np.hstack((self.time_opt, elapse_opt))

        super(BayesOpt, self).augment_the_new_data(x_max)
class BayesOpt(BO_Sequential_Base):
    def __init__(self, gp_params, func_params, acq_params, verbose=1):
        """      
        Input parameters
        ----------
        
        gp_params:                  GP parameters
        gp_params.theta:            to compute the kernel
        gp_params.delta:            to compute the kernel
        
        func_params:                function to optimize
        func_params.init bound:     initial bounds for parameters
        func_params.bounds:        bounds on parameters        
        func_params.func:           a function to be optimized
        
        
        acq_params:            acquisition function, 
        acq_params.acq_func['name']=['ei','ucb','poi','lei']
                            ,acq['kappa'] for ucb, acq['k'] for lei
        acq_params.opt_toolbox:     optimization toolbox 'nlopt','direct','scipy'
                            
        Returns
        -------
        dim:            dimension
        bounds:         bounds on original scale
        scalebounds:    bounds on normalized scale of 0-1
        time_opt:       will record the time spent on optimization
        gp:             Gaussian Process object
        """

        # Find number of parameters

        super(BayesOpt, self).__init__(gp_params, func_params, acq_params,
                                       verbose)
        """
        bounds=func_params['function'].bounds
        
        self.dim = len(bounds)

        # Create an array with parameters bounds
        if isinstance(bounds,dict):
            # Get the name of the parameters
            self.keys = list(bounds.keys())
        
            self.bounds = []
            for key in list(bounds.keys()):
                self.bounds.append(bounds[key])
            self.bounds = np.asarray(self.bounds)
        else:
            self.bounds=np.asarray(bounds)

        #print(self.bounds)
 
        # create a scalebounds 0-1
        scalebounds=np.array([np.zeros(self.dim), np.ones(self.dim)])
        self.scalebounds=scalebounds.T
        
        self.max_min_gap=self.bounds[:,1]-self.bounds[:,0]
        
        
        # Some function to be optimized
        self.f = func_params['function'].func
        # optimization toolbox
        if 'opt_toolbox' not in acq_params:
            self.opt_toolbox='scipy'
        else:
            self.opt_toolbox=acq_params['opt_toolbox']
        # acquisition function type
        
        self.acq=acq_params['acq_func']
        self.acq['scalebounds']=self.scalebounds
        
        if 'debug' not in self.acq:
            self.acq['debug']=0           
        if 'stopping' not in acq_params:
            self.stopping_criteria=0
        else:
            self.stopping_criteria=acq_params['stopping']
        if 'optimize_gp' not in acq_params:
            self.optimize_gp=0
        else:                
            self.optimize_gp=acq_params['optimize_gp']       
        if 'marginalize_gp' not in acq_params:
            self.marginalize_gp=0
        else:                
            self.marginalize_gp=acq_params['marginalize_gp']
            
        # store X in original scale
        self.X_original= None

        # store X in 0-1 scale
        self.X = None
        
        # store y=f(x)
        # (y - mean)/(max-min)
        self.Y = None
               
        # y original scale
        self.Y_original = None
        
        # performance evaluation at the maximum mean GP (for information theoretic)
        self.Y_original_maxGP = None
        self.X_original_maxGP = None
        
        # value of the acquisition function at the selected point
        self.alpha_Xt=None
        self.Tau_Xt=None
        
        self.time_opt=0

        self.k_Neighbor=2
        
        # Lipschitz constant
        self.L=0
        
        self.gp_params=gp_params       

        # Gaussian Process class
        self.gp=GaussianProcess(gp_params)

        # acquisition function
        self.acq_func = None
    
        # stop condition
        self.stop_flag=0
        self.logmarginal=0
        
        # xt_suggestion, caching for Consensus
        self.xstars=[]
        self.xstar_accumulate=[]

        # theta vector for marginalization GP
        self.theta_vector =[]
        
        # PVRS before and after
        self.PVRS_before_after=[]
        self.accummulate_PVRS_before_after=[]
        
        # store ystars
        #self.ystars=np.empty((0,100), float)
        self.ystars=[]
       """

    # will be later used for visualization
    def posterior(self, Xnew):
        self.gp.fit(self.X, self.Y)
        mu, sigma2 = self.gp.predict(Xnew, eval_MSE=True)
        return mu, np.sqrt(sigma2)

    def init(self, gp_params, n_init_points=3, seed=1):
        """      
        Input parameters
        ----------
        gp_params:            Gaussian Process structure      
        n_init_points:        # init points
        """

        super(BayesOpt, self).init(gp_params, n_init_points, seed)

    def init_with_data(self, init_X, init_Y):
        """      
        Input parameters
        ----------
        gp_params:            Gaussian Process structure      
        x,y:        # init data observations (in original scale)
        """

        super(BayesOpt, self).init_with_data(init_X, init_Y)

    def estimate_L(self, bounds):
        '''
        Estimate the Lipschitz constant of f by taking maximizing the norm of the expectation of the gradient of *f*.
        '''
        def df(x, model, x0):
            mean_derivative = gp_model.predictive_gradient(self.X, self.Y, x)

            temp = mean_derivative * mean_derivative
            if len(temp.shape) <= 1:
                res = np.sqrt(temp)
            else:
                res = np.sqrt(
                    np.sum(temp, axis=1)
                )  # simply take the norm of the expectation of the gradient

            return -res

        gp_model = self.gp

        dim = len(bounds)
        num_data = 1000 * dim
        samples = np.zeros(shape=(num_data, dim))
        for k in range(0, dim):
            samples[:, k] = np.random.uniform(low=bounds[k][0],
                                              high=bounds[k][1],
                                              size=num_data)

        #samples = np.vstack([samples,gp_model.X])
        pred_samples = df(samples, gp_model, 0)
        x0 = samples[np.argmin(pred_samples)]

        res = minimize(df,
                       x0,
                       method='L-BFGS-B',
                       bounds=bounds,
                       args=(gp_model, x0),
                       options={'maxiter': 100})

        try:
            minusL = res.fun[0][0]
        except:
            if len(res.fun.shape) == 1:
                minusL = res.fun[0]
            else:
                minusL = res.fun

        L = -minusL
        if L < 1e-6:
            L = 0.0001  ## to avoid problems in cases in which the model is flat.

        return L

    def maximize_with_lengthscale_derived_by_fstar(self, gp_params):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        if self.acq['name'] == 'random':
            x_max = [
                np.random.uniform(x[0], x[1], size=1) for x in self.bounds
            ]
            x_max = np.asarray(x_max)
            x_max = x_max.T
            self.X_original = np.vstack((self.X_original, x_max))
            # evaluate Y using original X

            #self.Y = np.append(self.Y, self.f(temp_X_new_original))
            self.Y_original = np.append(self.Y_original, self.f(x_max))

            # update Y after change Y_original
            self.Y = (self.Y_original - np.mean(self.Y_original)) / np.std(
                self.Y_original)

            self.time_opt = np.hstack((self.time_opt, 0))
            return

        # init a new Gaussian Process
        self.gp = GaussianProcess(gp_params)
        if self.gp.KK_x_x_inv == []:
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

        acq = self.acq

        # optimize GP parameters after 10 iterations
        if len(self.Y) % (3 * self.dim) == 0:
            fstar_scaled = (self.acq['fstar'] -
                            np.mean(self.Y_original)) / np.std(self.Y_original)
            newlengthscale = self.gp.optimize_lengthscale_SE_fstar(
                self.gp_params['lengthscale'], self.gp_params['noise_delta'],
                fstar_scaled)
            self.gp_params['lengthscale'] = newlengthscale
            print("estimated lengthscale =", newlengthscale)

            # init a new Gaussian Process after optimizing hyper-parameter
            self.gp = GaussianProcess(gp_params)
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

        if self.acq['name'] == 'mes':
            self.maximize_mes(gp_params)
            return
        if self.acq['name'] == 'pvrs':
            self.maximize_pvrs(gp_params)
            return
        if self.acq['name'] == 'e3i':
            self.maximize_e3i(gp_params)
            return
        if self.acq['name'] == 'ei_kov' or self.acq[
                'name'] == 'poi_kov' or self.acq['name'] == 'ei_fstar':
            self.acq['fstar_scaled'] = (self.acq['fstar'] - np.mean(
                self.Y_original)) / np.std(self.Y_original)

        # Set acquisition function
        start_opt = time.time()

        y_max = self.Y.max()

        if 'xstars' not in globals():
            xstars = []

        self.xstars = xstars

        self.acq['xstars'] = xstars
        self.acq_func = AcquisitionFunction(self.acq)

        if acq['name'] == "ei_mu":
            #find the maximum in the predictive mean
            x_mu_max, y_max = acq_max_with_name(gp=self.gp,
                                                scalebounds=self.scalebounds,
                                                acq_name='mu',
                                                IsReturnY=True)

        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)

        val_acq = self.acq_func.acq_kind(x_max, self.gp)

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            val_acq = self.acq_func.acq_kind(x_max, self.gp)

            self.stop_flag = 1
            #print "Stopping Criteria is violated. Stopping Criteria is {:.15f}".format(self.stopping_criteria)

        self.alpha_Xt = np.append(self.alpha_Xt, val_acq)

        mean, var = self.gp.predict(x_max, eval_MSE=True)
        var.flags['WRITEABLE'] = True
        var[var < 1e-20] = 0
        #self.Tau_Xt= np.append(self.Tau_Xt,val_acq/var)

        # 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
        temp_X_new_original = x_max * self.max_min_gap + self.bounds[:, 0]
        self.X_original = np.vstack((self.X_original, temp_X_new_original))
        # evaluate Y using original X

        #self.Y = np.append(self.Y, self.f(temp_X_new_original))

        self.Y_original = np.append(self.Y_original,
                                    self.f(temp_X_new_original))

        # update Y after change Y_original
        self.Y = (self.Y_original - np.mean(self.Y_original)) / np.std(
            self.Y_original)

        if self.gp.flagIncremental == 1:
            self.gp.fit_incremental(x_max, self.Y[-1])

    def maximize(self):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        if self.acq['name'] == 'random':

            super(BayesOpt, self).generate_random_point()

            return

        # init a new Gaussian Process
        self.gp = GaussianProcess(self.gp_params)
        if self.gp.KK_x_x_inv == []:
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

        acq = self.acq

        # optimize GP parameters after 10 iterations
        if len(self.Y) % (2 * self.dim) == 0:
            self.gp, self.gp_params = super(BayesOpt,
                                            self).optimize_gp_hyperparameter()

        if self.acq['name'] == 'mes':
            self.maximize_mes()
            return
        if self.acq['name'] == 'pvrs':
            self.maximize_pvrs()
            return
        if self.acq['name'] == 'e3i':
            self.maximize_e3i()
            return
        if self.acq['name'] == 'ei_kov' or self.acq[
                'name'] == 'poi_kov' or self.acq['name'] == 'ei_fstar':
            self.acq['fstar_scaled'] = (self.acq['fstar'] - np.mean(
                self.Y_original)) / np.std(self.Y_original)

        # Set acquisition function
        start_opt = time.time()

        #y_max = self.Y.max()

        if 'xstars' not in globals():
            xstars = []

        self.xstars = xstars

        self.acq['xstars'] = xstars
        self.acq_func = AcquisitionFunction(self.acq)

        if acq['name'] == "ei_mu":
            #find the maximum in the predictive mean
            x_mu_max, y_max = acq_max_with_name(gp=self.gp,
                                                scalebounds=self.scalebounds,
                                                acq_name='mu',
                                                IsReturnY=True)

        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)

        val_acq = self.acq_func.acq_kind(x_max, self.gp)

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            #val_acq=self.acq_func.acq_kind(x_max,self.gp)

            self.stop_flag = 1
            #print "Stopping Criteria is violated. Stopping Criteria is {:.15f}".format(self.stopping_criteria)

        self.alpha_Xt = np.append(self.alpha_Xt, val_acq)

        mean, var = self.gp.predict(x_max, eval_MSE=True)
        var.flags['WRITEABLE'] = True
        var[var < 1e-20] = 0
        #self.Tau_Xt= np.append(self.Tau_Xt,val_acq/var)

        # record the optimization time
        finished_opt = time.time()
        elapse_opt = finished_opt - start_opt
        self.time_opt = np.hstack((self.time_opt, elapse_opt))

        super(BayesOpt, self).augment_the_new_data(x_max)

    def maximize_mes(self):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        # Set acquisition function
        start_opt = time.time()

        y_max = self.Y.max()

        # run the acquisition function for the first time to get xstar

        self.xstars = []
        # finding the xt of UCB

        y_max = np.max(self.Y)
        #numXtar=10*self.dim
        numXtar = 30

        y_stars = []
        temp = []
        # finding the xt of Thompson Sampling
        for ii in range(numXtar):

            xt_TS, y_xt_TS = acq_max_with_name(gp=self.gp,
                                               scalebounds=self.scalebounds,
                                               acq_name="thompson",
                                               IsReturnY=True)

            #if y_xt_TS>=y_max:
            y_stars.append(y_xt_TS)

            temp.append(xt_TS)
            # check if f* > y^max and ignore xt_TS otherwise
            if y_xt_TS >= y_max:
                self.xstars.append(xt_TS)

        if self.xstars == []:
            #print 'xt_suggestion is empty'
            # again perform TS and take all of them
            self.xstars = temp

        self.acq['xstars'] = self.xstars
        self.acq['ystars'] = y_stars

        self.acq_func = AcquisitionFunction(self.acq)
        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)

        #xstars_array=np.asarray(self.acq_func.object.xstars)

        val_acq = self.acq_func.acq_kind(x_max, self.gp)

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            val_acq = self.acq_func.acq_kind(x_max, self.gp)
            self.stop_flag = 1
            print(
                "Stopping Criteria is violated. Stopping Criteria is {:.15f}".
                format(self.stopping_criteria))

        # record the optimization time
        finished_opt = time.time()
        elapse_opt = finished_opt - start_opt
        self.time_opt = np.hstack((self.time_opt, elapse_opt))

        super(BayesOpt, self).augment_the_new_data(x_max)

        # convert ystar to original scale
        y_stars = [
            val * np.std(self.Y_original) + np.mean(self.Y_original)
            for idx, val in enumerate(y_stars)
        ]

        self.ystars.append(np.ravel(y_stars))

    def maximize_e3i(self):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        # Set acquisition function
        start_opt = time.time()

        y_max = self.Y.max()

        # run the acquisition function for the first time to get xstar

        self.xstars = []
        # finding the xt of UCB

        y_max = np.max(self.Y)
        numXtar = 50 * self.dim
        #numXtar=20

        y_stars = []
        temp = []
        # finding the xt of Thompson Sampling
        for ii in range(numXtar):
            xt_TS, y_xt_TS = acq_max_with_name(gp=self.gp,
                                               scalebounds=self.scalebounds,
                                               acq_name="thompson",
                                               IsReturnY=True)

            y_stars.append(y_xt_TS)

            temp.append(xt_TS)
            # check if f* > y^max and ignore xt_TS otherwise
            #if y_xt_TS>=y_max:
            self.xstars.append(xt_TS)

        #y_stars=y_stars*np.std(self.Y_original)+np.mean(self.Y_original)
        #print "{:.5f} {:.6f}".format(np.mean(y_stars),np.std(y_stars))
        #print "ymax={:.5f}".format(np.max(self.Y))

        if self.acq['debug'] == 1:
            print('mean y*={:.4f}({:.8f}) y+={:.4f}'.format(
                np.mean(y_xt_TS), np.std(y_xt_TS), y_max))

        if self.xstars == []:
            #print 'xt_suggestion is empty'
            # again perform TS and take all of them
            self.xstars = temp

        self.acq['xstars'] = self.xstars
        self.acq['ystars'] = y_stars

        self.acq_func = AcquisitionFunction(self.acq)
        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)

        #xstars_array=np.asarray(self.acq_func.object.xstars)

        val_acq = self.acq_func.acq_kind(x_max, self.gp)

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            val_acq = self.acq_func.acq_kind(x_max, self.gp)
            self.stop_flag = 1
            print(
                "Stopping Criteria is violated. Stopping Criteria is {:.15f}".
                format(self.stopping_criteria))

        # record the optimization time
        finished_opt = time.time()
        elapse_opt = finished_opt - start_opt
        self.time_opt = np.hstack((self.time_opt, elapse_opt))

        super(BayesOpt, self).augment_the_new_data(x_max)

    def maximize_pvrs(self):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        if 'n_xstars' in self.acq:
            numXstar = self.acq['n_xstars']
        else:
            numXstar = 10 * self.dim

        # Set acquisition function
        start_opt = time.time()

        y_max = self.Y.max()

        # run the acquisition function for the first time to get xstar

        self.xstars = []
        # finding the xt of UCB

        numTheta = len(self.theta_vector)
        temp = []
        # finding the xt of Thompson Sampling
        for ii in range(numXstar):
            if self.theta_vector != []:
                # since the numXstar > len(theta_vector)

                index = np.random.randint(numTheta)
                #print index
                gp_params['theta'] = self.theta_vector[index]

            # init a new Gaussian Process
            self.gp = GaussianProcess(self.gp_params)
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

            xt_TS, y_xt_TS = acq_max_with_name(gp=self.gp,
                                               scalebounds=self.scalebounds,
                                               acq_name="thompson",
                                               IsReturnY=True)

            temp.append(xt_TS)
            # check if f* > y^max and ignore xt_TS otherwise
            #if y_xt_TS>=y_max:
            #self.xstars.append(xt_TS)

        if self.xstars == []:
            #print 'xt_suggestion is empty'
            # again perform TS and take all of them
            self.xstars = temp

        # check predictive variance before adding a new data points
        var_before = self.gp.compute_var(self.gp.X, self.xstars)
        var_before = np.mean(var_before)

        if self.xstar_accumulate == []:
            self.xstar_accumulate = np.asarray(self.xstars)
        else:
            self.xstar_accumulate = np.vstack(
                (self.xstar_accumulate, np.asarray(self.xstars)))

        accum_var_before = [
            self.gp.compute_var(self.gp.X, val)
            for idx, val in enumerate(self.xstar_accumulate)
        ]
        accum_var_before = np.mean(accum_var_before)

        self.gp.lengthscale_vector = self.theta_vector
        self.acq['xstars'] = self.xstars
        self.acq_func = AcquisitionFunction(self.acq)
        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)
        #xstars_array=np.asarray(self.acq_func.object.xstars)

        val_acq = -self.acq_func.acq_kind(x_max, self.gp)

        # check predictive variance after
        temp = np.vstack((self.gp.X, x_max))
        var_after = self.gp.compute_var(temp, self.xstars)
        var_after = np.mean(var_after)

        accum_var_after = [
            self.gp.compute_var(temp, val)
            for idx, val in enumerate(self.xstar_accumulate)
        ]
        accum_var_after = np.mean(accum_var_after)

        if self.PVRS_before_after == []:
            self.PVRS_before_after = np.asarray([var_before, var_after])
            self.accummulate_PVRS_before_after = np.asarray(
                [accum_var_before, accum_var_after])

        else:
            self.PVRS_before_after = np.vstack(
                (self.PVRS_before_after, np.asarray([var_before, var_after])))
            self.accummulate_PVRS_before_after = np.vstack(
                (self.accummulate_PVRS_before_after,
                 np.asarray([accum_var_before, accum_var_after])))

        #print "predictive variance before={:.12f} after={:.12f} val_acq={:.12f}".format(var_before,var_after,np.asscalar(val_acq))

        # check maximum variance
        var_acq = {}
        var_acq['name'] = 'pure_exploration'
        var_acq['dim'] = self.dim
        var_acq['scalebounds'] = self.scalebounds
        acq_var = AcquisitionFunction(var_acq)
        temp = acq_max(ac=acq_var.acq_kind,
                       gp=self.gp,
                       bounds=self.scalebounds,
                       opt_toolbox='scipy')

        # get the value f*
        #max_var_after=acq_var.acq_kind(temp,self.gp,y_max=y_max)
        #print "max predictive variance ={:.8f}".format(np.asscalar(max_var_after))

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            val_acq = self.acq_func.acq_kind(x_max, self.gp)
            self.stop_flag = 1
            print(
                "Stopping Criteria is violated. Stopping Criteria is {:.15f}".
                format(self.stopping_criteria))

        #mean,var=self.gp.predict(x_max, eval_MSE=True)
        #var.flags['WRITEABLE']=True
        #var[var<1e-20]=0
        #self.Tau_Xt= np.append(self.Tau_Xt,val_acq/var)

        # record the optimization time
        finished_opt = time.time()
        elapse_opt = finished_opt - start_opt
        self.time_opt = np.hstack((self.time_opt, elapse_opt))

        super(BayesOpt, self).augment_the_new_data(x_max)
    def maximize_with_lengthscale_derived_by_fstar(self, gp_params):
        """
        Main optimization method.

        Input parameters
        ----------
        gp_params: parameter for Gaussian Process

        Returns
        -------
        x: recommented point for evaluation
        """

        if self.stop_flag == 1:
            return

        if self.acq['name'] == 'random':
            x_max = [
                np.random.uniform(x[0], x[1], size=1) for x in self.bounds
            ]
            x_max = np.asarray(x_max)
            x_max = x_max.T
            self.X_original = np.vstack((self.X_original, x_max))
            # evaluate Y using original X

            #self.Y = np.append(self.Y, self.f(temp_X_new_original))
            self.Y_original = np.append(self.Y_original, self.f(x_max))

            # update Y after change Y_original
            self.Y = (self.Y_original - np.mean(self.Y_original)) / np.std(
                self.Y_original)

            self.time_opt = np.hstack((self.time_opt, 0))
            return

        # init a new Gaussian Process
        self.gp = GaussianProcess(gp_params)
        if self.gp.KK_x_x_inv == []:
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

        acq = self.acq

        # optimize GP parameters after 10 iterations
        if len(self.Y) % (3 * self.dim) == 0:
            fstar_scaled = (self.acq['fstar'] -
                            np.mean(self.Y_original)) / np.std(self.Y_original)
            newlengthscale = self.gp.optimize_lengthscale_SE_fstar(
                self.gp_params['lengthscale'], self.gp_params['noise_delta'],
                fstar_scaled)
            self.gp_params['lengthscale'] = newlengthscale
            print("estimated lengthscale =", newlengthscale)

            # init a new Gaussian Process after optimizing hyper-parameter
            self.gp = GaussianProcess(gp_params)
            # Find unique rows of X to avoid GP from breaking
            ur = unique_rows(self.X)
            self.gp.fit(self.X[ur], self.Y[ur])

        if self.acq['name'] == 'mes':
            self.maximize_mes(gp_params)
            return
        if self.acq['name'] == 'pvrs':
            self.maximize_pvrs(gp_params)
            return
        if self.acq['name'] == 'e3i':
            self.maximize_e3i(gp_params)
            return
        if self.acq['name'] == 'ei_kov' or self.acq[
                'name'] == 'poi_kov' or self.acq['name'] == 'ei_fstar':
            self.acq['fstar_scaled'] = (self.acq['fstar'] - np.mean(
                self.Y_original)) / np.std(self.Y_original)

        # Set acquisition function
        start_opt = time.time()

        y_max = self.Y.max()

        if 'xstars' not in globals():
            xstars = []

        self.xstars = xstars

        self.acq['xstars'] = xstars
        self.acq_func = AcquisitionFunction(self.acq)

        if acq['name'] == "ei_mu":
            #find the maximum in the predictive mean
            x_mu_max, y_max = acq_max_with_name(gp=self.gp,
                                                scalebounds=self.scalebounds,
                                                acq_name='mu',
                                                IsReturnY=True)

        x_max = acq_max(ac=self.acq_func.acq_kind,
                        gp=self.gp,
                        bounds=self.scalebounds,
                        opt_toolbox=self.opt_toolbox,
                        seeds=self.xstars)

        val_acq = self.acq_func.acq_kind(x_max, self.gp)

        if self.stopping_criteria != 0 and val_acq < self.stopping_criteria:
            val_acq = self.acq_func.acq_kind(x_max, self.gp)

            self.stop_flag = 1
            #print "Stopping Criteria is violated. Stopping Criteria is {:.15f}".format(self.stopping_criteria)

        self.alpha_Xt = np.append(self.alpha_Xt, val_acq)

        mean, var = self.gp.predict(x_max, eval_MSE=True)
        var.flags['WRITEABLE'] = True
        var[var < 1e-20] = 0
        #self.Tau_Xt= np.append(self.Tau_Xt,val_acq/var)

        # 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
        temp_X_new_original = x_max * self.max_min_gap + self.bounds[:, 0]
        self.X_original = np.vstack((self.X_original, temp_X_new_original))
        # evaluate Y using original X

        #self.Y = np.append(self.Y, self.f(temp_X_new_original))

        self.Y_original = np.append(self.Y_original,
                                    self.f(temp_X_new_original))

        # update Y after change Y_original
        self.Y = (self.Y_original - np.mean(self.Y_original)) / np.std(
            self.Y_original)

        if self.gp.flagIncremental == 1:
            self.gp.fit_incremental(x_max, self.Y[-1])
Ejemplo n.º 10
0
    def maximize_batch_greedy_PVRS(self,B=5):
        """
        Finding a batch of points using Peak Suppression / Constant Liar approach
        
        Input Parameters
        ----------

        gp_params:          Parameters to be passed to the Gaussian Process class
        
        kappa:              constant value in UCB
              
        Returns
        -------
        X: a batch of [x_1..x_Nt]
        """
        y_max = self.Y.max()
        
        # Set parameters if any was passed
        self.gp=GaussianProcess(self.gp_params)
        
        # Find unique rows of X to avoid GP from breaking
        ur = unique_rows(self.X)
        self.gp.fit(self.X[ur], self.Y[ur])
        
        start_opt=time.time()        

        if 'n_xstars' in self.acq:
            numXtar=self.acq['n_xstars']
        else:
            numXtar=30*self.dim
        
        #temp=[]
        # finding the xt of Thompson Sampling
        xstars=[]
            
        for ii in range(numXtar):
            mu_acq={}
            mu_acq['name']='thompson'
            mu_acq['dim']=self.dim
            mu_acq['scalebounds']=self.scalebounds     
            acq_mu=AcquisitionFunction(mu_acq)
            xt_TS = acq_max(ac=acq_mu.acq_kind,gp=self.gp,bounds=self.scalebounds,opt_toolbox='scipy')
            
            #temp.append(xt_TS)
            xstars.append(xt_TS)
                
        self.xstars=xstars

                    
        # Set acquisition function
        myacq={}
        myacq['name']='pvrs'
        myacq['dim']=self.acq['dim']
        myacq['xstars']=xstars
        
        acq_func = AcquisitionFunction(myacq)
        
        # copy GP, X and Y
        temp_gp=copy.deepcopy(self.gp)
        temp_X=copy.deepcopy(self.X)
        temp_Y=copy.deepcopy(self.Y)
        #temp_Y_original=self.Y_original
        
        start_batch=time.time()


        # check predictive variance before adding a new data points
        var_before=self.gp.compute_var(temp_X,xstars) 
        var_before=np.mean(var_before)
        
        
        #store new_x
        new_X=np.empty((0,self.dim),float)
        for ii in range(B):
            # Finding argmax of the acquisition function.
            x_max = acq_max(ac=acq_func.acq_kind,gp=temp_gp, bounds=self.scalebounds)
                                  
            new_X= np.vstack((new_X, x_max.reshape((1, -1))))
            
            temp_X = np.vstack((temp_X, x_max.reshape((1, -1))))
            
            
                    
            # check predictive variance after
            var_after=self.gp.compute_var(temp_X,xstars) 
            var_after=np.mean(var_after)
        
            if self.PVRS_before_after==[]:
                self.PVRS_before_after=np.asarray([var_before,var_after])
            else:
                temp_var=np.asarray([var_before,var_after])
                self.PVRS_before_after=np.vstack((self.PVRS_before_after, temp_var))

        
            var_before=var_after
            
            const_liar,const_liar_variance=temp_gp.predict(x_max,eval_MSE=1)
            
            const_liar=np.random.rand()
            temp_Y = np.append(temp_Y, const_liar )
            
            temp_gp.fit(temp_X,temp_Y)
        
        # for debug
        finish_batch=time.time()-start_batch        

        #return new_X,new_X_original
        
        self.NumPoints=np.append(self.NumPoints,new_X.shape[0])

        self.X=np.vstack((self.X,new_X))
        # convert back to original scale
        temp_X_new_original=[val*self.max_min_gap+self.bounds[:,0] for idx, val in enumerate(new_X)]
        temp_X_new_original=np.asarray(temp_X_new_original)
        self.X_original=np.vstack((self.X_original, temp_X_new_original))
        
        # evaluate y=f(x)
        temp=self.f(temp_X_new_original)
        temp=np.reshape(temp,(-1,1))
        self.Y_original=np.append(self.Y_original,temp)
        self.Y=(self.Y_original-np.mean(self.Y_original))/(np.max(self.Y_original)-np.min(self.Y_original))
        
                # find the maximizer in the GP mean function
        try: 
            len(self.gp)
            x_mu_max=[]
            for j in range(self.J):
                x_mu_max_temp=acq_max_with_name(gp=self.gp[j],scalebounds=self.scalebounds[self.featIdx[j]],acq_name="mu")
                x_mu_max=np.hstack((x_mu_max,x_mu_max_temp))

        except:            
            x_mu_max=acq_max_with_name(gp=self.gp,scalebounds=self.scalebounds,acq_name="mu")

        
        x_mu_max_original=x_mu_max*self.max_min_gap+self.bounds[:,0]
        # set y_max = mu_max
        #mu_max=acq_mu.acq_kind(x_mu_max,gp=self.gp)
        self.Y_original_maxGP = np.append(self.Y_original_maxGP, self.f(x_mu_max_original))
        self.X_original_maxGP = np.vstack((self.X_original_maxGP, x_mu_max_original))
        
        return new_X
Ejemplo n.º 11
0
    def __init__(self,gp_params, func_params, acq_params):
        """      
        Input parameters
        ----------
        
        gp_params:                  GP parameters
        gp_params.thete:            to compute the kernel
        gp_params.delta:            to compute the kernel
        
        func_params:                function to optimize
        func_params.init bound:     initial bounds for parameters
        func_params.bounds:        bounds on parameters        
        func_params.func:           a function to be optimized
        
        
        acq_params:            acquisition function, 
        acq_params.acq_func['name']=['ei','ucb','poi','lei']
                            ,acq['kappa'] for ucb, acq['k'] for lei
        acq_params.opt_toolbox:     optimization toolbox 'nlopt','direct','scipy'
                            
        Returns
        -------
        dim:            dimension
        bounds:         bounds on original scale
        scalebounds:    bounds on normalized scale of 0-1
        time_opt:       will record the time spent on optimization
        gp:             Gaussian Process object
        """
        
        try:
            bounds=func_params['bounds']
        except:
            bounds=func_params['function'].bounds      
            
        self.dim = len(bounds)

        # Create an array with parameters bounds
        if isinstance(bounds,dict):
            # Get the name of the parameters
            self.keys = list(bounds.keys())
        
            self.bounds = []
            for key in list(bounds.keys()):
                self.bounds.append(bounds[key])
            self.bounds = np.asarray(self.bounds)
        else:
            self.bounds=np.asarray(bounds)

     

        scalebounds=np.array([np.zeros(self.dim), np.ones(self.dim)])
        self.scalebounds=scalebounds.T
        
        self.max_min_gap=self.bounds[:,1]-self.bounds[:,0]
                    
        # acquisition function type
        self.acq=acq_params['acq_func']
        
        if 'debug' not in self.acq:
            self.acq['debug']=0
            
        if 'optimize_gp' not in acq_params:
            self.optimize_gp=0
        else:                
            self.optimize_gp=acq_params['optimize_gp']
        
        if 'marginalize_gp' not in acq_params:
            self.marginalize_gp=0
        else:                
            self.marginalize_gp=acq_params['marginalize_gp']
            
        # Some function to be optimized
           
        self.function=func_params['function']
        try:
            self.f = func_params['function']['func']
        except:
            self.f = func_params['function'].func
            
        # optimization toolbox
        if 'opt_toolbox' not in acq_params:
            self.opt_toolbox='scipy'
        else:
            self.opt_toolbox=acq_params['opt_toolbox']

        
        # store the batch size for each iteration
        self.NumPoints=[]
        # Numpy array place holders
        self.X_original= None
        
        # scale the data to 0-1 fit GP better
        self.X = None # X=( X_original - min(bounds) / (max(bounds) - min(bounds))
        
        self.Y = None # Y=( Y_original - mean(bounds) / (max(bounds) - min(bounds))
        self.Y_original = None
        self.opt_time=0
        
        self.L=0 # lipschitz

        self.gp=GaussianProcess(gp_params)
        
        self.gp_params=gp_params

        # Acquisition Function
        #self.acq_func = None
        self.acq_func = AcquisitionFunction(acq=self.acq)
        self.accum_dist=[]
        
        # theta vector for marginalization GP
        self.theta_vector =[]
        
        if 'xstars' not in self.acq:
            self.xstars=[]
        else:
            self.xstars=self.acq['xstars']
            
        # PVRS before and after
        self.PVRS_before_after=[]
        self.xstars=[]
        
        self.Y_original_maxGP=None
        self.X_original_maxGP=None
Ejemplo n.º 12
0
    def maximize_batch_PVRS_iterative_greedy(self,B=5,first_batch=[]):
        """
        Finding a batch of points using Peak Suppression / Constant Liar approach
        
        Input Parameters
        ----------

        gp_params:          Parameters to be passed to the Gaussian Process class
        
        kappa:              constant value in UCB
              
        Returns
        -------
        X: a batch of [x_1..x_Nt]
        """
        y_max = self.Y.max()
        
        # Set parameters if any was passed
        gp=GaussianProcess(self.gp_params)
        
        # Find unique rows of X to avoid GP from breaking
        ur = unique_rows(self.X)
        gp.fit(self.X[ur], self.Y[ur])
        
        # define the number of Thompson sample M
        if 'n_xstars' in self.acq:
            numXtar=self.acq['n_xstars']
        else:
            numXtar=20*self.dim

        if self.xstars==[]:
            xstars=[]
            for ii in range(numXtar):
                mu_acq={}
                mu_acq['name']='thompson'
                mu_acq['dim']=self.dim
                mu_acq['scalebounds']=self.scalebounds     
                acq_mu=AcquisitionFunction(mu_acq)
                xt_TS = acq_max(ac=acq_mu.acq_kind,gp=gp,bounds=self.scalebounds,opt_toolbox='scipy')
                
                #temp.append(xt_TS)
                xstars.append(xt_TS)
        else:
            xstars=self.xstars
            
        # Set acquisition function
        myacq={}
        myacq['name']='pvrs'
        myacq['dim']=self.acq['dim']
        myacq['xstars']=xstars
        acq_func = AcquisitionFunction(myacq)
        
        nRepeat=8
        pred_var=[0]*nRepeat
        bestBatch=[0]*nRepeat
        for tt in range(nRepeat):
            
            # copy GP, X and Y
            temp_gp=copy.deepcopy(gp)
            temp_X=copy.deepcopy(self.X)
            temp_Y=copy.deepcopy(self.Y)
            
            start_batch=time.time()
    
            #store new_x
            if tt==0: # first iteration (repeat) use Greedy approach to fill a batch
                
                if first_batch==[]: # if the first batch is not initialized by greedy
                    new_X=[]
                    for ii in range(B):
                        # Finding argmax of the acquisition function.
                        x_max = acq_max(ac=acq_func.acq_kind,gp=temp_gp, bounds=self.scalebounds)
                        if ii==0:
                            new_X=x_max
                        else:
                            new_X= np.vstack((new_X, x_max.reshape((1, -1))))
                        temp_X = np.vstack((temp_X, x_max.reshape((1, -1))))
                        const_liar,const_liar_variance=temp_gp.predict(x_max,eval_MSE=1)
                        const_liar=np.random.rand()
                        temp_Y = np.append(temp_Y, const_liar )
                        temp_gp.fit(temp_X,temp_Y)
                else:
                    new_X=first_batch
                    #temp_X = np.vstack((temp_X, new_X.reshape((B, -1))))
                    #const_liar,const_liar_variance=temp_gp.predict(new_X,eval_MSE=1)
                    #const_liar=np.random.rand()
                    #temp_Y = np.append(temp_Y, const_liar )
                    #temp_gp.fit(temp_X,temp_Y)
                    
            else:# >=1 iteration
  
                for ii in range(B):                
                    #new_X=new_X.pop(0)
                    temp_X=copy.deepcopy(self.X)

                    if ii==0: # first element
                        temp_X = np.vstack((temp_X, new_X[ii+1:])) # remove item ii  
                    else:
                        if ii==B-1: # last element
                            temp_X = np.vstack((temp_X, new_X[0:ii-1])) # remove item ii  
                        else:
                            #temp_X = np.vstack((temp_X, new_X[0:ii]+new_X[ii+1:])) # remove item ii  
                            temp_X = np.vstack((temp_X, np.vstack((new_X[0:ii],new_X[ii+1:])))) # remove item ii  
   
                    temp_Y,const_liar_variance=temp_gp.predict(temp_X,eval_MSE=1)
                    #temp_Y=np.random.random(size=(len(temp_X),1)) # constant liar
                    temp_gp.fit(temp_X,temp_Y)
    
                    # Finding argmax of the acquisition function.
                    x_max = acq_max_with_init(ac=acq_func.acq_kind,
                                                          gp=temp_gp, y_max=y_max, 
                                                          bounds=self.scalebounds,
                                                          #init_location=np.asarray(new_X[ii]))                    
                                                          init_location=[])                    
                                                                                              
                    previous_var=self.compute_PredictiveVariance(Xstars=xstars,X_t=np.asarray(new_X))
                    
                    # back up old value
                    old_value=new_X[ii].copy()
                                       
                    new_X[ii]=x_max
                    
                    new_var=self.compute_PredictiveVariance(Xstars=xstars,X_t=np.asarray(new_X))

                    if new_var>previous_var: # keep the previous value if the uncertainty does not reduce
                        new_X[ii]=old_value
                        #print "old value"
                        
                    #new_var2=self.compute_PredictiveVariance(Xstars=xstars,X_t=np.asarray(new_X))

                    #print "prev var={:.6f}, newvar={:.6f}, newvar2={:.6f}".format(np.asscalar(previous_var),
                                    #np.asscalar(new_var),np.asscalar(new_var2))


            pred_var[tt]=self.compute_PredictiveVariance(Xstars=xstars,X_t=np.asarray(new_X))
            #print pred_var
            bestBatch[tt]=np.asarray(new_X)
            
            
        #return new_X,new_X_original
        idxBest=np.argmin(pred_var)
        
        new_X=bestBatch[idxBest]
        
        self.NumPoints=np.append(self.NumPoints,new_X.shape[0])

        self.X=np.vstack((self.X,new_X))
        # convert back to original scale
        temp_X_new_original=[val*self.max_min_gap+self.bounds[:,0] for idx, val in enumerate(new_X)]
        temp_X_new_original=np.asarray(temp_X_new_original)
        self.X_original=np.vstack((self.X_original, temp_X_new_original))
        
        # evaluate y=f(x)
        temp=self.f(temp_X_new_original)
        temp=np.reshape(temp,(-1,1))
        self.Y_original=np.append(self.Y_original,temp)
        self.Y=(self.Y_original-np.mean(self.Y_original))/(np.max(self.Y_original)-np.min(self.Y_original))
        
        
        
        #return bestBatch[idxBest],pred_var[idxBest]
        return bestBatch[idxBest],pred_var
Ejemplo n.º 13
0
def plot_acq_bo_1d_tgp(bo_tgp, fstar=0):

    global counter
    counter = counter + 1

    func = bo_tgp.f
    #x_original = np.linspace(bo.bounds[0,0], bo.bounds[0,1], 100)
    x = np.linspace(bo_tgp.scalebounds[0, 0], bo_tgp.scalebounds[0, 1], 1000)
    x_original = x * bo_tgp.max_min_gap + bo_tgp.bounds[:, 0]

    y_original = func(x_original)
    #y = func(x)
    #y_original=mu*np.std(bo.Y_original)+np.mean(bo.Y_original)

    fig = plt.figure(figsize=(7, 13))
    #fig.suptitle('Gaussian Process and Utility Function After {} Points'.format(len(bo.X)), fontdict={'size':18})

    gs = gridspec.GridSpec(5, 1, height_ratios=[3, 1, 1, 1, 1])
    axis_tgp = plt.subplot(gs[0])
    #axis_tgp_g = plt.subplot(gs[1])

    acq_UCB = plt.subplot(gs[1])
    acq_EI = plt.subplot(gs[2])

    acq_CBM = plt.subplot(gs[3])

    acq_ERM_TGP = plt.subplot(gs[4])
    #acq_ERM = plt.subplot(gs[2])

    #acq_TS2 = plt.subplot(gs[5])

    temp = np.abs(y_original - fstar)
    idx = np.argmin(temp)

    axis_tgp.hlines(fstar,
                    xmin=bo_tgp.bounds[0, 0],
                    xmax=bo_tgp.bounds[0, 1],
                    colors='r',
                    linestyles='solid')
    axis_tgp.text(7.3, fstar + 1, 'Known Value $f^*$', fontsize=14)
    axis_tgp.vlines(x=x_original[idx],
                    ymin=-11,
                    ymax=13,
                    colors='r',
                    linestyles='solid')
    axis_tgp.text(3, 14, 'Unknown Location $x^*$', fontsize=14)
    axis_tgp.set_ylim([-19, 18])
    #axis.set_yticks([])
    axis_tgp.set_xticks([])

    axis_tgp.set_title('f(x)=$f^*$-0.5*$g^2$(x), g$\sim$GP( $\sqrt{2f^*}$ ,K)',
                       fontsize=18)

    # TGP
    mu, sigma = bo_tgp.posterior_tgp(x)
    #mu_original=mu*(np.max(y_original)-np.min(y_original))+np.mean(y_original)
    mu_original = mu * np.std(bo_tgp.Y_original) + np.mean(bo_tgp.Y_original)
    sigma_original = sigma * np.std(bo_tgp.Y_original) + np.mean(
        bo_tgp.Y_original)**2

    #axis_tgp.plot(x_original, y_original, linewidth=3, label='f(x)=$f^*$-0.5*$g^2$(x)')
    axis_tgp.plot(x_original, y_original, linewidth=3, label='f(x)')
    axis_tgp.plot(bo_tgp.X_original.flatten(),
                  bo_tgp.Y_original,
                  'D',
                  markersize=8,
                  label=u'Obs',
                  color='r')
    axis_tgp.plot(x_original, mu_original, '--', color='k', label='$\mu_f(x)$')

    #samples*bo_tgp.max_min_gap+bo_tgp.bounds[:,0]
    axis_tgp.set_yticks([])
    axis_tgp.set_xticks([])

    temp_xaxis = np.concatenate([x_original, x_original[::-1]])
    #temp_xaxis=temp*bo_tgp.max_min_gap+bo_tgp.bounds[:,0]

    temp_yaxis_original = np.concatenate([
        mu_original - 1.9600 * sigma_original,
        (mu_original + 1.9600 * sigma_original)[::-1]
    ])
    #temp_yaxis=np.concatenate([mu - 1.9600 * sigma, (mu + 1.9600 * sigma)[::-1]])
    temp_yaxis = np.concatenate([mu - 1.0 * sigma, (mu + 1.0 * sigma)[::-1]])
    temp_yaxis_original2 = temp_yaxis * np.std(bo_tgp.Y_original) + np.mean(
        bo_tgp.Y_original)
    axis_tgp.fill(temp_xaxis,
                  temp_yaxis_original2,
                  alpha=.6,
                  fc='c',
                  ec='None',
                  label='$\sigma_f(x)$')

    axis_tgp.set_xlim((np.min(x_original), np.max(x_original)))
    #axis_tgp.set_ylim((-23, 18))
    axis_tgp.set_ylabel('f(x)', fontdict={'size': 16})

    # UCB
    acq_func = {}
    acq_func['name'] = 'ucb'
    acq_func['kappa'] = 2
    acq_func['dim'] = 1
    acq_func['scalebounds'] = bo_tgp.scalebounds

    myacq = AcquisitionFunction(acq_func)
    utility = myacq.acq_kind(x.reshape((-1, 1)), bo_tgp.gp)
    acq_UCB.plot(x_original, utility, label='Utility Function', color='purple')
    acq_UCB.plot(x_original[np.argmax(utility)],
                 np.max(utility),
                 '*',
                 markersize=15,
                 label=u'Next Best Guess',
                 markerfacecolor='gold',
                 markeredgecolor='k',
                 markeredgewidth=1)

    acq_UCB.vlines(x=x_original[idx],
                   ymin=-1.3,
                   ymax=2.6,
                   colors='r',
                   linestyles='solid')

    # check batch BO
    try:
        nSelectedPoints = np.int(bo_tgp.NumPoints[-1])
    except:
        nSelectedPoints = 1
    max_point = np.max(utility)

    #acq_UCB.plot(bo_tgp.X_original[-nSelectedPoints:], max_point.repeat(nSelectedPoints), 'v', markersize=15,
    #label=u'Previous Selection', markerfacecolor='green', markeredgecolor='k', markeredgewidth=1)

    acq_UCB.set_xlim((np.min(x_original), np.max(x_original)))
    acq_UCB.set_ylabel('UCB', fontdict={'size': 16})
    #acq_UCB.set_xlabel('x', fontdict={'size':16})
    acq_UCB.set_xticks([])
    acq_UCB.set_yticks([])

    # EI
    acq_func = {}
    acq_func['name'] = 'ei'
    acq_func['dim'] = 1
    acq_func['scalebounds'] = bo_tgp.scalebounds
    myacq = AcquisitionFunction(acq_func)

    utility = myacq.acq_kind(x.reshape((-1, 1)), bo_tgp.gp)
    acq_EI.plot(x_original, utility, label='Utility Function', color='purple')
    acq_EI.plot(x_original[np.argmax(utility)],
                np.max(utility),
                '*',
                markersize=15,
                label=u'Next Best Guess',
                markerfacecolor='gold',
                markeredgecolor='k',
                markeredgewidth=1)

    max_point = np.max(utility)
    acq_EI.vlines(x=x_original[idx],
                  ymin=0,
                  ymax=0.17,
                  colors='r',
                  linestyles='solid')

    #acq_EI.plot(bo.X_original[-nSelectedPoints:], max_point.repeat(nSelectedPoints), 'v', markersize=15,
    #label=u'Previous Selection', markerfacecolor='green', markeredgecolor='k', markeredgewidth=1)

    acq_EI.set_xticks([])
    acq_EI.set_yticks([])

    acq_EI.set_xlim((np.min(x_original), np.max(x_original)))
    acq_EI.set_ylabel('EI', fontdict={'size': 16})
    #acq_EI.set_xlabel('x', fontdict={'size':16})

    #Confidence Bound Minimization
    acq_func = {}
    acq_func['name'] = 'kov_cbm'
    acq_func['dim'] = 1
    acq_func['scalebounds'] = bo_tgp.scalebounds
    acq_func['fstar_scaled'] = (fstar - np.mean(bo_tgp.Y_original)) / np.std(
        bo_tgp.Y_original)

    myacq = AcquisitionFunction(acq_func)

    utility = myacq.acq_kind(x.reshape((-1, 1)), bo_tgp.gp)
    acq_CBM.plot(x_original, utility, label='Utility Function', color='purple')
    acq_CBM.plot(x_original[np.argmax(utility)],
                 np.max(utility),
                 '*',
                 markersize=15,
                 label=u'Next Best Guess',
                 markerfacecolor='gold',
                 markeredgecolor='k',
                 markeredgewidth=1)

    acq_CBM.vlines(x=x_original[idx],
                   ymin=-5.5,
                   ymax=0.1,
                   colors='r',
                   linestyles='solid')

    acq_CBM.set_xticks([])
    acq_CBM.set_yticks([])

    acq_CBM.set_xlim((np.min(x_original), np.max(x_original)))
    acq_CBM.set_ylabel('CBM', fontdict={'size': 16})
    acq_CBM.set_xlabel('x', fontdict={'size': 16})

    #axis.legend(loc="lower center",prop={'size':16},ncol=4)

    # ERM TGP
    acq_func = {}
    acq_func['name'] = 'kov_tgp'
    acq_func['dim'] = 1
    acq_func['scalebounds'] = bo_tgp.scalebounds
    acq_func['fstar_scaled'] = (fstar - np.mean(bo_tgp.Y_original)) / np.std(
        bo_tgp.Y_original)

    myacq = AcquisitionFunction(acq_func)

    utility = myacq.acq_kind(x.reshape((-1, 1)), bo_tgp.gp)
    acq_ERM_TGP.plot(x_original,
                     utility,
                     label='Utility Function',
                     color='purple')
    acq_ERM_TGP.plot(x_original[np.argmax(utility)],
                     np.max(utility),
                     '*',
                     markersize=15,
                     label=u'Next Best Guess',
                     markerfacecolor='gold',
                     markeredgecolor='k',
                     markeredgewidth=1)

    acq_ERM_TGP.vlines(x=x_original[idx],
                       ymin=-3.5,
                       ymax=0.1,
                       colors='r',
                       linestyles='solid')

    acq_ERM_TGP.set_xticks([])
    acq_ERM_TGP.set_yticks([])

    acq_ERM_TGP.set_xlim((np.min(x_original), np.max(x_original)))
    acq_ERM_TGP.set_ylabel('ERM', fontdict={'size': 16})
    acq_ERM_TGP.set_xlabel('x', fontdict={'size': 16})

    axis_tgp.legend(loc="lower center", prop={'size': 16}, ncol=4)
    #axis_tgp_g.legend(loc="lower center",prop={'size':16},ncol=4)

    strFileName = "{:d}_GP_AF_ERM_TGP.pdf".format(counter)
    fig.savefig(strFileName, bbox_inches='tight')