def compute_log_marginal_with_logistic_hyper(lengthscale, lengthscale_t,midpoint,growth,noise_delta):
            # compute K
            temp=np.hstack((self.X,self.T))
            ur = unique_rows(temp)
            myX=self.X[ur]
            myT=self.T[ur]
            
            # transform Y_curve to Y_original, then to Y
            Y_original=transform_logistic(self.Y_curves,midpoint,growth,self.MaxEpisode)
            myY=(Y_original-np.mean(Y_original))/np.std(Y_original)
            
            myY=myY[ur]
          
            self.Euc_dist_x=euclidean_distances(myX,myX)
            self.Euc_dist_t=euclidean_distances(myT,myT)
        
            KK=np.exp(-np.square(self.Euc_dist_x)/lengthscale-np.square(self.Euc_dist_t)/lengthscale_t)\
                +np.eye(len(myX))*noise_delta
                    
            
            try:
                temp_inv=np.linalg.solve(KK,myY)
            except: # singular
                return -np.inf
            
            try:
                #logmarginal=-0.5*np.dot(self.Y.T,temp_inv)-0.5*np.log(np.linalg.det(KK+noise_delta))-0.5*len(X)*np.log(2*3.14)
                first_term=-0.5*np.dot(myY.T,temp_inv)
                
                # if the matrix is too large, we randomly select a part of the data for fast computation
                if KK.shape[0]>200:
                    idx=np.random.permutation(KK.shape[0])
                    idx=idx[:200]
                    KK=KK[np.ix_(idx,idx)]
                #Wi, LW, LWi, W_logdet = pdinv(KK)
                #sign,W_logdet2=np.linalg.slogdet(KK)
                chol  = spla.cholesky(KK, lower=True)
                W_logdet=np.sum(np.log(np.diag(chol)))
                # Uses the identity that log det A = log prod diag chol A = sum log diag chol A
    
                #second_term=-0.5*W_logdet2
                second_term=-W_logdet
            except: # singular
                return -np.inf
            

            logmarginal=first_term+second_term-0.5*len(myY)*np.log(2*3.14)
                
            if np.isnan(np.asscalar(logmarginal))==True:
                print("lengthscale_x={:f} lengthscale_t={:f} first term ={:.4f} second  term ={:.4f}".format(
                        lengthscale,lengthscale_t,np.asscalar(first_term),np.asscalar(second_term)))

            #print(lengthscale, lengthscale_t,midpoint,growth,"logmarginal:",logmarginal)
            return np.asscalar(logmarginal)
    def optimize_lengthscale_logistic_hyper(self,prev_hyper,noise_delta):
        # optimize both GP lengthscale and logistic hyperparameter

            
        #prev_theta=[prev_theta_x,prev_theta_t,prev_midpoint,prev_growth]
        newlengthscale,newlengthscale_t,newmidpoint,newgrowth=self.optimize_lengthscale_SE_logistic_hyper(prev_hyper,noise_delta)
        self.hyper['lengthscale_x']=newlengthscale
        self.hyper['lengthscale_t']=newlengthscale_t
        
        # refit the model
        temp=np.hstack((self.X,self.T))
        ur = unique_rows(temp)

        # update Y here
        Y_original=transform_logistic(self.Y_curves,newmidpoint,newgrowth,self.SearchSpace[-1,1])
        Y=(Y_original-np.mean(Y_original))/np.std(Y_original)
        self.Y=Y
        #
        self.fit(self.X[ur],self.T[ur],self.Y[ur],self.Y_curves)
        
        return newlengthscale,newlengthscale_t,newmidpoint,newgrowth
