We opted for a single multidimensional KDE compared to the
        hierarchy of one-dimensional KDEs used in TPE. The dimensional is
        seperated by budget. This function sample a configuration from
        largest budget. Firstly we sample "num_samples" configurations,
        then prefer one with the largest l(x)/g(x).
        
        Parameters:
        -----------
        info_dict: dict
            record the information of this configuration

        Returns
        -------
        dict:
            new configuration named sample
        dict:
            info_dict, record the information of this configuration

def sample_from_largest_budget(self, info_dict):
        """We opted for a single multidimensional KDE compared to the
        hierarchy of one-dimensional KDEs used in TPE. The dimensional is
        seperated by budget. This function sample a configuration from
        largest budget. Firstly we sample "num_samples" configurations,
        then prefer one with the largest l(x)/g(x).
        
        Parameters:
        -----------
        info_dict: dict
            record the information of this configuration

        Returns
        -------
        dict:
            new configuration named sample
        dict:
            info_dict, record the information of this configuration
        """
        best = np.inf
        best_vector = None

        budget = max(self.kde_models.keys())

        l = self.kde_models[budget]['good'].pdf
        g = self.kde_models[budget]['bad'].pdf

        minimize_me = lambda x: max(1e-32, g(x))/max(l(x), 1e-32)

        kde_good = self.kde_models[budget]['good']
        kde_bad = self.kde_models[budget]['bad']

        for i in range(self.num_samples):
            idx = np.random.randint(0, len(kde_good.data))
            datum = kde_good.data[idx]
            vector = []

            for m, bw, t in zip(datum, kde_good.bw, self.vartypes):

                bw = max(bw, self.min_bandwidth)
                if t == 0:
                    bw = self.bw_factor*bw
                    vector.append(sps.truncnorm.rvs(-m/bw, (1-m)/bw, loc=m, scale=bw))
                else:
                    if np.random.rand() < (1-bw):
                        vector.append(int(m))
                    else:
                        vector.append(np.random.randint(t))
            val = minimize_me(vector)

            if not np.isfinite(val):
                logger.warning('sampled vector: %s has EI value %s'%(vector, val))
                logger.warning("data in the KDEs:\n%s\n%s"%(kde_good.data, kde_bad.data))
                logger.warning("bandwidth of the KDEs:\n%s\n%s"%(kde_good.bw, kde_bad.bw))
                logger.warning("l(x) = %s"%(l(vector)))
                logger.warning("g(x) = %s"%(g(vector)))

                # right now, this happens because a KDE does not contain all values for a categorical parameter
                # this cannot be fixed with the statsmodels KDE, so for now, we are just going to evaluate this one
                # if the good_kde has a finite value, i.e. there is no config with that value in the bad kde,
                # so it shouldn't be terrible.
                if np.isfinite(l(vector)):
                    best_vector = vector
                    break

            if val < best:
                best = val
                best_vector = vector

        if best_vector is None:
            logger.debug("Sampling based optimization with %i samples failed -> using random configuration"%self.num_samples)
            sample = self.configspace.sample_configuration().get_dictionary()
            info_dict['model_based_pick'] = False

        else:
            logger.debug('best_vector: {}, {}, {}, {}'.format(best_vector, best, l(best_vector), g(best_vector)))
            for i, hp_value in enumerate(best_vector):
                if isinstance(
                    self.configspace.get_hyperparameter(
                        self.configspace.get_hyperparameter_by_idx(i)
                    ),
                    ConfigSpace.hyperparameters.CategoricalHyperparameter
                ):
                    best_vector[i] = int(np.rint(best_vector[i]))
            sample = ConfigSpace.Configuration(self.configspace, vector=best_vector).get_dictionary()

            sample = ConfigSpace.util.deactivate_inactive_hyperparameters(
                configuration_space=self.configspace,
                configuration=sample)
            info_dict['model_based_pick'] = True

        return sample, info_dict