Example #1
0
def make_fuzzy_linear_prediction_classifier(rule, time_step):
    return FuzzyLinearPredictionClassifier(rule, get_hyperparam("epsilon_I"),
                                           get_hyperparam("fitness_I"),
                                           time_step,
                                           get_hyperparam("x_nought"),
                                           get_hyperparam("delta_rls"),
                                           get_rng())
Example #2
0
    def _update_prediction(self, classifier, payoff_diff, situation,
                           credit_weight):
        # Weighted recursive least squares
        enriched_situation = self._prepend_threshold_to_situation(situation)

        should_reset_cov_mat = \
            (classifier.experience - classifier.cov_mat_reset_stamp) \
                >= get_hyperparam("tau_rls")
        if should_reset_cov_mat:
            logging.debug("Resetting clfr cov mat")
            classifier.reset_cov_mat(get_hyperparam("delta_rls"))

        # calc cov mat update rate
        beta_rls = 1 + credit_weight* \
            np.asscalar((np.dot(enriched_situation,
                classifier.cov_mat)).dot(enriched_situation.transpose()))

        # update cov mat
        classifier.cov_mat -= (1/beta_rls)*credit_weight* \
            (np.dot(classifier.cov_mat, enriched_situation.transpose())).dot(
                (np.dot(enriched_situation, classifier.cov_mat)))

        # calc gain vector for weights
        gain_vec = np.dot(classifier.cov_mat, enriched_situation.transpose())
        gain_vec = gain_vec.flatten()

        # update weights with gain vec and payoff diff (error)
        assert len(gain_vec) == len(classifier.weight_vec)
        for idx, gain in enumerate(gain_vec):
            classifier.weight_vec[idx] += gain * credit_weight * payoff_diff
Example #3
0
 def _update_prediction(self, classifier, payoff_diff):
     if classifier.experience < (1 / get_hyperparam("beta")):
         updated_prediction = classifier.get_prediction() +  \
             payoff_diff/classifier.experience
     else:
         updated_prediction = classifier.get_prediction() + \
             get_hyperparam("beta") * payoff_diff
     classifier.set_prediction(updated_prediction)
Example #4
0
 def _update_niche_min_error(self, classifier, niche_min_error):
     # Use MAM for mu param
     niche_min_error_diff = niche_min_error - classifier.niche_min_error
     if classifier.experience < (1 / get_hyperparam("beta_e")):
         classifier.niche_min_error += \
             niche_min_error_diff / classifier.experience
     else:
         classifier.niche_min_error += \
             get_hyperparam("beta_e") * niche_min_error_diff
 def mutate_condition(self, condition, situation=None):
     genotype = condition.genotype
     for allele_idx in range(len(genotype)):
         should_mutate = get_rng().rand() < get_hyperparam("mu")
         if should_mutate:
             mutation_magnitude = get_rng().uniform(0, get_hyperparam("m"))
             mutation_sign = get_rng().choice([1, -1])
             mutation_amount = mutation_magnitude * mutation_sign
             genotype[allele_idx] += mutation_amount
     self._enforce_genotype_maps_to_valid_phenotype(genotype)
Example #6
0
def update_action_set_size(classifier, action_set):
    action_set_size_diff = action_set.num_micros \
            - classifier.action_set_size

    if classifier.experience < (1 / get_hyperparam("beta")):
        classifier.action_set_size += action_set_size_diff / \
            classifier.experience
    else:
        classifier.action_set_size += \
            get_hyperparam("beta") * action_set_size_diff
Example #7
0
    def _update_prediction_error(self, classifier, payoff_diff):
        #        first_term = abs(payoff_diff) - classifier.niche_min_error
        #        if first_term < 0:
        #            first_term = get_hyperparam("epsilon_nought")
        #        error_diff = first_term - classifier.error
        error_diff = abs(payoff_diff) - classifier.error

        # Use MAM for error
        if classifier.experience < (1 / get_hyperparam("beta")):
            classifier.error += error_diff / classifier.experience
        else:
            classifier.error += get_hyperparam("beta") * error_diff