Exemple #3
0
    def generating_virtual_observations(self,
                                        x_max,
                                        t_max,
                                        y_original_curves,
                                        y_cost_original,
                                        IsRandom=False):

        #temp_X_new_original=x_max*self.max_min_gap[:-1]+self.SearchSpace[:-1,0]
        temp_X_new_original = self.Xscaler.inverse_transform(
            np.reshape(x_max, (-1, self.dim - 1)))

        # selecting MAX number of virtual observations, e.g., we dont want to augment more than 10 points
        max_n_virtual_obs = np.int(t_max * self.max_n_augmentation)
        if max_n_virtual_obs == 0:
            self.countVirtual.append(0)
            return

        if IsRandom == True:  # select informative locations by random uniform
            l = [np.random.uniform(0, t_max) for _ in range(max_n_virtual_obs)]
        else:
            # select informative locations by uncertainty as in the paper
            l, n_virtual_obs = self.select_informative_location_by_uncertainty(
                max_n_virtual_obs, x_max, t_max)

        self.countVirtual.append(n_virtual_obs)

        if self.verbose:
            np.set_printoptions(suppress=True)
            print("Max #augmented points", max_n_virtual_obs,
                  "\t #augmented points ", len(l), "\t Augmented points: ",
                  np.round(l, decimals=3))

        l_original = [
            self.SearchSpace[-1, 0] + val * self.max_min_gap[-1] for val in l
        ]
        #l_original=[self.Tscaler.inverse_transform(val) for val in l]

        virtual_obs_t_original = np.asarray(l_original).T
        virtual_obs_t = np.asarray(l).T

        # compute y_original for the virtual observations
        y_virtual_original = [0] * n_virtual_obs
        for ii in range(n_virtual_obs):

            idx = np.int(virtual_obs_t_original[ii])

            temp_curve = y_original_curves[0][:idx + 1]
            self.markVirtualObs.append(1)

            y_virtual_original[ii]=transform_logistic([temp_curve],\
                      self.gp.logistic_hyper['midpoint'],self.gp.logistic_hyper['growth'],self.SearchSpace[-1,1])

            self.X = np.vstack((self.X, x_max.reshape((1, -1))))
            self.X_original = np.vstack((self.X_original, temp_X_new_original))

            self.T = np.vstack((self.T, virtual_obs_t[ii].reshape((1, -1))))
            temp = np.asarray(virtual_obs_t_original[ii])
            self.T_original = np.vstack((self.T_original, temp.reshape(
                (1, -1))))

            self.Y_original = np.append(self.Y_original,
                                        [y_virtual_original[ii]])
            self.Y_curves.append(temp_curve)

            # interpolating the cost for augmented observation
            y_cost_estimate = y_cost_original * virtual_obs_t[ii]
            self.Y_cost_original = np.append(self.Y_cost_original,
                                             [y_cost_estimate])
