Beispiel #1
0
    def _update_feas_param(self, num=1000):
        # feas_param values to be considered
        feas_params = np.linspace(self.feas_param, 0.0, 11)

        # use known_constraints only, so that we can see how much of the remaining domain is considered feasible
        # by the classifier
        random_sampler = RandomSampler(self.config,
                                       constraints=self.known_constraints)

        # draw random samples
        samples = random_sampler.draw(num=num)

        for i, feas_param in enumerate(feas_params):
            feasibility = [
                self.bayesian_network.classification_surrogate(
                    sample, threshold=feas_param) for sample in samples
            ]
            fraction_feasible = sum(feasibility) / len(feasibility)
            self.log(
                f'feas_param: {feas_param},  fraction_feasible: {fraction_feasible}',
                'DEBUG')
            # if at least 10% feasible, feas_param is acceptable
            if fraction_feasible > 0.1:
                self.feas_param = feas_param
                if i != 0:
                    self.log(
                        f'Setting "feas_param" to {feas_param} to have >10% of the optimization domain '
                        f'classified as feasible', 'WARNING')
                break

            # if feas_param == 0 and fraction_feasible == 0, something is wrong
            if feas_param < 1e-5 and fraction_feasible < 1e-5:
                raise ValueError(
                    '** feas_param == 0 and fraction_feasible == 0 **')
    def __init__(self, config):

        self.config = config
        Logger.__init__(self, 'Acquisition', self.config.get('verbosity'))
        self.random_sampler   = RandomSampler(self.config.general, self.config.parameters)
        self.total_num_vars   = len(self.config.feature_names)
        self.local_optimizers = None
        self.num_cpus         = multiprocessing.cpu_count()
Beispiel #3
0
    def __init__(self, config):

        self.config = config
        Logger.__init__(self, 'Acquisition', self.config.get('verbosity'))
        self.random_sampler = RandomSampler(self.config.general,
                                            self.config.parameters)
        self.total_num_vars = len(self.config.feature_names)
        self.local_optimizers = None
        # figure out how many CPUs to use
        if self.config.get('num_cpus') == 'all':
            self.num_cpus = multiprocessing.cpu_count()
        else:
            self.num_cpus = int(self.config.get('num_cpus'))
Beispiel #4
0
    def _propose_randomly_thread(self,
                                 best_params,
                                 num_samples,
                                 acquisition_constraints,
                                 dominant_samples=None,
                                 return_list=None):
        """
        acquisition_constraints : list
            list of constraints functions.
        dominant_samples :
            dominant samples for batch constraints.
        """

        random_sampler = RandomSampler(self.config,
                                       constraints=acquisition_constraints)

        # -------------------
        # get uniform samples
        # -------------------
        if dominant_samples is None:
            uniform_samples = random_sampler.draw(num=num_samples)
            perturb_samples = random_sampler.perturb(best_params,
                                                     num=num_samples)
            samples = np.concatenate([uniform_samples, perturb_samples])
        else:
            dominant_features = self.config.feature_process_constrained
            for batch_sample in dominant_samples:
                uniform_samples = random_sampler.draw(num=num_samples //
                                                      len(dominant_samples))
                perturb_samples = random_sampler.perturb(best_params,
                                                         num=num_samples)
                samples = np.concatenate([uniform_samples, perturb_samples])
            samples[:, dominant_features] = batch_sample[dominant_features]

        # append to shared memory list if present
        if return_list is not None:
            return_list.append(samples)

        return samples