Example #8
0
    def _calc_deletion_vote(self, classifier, mean_fitness_in_pop):
        """DELETION VOTE function from 'An Algorithmic Description of
        XCS' (Butz and Wilson, 2002)."""
        vote = classifier.action_set_size * classifier.numerosity
        fitness_numerosity_ratio = classifier.fitness / classifier.numerosity

        has_sufficient_experience = classifier.experience > \
            get_hyperparam("theta_del")
        has_low_fitness = fitness_numerosity_ratio < \
            (get_hyperparam("delta") * mean_fitness_in_pop)
        if has_sufficient_experience and has_low_fitness:
            vote *= mean_fitness_in_pop / fitness_numerosity_ratio

        return vote
 def mutate_condition(self, condition, situation=None):
     genotype = condition.genotype
     for allele_idx in range(len(genotype)):
         should_mutate = get_rng().rand() < get_hyperparam("mu")
         if should_mutate:
             # mutation draws from +-[0, m_nought)
             m_nought = get_hyperparam("m_nought")
             assert m_nought > 0
             mut_choices = range(0, m_nought)
             mutation_magnitude = get_rng().choice(mut_choices)
             mutation_sign = get_rng().choice([1, -1])
             mutation_amount = mutation_magnitude * mutation_sign
             genotype[allele_idx] += mutation_amount
     self._enforce_genotype_maps_to_valid_phenotype(genotype)
Example #10
0
 def _update_population(self, children, parents, population):
     should_do_subsumption = get_hyperparam("do_ga_subsumption")
     for child in children:
         if should_do_subsumption:
             was_subsumed = self._try_subsume_with_parents(
                 child, parents, population)
             if not was_subsumed:
                 population.insert(child, operation_label="discovery")
         else:
             population.insert(child, operation_label="discovery")
Example #11
0
 def _calc_weight_deltas(self, payoff_diff, situation):
     augmented_situation = self._prepend_threshold_to_situation(situation)
     # Normalise by squared L2 norm: see e.g.
     # https://danieltakeshi.github.io/2015-07-29-the-least-mean-squares-algorithm/
     normalisation_term = sum([elem**2 for elem in augmented_situation])
     weight_deltas = []
     for elem in augmented_situation:
         delta = (get_hyperparam("eta") / normalisation_term) \
             * payoff_diff * elem
         weight_deltas.append(delta)
     return weight_deltas
Example #12
0
 def __call__(self, operating_set):
     tournament_size = math.ceil(
         get_hyperparam("tau") * operating_set.num_macros)
     assert 1 <= tournament_size <= operating_set.num_macros
     best_classifier = \
         self._select_random_classifier_from_set(operating_set)
     for _ in range(2, (tournament_size + 1)):
         classifier = self._select_random_classifier_from_set(operating_set)
         if classifier.fitness > best_classifier.fitness:
             best_classifier = classifier
     return best_classifier
Example #13
0
 def _perform_crossover(self, children, parents, situation):
     should_do_crossover = get_rng().rand() < get_hyperparam("chi")
     if should_do_crossover:
         (child_one, child_two) = children
         logging.debug(f"Before crossover {child_one.condition}, "
                       f"{child_two.condition}")
         self._rule_repr.crossover_conditions(child_one.condition,
                                              child_two.condition,
                                              self._crossover_strat)
         logging.debug(f"After crossover {child_one.condition}, "
                       f"{child_two.condition}")
         self._update_children_params(children, parents, situation)
Example #14
0
 def mutate_condition(self, condition, situation):
     """First part (condition mutation) of APPLY MUTATION function from 'An
     Algorithmic Description of XCS' (Butz and Wilson, 2002)."""
     genotype = condition.genotype
     for idx, (allele,
               situation_elem) in enumerate(zip(genotype, situation)):
         should_mutate_allele = get_rng().rand() < get_hyperparam("mu")
         if should_mutate_allele:
             if self._is_wildcard(allele):
                 genotype[idx] = situation_elem
             else:
                 genotype[idx] = self._WILDCARD_ALLELE
 def gen_covering_condition(self, situation):
     alleles = []
     for (idx, situation_elem) in enumerate(situation):
         lower = situation_elem - get_rng().uniform(
             0, get_hyperparam("s_nought"))
         upper = situation_elem + get_rng().uniform(
             0, get_hyperparam("s_nought"))
         dimension = self._situation_space[idx]
         lower = truncate_val(lower,
                              lower_bound=dimension.lower,
                              upper_bound=dimension.upper)
         upper = truncate_val(upper,
                              lower_bound=dimension.lower,
                              upper_bound=dimension.upper)
         assert lower <= upper
         frac_to_upper = self._calc_frac_to_upper(lower, upper,
                                                  dimension.upper)
         alleles.append(lower)
         alleles.append(frac_to_upper)
     genotype = Genotype(alleles)
     return Condition(genotype)
Example #16
0
 def _calc_accuracy_vec_and_accuracy_sum(self, action_set):
     accuracy_sum = 0
     accuracy_vec = []
     for classifier in action_set:
         is_below_error_threshold = classifier.error < \
             get_hyperparam("epsilon_nought")
         if is_below_error_threshold:
             accuracy = self._MAX_ACCURACY
         else:
             accuracy = self._calc_accuracy(classifier)
         accuracy_vec.append(accuracy)
         accuracy_sum += accuracy * classifier.numerosity
     return accuracy_vec, accuracy_sum