Exemple #4
0
    def suggest_nextpoint(self):  # logistic, time-cost, virtual
        """
        Main optimization method.


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

        # init a new Gaussian Process============================================
        self.gp = ProductGaussianProcess(self.scaleSearchSpace, self.gp.hyper,
                                         self.gp.logistic_hyper)
        self.gp.fit(self.X, self.T, self.Y, self.Y_curves)

        # we store the condition number here=====================================
        self.condition_number.append(self.gp.cond_num)
        if self.verbose:
            print("ln of conditioning number of GP covariance matrix",
                  np.round(np.log(self.gp.cond_num), decimals=1))

        # count number of real observations
        count = len(self.markVirtualObs) - np.sum(self.markVirtualObs)
        count = np.int(count)

        # optimize GP hyperparameters and Logistic hyper after 3*d iterations
        if len(self.Y) % (2 * 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={:.4f}   lengthscale_t={:.3f}   Logistic_m0={:.1f}   Logistic_g0={:.1f}"
                    .format(newlengthscale_x, newlengthscale_t, new_midpoint,
                            new_growth))

        # Set acquisition function
        start_opt = time.time()

        # linear regression is used to fit the cost
        # fit X and T
        combine_input = np.hstack((self.X, self.T))
        self.linear_regression.fit(combine_input, self.Y_cost)

        # maximize the acquisition function to select the next point =================================
        x_max_temp = self.acq_utility_cost()
        x_max = x_max_temp[:-1]
        t_max = x_max_temp[-1]

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

        # this is for house keeping stuff
        self.markVirtualObs.append(0)

        self.X = np.vstack((self.X, x_max.reshape((1, -1))))
        self.T = np.vstack((self.T, t_max.reshape((1, -1))))

        # compute X in original scale
        temp_X_new_original = self.Xscaler.inverse_transform(
            np.reshape(x_max, (-1, self.dim - 1)))
        #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=t_max*self.max_min_gap[-1]+self.SearchSpace[-1,0]
        temp_T_new_original = self.Tscaler.inverse_transform(
            np.reshape(t_max, (-1, 1)))
        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]

        # evaluate the black-box function=================================================
        y_original_curves, y_cost_original = self.f(x_original_to_test)

        # compute the utility score by transformation
        y_original=transform_logistic(y_original_curves,\
              self.gp.logistic_hyper['midpoint'],self.gp.logistic_hyper['growth'],self.SearchSpace[-1,1])

        if len(y_original_curves) == 1:  # list
            self.Y_curves.append(y_original_curves[0])
        else:
            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)

        # augmenting virtual observations =====================================================
        self.generating_virtual_observations(x_max, t_max, y_original_curves,
                                             y_cost_original[0])

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

        self.Y_cost = (self.Y_cost_original - np.min(self.Y_cost_original)) / (
            np.max(self.Y_cost_original) - np.min(self.Y_cost_original))

        #if self.verbose:
        np.set_printoptions(suppress=True)

        print("[original scale] x={} t={:.0f} current y={:.2f}, ybest={:.2f}".format( np.round(self.X_original[-1],decimals=4),\
              np.asscalar(self.T_original[-1]),np.asscalar(self.Y_original[-1]), np.asscalar(self.Y_original.max())))
Exemple #5
0
    def init(self, n_init_points=3, seed=1):
        """      
        Input parameters
        ----------
        n_init_points:        # init points
        """
        np.random.seed(seed)

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

        l = [
            np.random.uniform(x[0], x[1]) for _ in range(n_init_points)
            for x in SearchSpace
        ]

        # Concatenate new random points to possible existing
        # points from self.explore method.
        temp = np.asarray(l)
        temp = temp.T
        init_X = list(temp.reshape((n_init_points, -1)))

        self.X_original = np.asarray(init_X)
        self.T_original = self.X_original[:, -1]
        self.T_original = np.reshape(self.T_original, (n_init_points, -1))

        self.X_original = self.X_original[:, :
                                          -1]  # remove the last dimension of MaxEpisode
        self.X_original = np.reshape(self.X_original, (n_init_points, -1))

        # Evaluate target function at all initialization
        y_init_curves, y_init_cost = self.f(init_X)

        y_init_cost = np.atleast_2d(np.asarray(y_init_cost)).astype('Float64')

        self.Y_curves += y_init_curves

        # we transform the y_init_curves as the average of [ curves * logistic ]
        y_init=transform_logistic(y_init_curves,self.gp.logistic_hyper['midpoint'],\
                                  self.gp.logistic_hyper['growth'], self.SearchSpace[-1,1])
        #y_init=y_init_curves
        y_init = np.reshape(y_init, (n_init_points, 1))

        # record keeping ========================================================
        self.Y_original = np.asarray(y_init)
        self.Y_cost_original = np.reshape(y_init_cost, (-1, 1))

        # convert it to scaleX
        self.X = self.Xscaler.transform(np.asarray(
            init_X)[:, :-1])  #remove the last dimension of MaxEpisode
        #self.X=self.X[:,:-1]
        self.X = np.reshape(self.X, (n_init_points, -1))

        self.T = self.Tscaler.transform(self.T_original)

        self.markVirtualObs += [0] * n_init_points

        # generating virtual observations for each initial point
        for ii in range(n_init_points):
            self.generating_virtual_observations(self.X[ii, :],
                                                 self.T[ii],
                                                 [y_init_curves[ii]],
                                                 y_init_cost[0][ii],
                                                 IsRandom=False)

        self.Y_cost = (self.Y_cost_original - np.min(self.Y_cost_original)) / (
            np.max(self.Y_cost_original) - np.min(self.Y_cost_original))

        if np.std(self.Y_original) == 0:
            self.Y = (self.Y_original - np.mean(self.Y_original))
        else:
            self.Y = (self.Y_original - np.mean(self.Y_original)) / np.std(
                self.Y_original)