class Acquisition(Logger):

    def __init__(self, config):

        self.config = config
        Logger.__init__(self, 'Acquisition', self.config.get('verbosity'))
        self.random_sampler   = RandomSampler(self.config.general, self.config.parameters)
        self.total_num_vars   = len(self.config.feature_names)
        self.local_optimizers = None
        self.num_cpus         = multiprocessing.cpu_count()


    def _propose_randomly(self, best_params, num_samples, dominant_samples = None):
        # get uniform samples
        if dominant_samples is None:
            uniform_samples = self.random_sampler.draw(num = self.total_num_vars * num_samples)
            perturb_samples = self.random_sampler.perturb(best_params, num = self.total_num_vars * num_samples)
            samples         = np.concatenate([uniform_samples, perturb_samples])
        else:
            dominant_features = self.config.feature_process_constrained
            for batch_sample in dominant_samples:
                uniform_samples = self.random_sampler.draw(num = self.total_num_vars * num_samples // len(dominant_samples))
                perturb_samples = self.random_sampler.perturb(best_params, num = self.total_num_vars * num_samples)
                samples         = np.concatenate([uniform_samples, perturb_samples])
            samples[:, dominant_features] = batch_sample[dominant_features]
        return samples


    def _proposal_optimization_thread(self, proposals, kernel_contribution, batch_index, return_index, return_dict = None, dominant_samples = None):
        self.log('starting process for %d' % batch_index, 'INFO')

        def kernel(x):
            num, inv_den = kernel_contribution(x)
            return (num + self.sampling_param_values[batch_index]) * inv_den

        if dominant_samples is not None:
            ignore = self.config.feature_process_constrained
        else:
            ignore = np.array([False for _ in range(len(self.config.feature_process_constrained))])

        local_optimizer = self.local_optimizers[batch_index]
        local_optimizer.set_func(kernel, ignores = ignore)

        optimized = []
        for sample_index, sample in enumerate(proposals):
            opt = local_optimizer.optimize(kernel, sample, max_iter = 10)
            optimized.append(opt)
        optimized = np.array(optimized)

        if return_dict.__class__.__name__ == 'DictProxy':
            return_dict[return_index] = optimized
        else:
            return optimized


    def _optimize_proposals(self, random_proposals, kernel_contribution, dominant_samples = None):

        if self.config.get('parallel'):
            result_dict = Manager().dict()

            # get the number of splits
            num_splits = self.num_cpus // len(self.sampling_param_values) + 1
            split_size = len(random_proposals) // num_splits

            processes   = []
            for batch_index in range(len(self.sampling_param_values)):
                for split_index in range(num_splits):

                    split_start  = split_size * split_index
                    split_end    = split_size * (split_index + 1)
                    return_index = num_splits * batch_index + split_index
                    process = Process(target = self._proposal_optimization_thread, args = (random_proposals[split_start : split_end], kernel_contribution, batch_index, return_index, result_dict, dominant_samples))
                    processes.append(process)
                    process.start()

            for process_index, process in enumerate(processes):
                process.join()

        else:
            num_splits  = 1
            result_dict = {}
            for batch_index in range(len(self.sampling_param_values)):
                return_index = batch_index
                result_dict[batch_index] = self._proposal_optimization_thread(random_proposals, kernel_contribution, batch_index, return_index, dominant_samples = dominant_samples)

        # collect optimized samples
        samples = []
        for batch_index in range(len(self.sampling_param_values)):
            batch_samples = []
            for split_index in range(num_splits):
                return_index = num_splits * batch_index + split_index
                batch_samples.append(result_dict[return_index])
            samples.append(np.concatenate(batch_samples))
        samples = np.array(samples)
        return np.array(samples)




    def propose(self, best_params, kernel_contribution, sampling_param_values,
                            num_samples = 200,
                            parallel = 'True',
                            dominant_samples  = None,
                            dominant_strategy = None,
                    ):

        self.local_optimizers = [ParameterOptimizer(self.config) for _ in range(len(sampling_param_values))]
        assert len(self.local_optimizers) == len(sampling_param_values)

        self.sampling_param_values = sampling_param_values
        random_proposals = self._propose_randomly(
                        best_params, num_samples, dominant_samples = dominant_samples,
                )


        import time
        start = time.time()
        optimized_proposals = self._optimize_proposals(
                        random_proposals, kernel_contribution, dominant_samples = dominant_samples,
                )
        end   = time.time()
        #print('[TIME]:  ', end - start, '  (optimizing proposals)')
        self.log('[TIME]:  ' + str(end - start) + '  (optimizing proposals)', 'INFO')


        extended_proposals = np.array([random_proposals for _ in range(len(sampling_param_values))])
        combined_proposals = np.concatenate((extended_proposals, optimized_proposals), axis = 1)

        return combined_proposals