Example #17
0
 def gen_covering_condition(self, situation):
     """First part (condition generation) of
     GENERATE COVERING CLASSIFIER function from
     'An Algorithmic Description of XCS' (Butz and Wilson, 2002).
     """
     alleles = []
     for situation_elem in situation:
         should_make_wildcard = get_rng().rand() < get_hyperparam(
             "p_wildcard")
         if should_make_wildcard:
             alleles.append(self._WILDCARD_ALLELE)
         else:
             # copy situation
             alleles.append(situation_elem)
     genotype = Genotype(alleles)
     return Condition(genotype)
 def gen_covering_condition(self, situation):
     alleles = []
     for (idx, situation_elem) in enumerate(situation):
         # covering draws from (0, r_nought)
         r_nought = get_hyperparam("r_nought")
         assert r_nought > 1
         cover_choices = range(1, r_nought)
         lower = situation_elem - get_rng().choice(cover_choices)
         upper = situation_elem + get_rng().choice(cover_choices)
         dimension = self._situation_space[idx]
         lower = truncate_val(lower,
                              lower_bound=dimension.lower,
                              upper_bound=dimension.upper)
         upper = truncate_val(upper,
                              lower_bound=dimension.lower,
                              upper_bound=dimension.upper)
         assert lower <= upper
         span_to_upper = self._calc_span_to_upper(lower, upper, dimension)
         alleles.append(lower)
         alleles.append(span_to_upper)
     genotype = Genotype(alleles)
     return Condition(genotype)
Example #19
0
 def _decay_epsilon(self, time_step):
     decayed_val = self._epsilon_max - \
         get_hyperparam("e_greedy_decay_factor")*time_step
     self._epsilon = max(decayed_val,
                         get_hyperparam("e_greedy_min_epsilon"))
Example #20
0
 def __call__(self, prediction_array, time_step=None):
     """SELECT ACTION function from 'An Algorithmic
     Description of XCS' (Butz and Wilson, 2002)."""
     epsilon = get_hyperparam("p_explore")
     return _epsilon_greedy(prediction_array, epsilon)
Example #21
0
 def _should_cover(self, match_set):
     return num_unique_actions(match_set) < get_hyperparam("theta_mna")
Example #22
0
def make_classifier(rule, time_step):
    return Classifier(rule, get_hyperparam("prediction_I"),
                      get_hyperparam("epsilon_I"), get_hyperparam("fitness_I"),
                      time_step)
Example #23
0
 def _prepend_threshold_to_situation(self, situation):
     # return 1x(d+1) row vector
     res = np.insert(situation, 0, get_hyperparam("x_nought"))
     res = np.reshape(res, (1, len(res)))
     return res
Example #24
0
 def _decay_epsilon(self, time_step):
     self._epsilon *= get_hyperparam("e_greedy_decay_factor")
     assert self._epsilon >= 0.0
Example #25
0
 def _prepend_threshold_to_situation(self, situation):
     return np.insert(situation, 0, get_hyperparam("x_nought"))
Example #26
0
 def _update_prediction_error(self, classifier, payoff_diff, credit_weight):
     error_diff = abs(payoff_diff) - classifier.error
     classifier.error += \
         (credit_weight * get_hyperparam("beta") * error_diff)
Example #27
0
 def _update_prediction_error(self, classifier, payoff_diff):
     error_diff = abs(payoff_diff) - classifier.error
     if classifier.experience < (1 / get_hyperparam("beta")):
         classifier.error += error_diff / classifier.experience
     else:
         classifier.error += get_hyperparam("beta") * error_diff
Example #28
0
 def _update_action_set_size(self, classifier, action_set):
     action_set_size_diff = action_set.num_micros \
         - classifier.action_set_size
     classifier.action_set_size += get_hyperparam(
         "beta") * action_set_size_diff
Example #29
0
 def __call__(self, first_vec, second_vec):
     assert len(first_vec) == len(second_vec)
     for swap_idx in range(0, len(first_vec)):
         should_swap = get_rng().rand() < get_hyperparam("upsilon")
         if should_swap:
             _swap_vec_elems(first_vec, second_vec, swap_idx)
Example #30
0
 def could_subsume(self, classifier):
     """COULD SUBSUME function from 'An Algorithmic Description of XCS'
     (Butz and Wilson, 2002)."""
     return classifier.experience > get_hyperparam("theta_sub") and \
         classifier.error < get_hyperparam("epsilon_nought")