diff --git a/README.md b/README.md index 2ed47475d..d7ba58b33 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ Here is a table of algorithms, the figure, name of the code in the book and in t | 18.24 | Back-Prop-Learning | `BackPropagationLearner` | [`learning.py`][learning] | | 18.34 | AdaBoost | `AdaBoost` | [`learning.py`][learning] | | 19.2 | Current-Best-Learning | `current_best_learning` | [`knowledge.py`](knowledge.py) | -| 19.3 | Version-Space-Learning | | +| 19.3 | Version-Space-Learning | `version_space_learning` | [`knowledge.py`](knowledge.py) | | 19.8 | Minimal-Consistent-Det | | | 19.12 | FOIL | | | 21.2 | Passive-ADP-Agent | `PassiveADPAgent` | [`rl.py`][rl] | diff --git a/knowledge.py b/knowledge.py index 106176c19..a42640bfd 100644 --- a/knowledge.py +++ b/knowledge.py @@ -81,7 +81,10 @@ def generalizations(examples_so_far, h): hypotheses += h3 # Add OR operations - hypotheses.extend(add_or(examples_so_far, h)) + if hypotheses == [] or hypotheses == [{}]: + hypotheses = add_or(examples_so_far, h) + else: + hypotheses.extend(add_or(examples_so_far, h)) shuffle(hypotheses) return hypotheses @@ -111,6 +114,97 @@ def add_or(examples_so_far, h): # ______________________________________________________________________________ +def version_space_learning(examples): + """ [Figure 19.3] + The version space is a list of hypotheses, which in turn are a list + of dictionaries/disjunctions.""" + V = all_hypotheses(examples) + for e in examples: + if V: + V = version_space_update(V, e) + + return V + + +def version_space_update(V, e): + return [h for h in V if is_consistent(e, h)] + + +def all_hypotheses(examples): + """Builds a list of all the possible hypotheses""" + values = values_table(examples) + h_powerset = powerset(values.keys()) + hypotheses = [] + for s in h_powerset: + hypotheses.extend(build_attr_combinations(s, values)) + + hypotheses.extend(build_h_combinations(hypotheses)) + + return hypotheses + + +def values_table(examples): + """Builds a table with all the possible values for each attribute. + Returns a dictionary with keys the attribute names and values a list + with the possible values for the corresponding attribute.""" + values = defaultdict(lambda: []) + for e in examples: + for k, v in e.items(): + if k == 'GOAL': + continue + + mod = '!' + if e['GOAL']: + mod = '' + + if mod + v not in values[k]: + values[k].append(mod + v) + + values = dict(values) + return values + + +def build_attr_combinations(s, values): + """Given a set of attributes, builds all the combinations of values. + If the set holds more than one attribute, recursively builds the + combinations.""" + if len(s) == 1: + # s holds just one attribute, return its list of values + k = values[s[0]] + h = [[{s[0]: v}] for v in values[s[0]]] + return h + + h = [] + for i, a in enumerate(s): + rest = build_attr_combinations(s[i+1:], values) + for v in values[a]: + o = {a: v} + for r in rest: + t = o.copy() + for d in r: + t.update(d) + h.append([t]) + + return h + + +def build_h_combinations(hypotheses): + """Given a set of hypotheses, builds and returns all the combinations of the + hypotheses.""" + h = [] + h_powerset = powerset(range(len(hypotheses))) + + for s in h_powerset: + t = [] + for i in s: + t.extend(hypotheses[i]) + h.append(t) + + return h + +# ______________________________________________________________________________ + + def check_all_consistency(examples, h): """Check for the consistency of all examples under h""" for e in examples: diff --git a/tests/test_knowledge.py b/tests/test_knowledge.py index d9822c625..025da5ddd 100644 --- a/tests/test_knowledge.py +++ b/tests/test_knowledge.py @@ -23,6 +23,37 @@ def test_current_best_learning(): assert values == [True, True, True, False, False, False, True] + examples = trivial + initial_h = [{'Pizza': 'Yes'}] + h = current_best_learning(examples, initial_h) + values = [] + for e in examples: + values.append(guess_value(e, h)) + + assert values == [True, True, False] + + +def test_version_space_learning(): + V = version_space_learning(trivial) + results = [] + for e in trivial: + guess = False + for h in V: + if guess_value(e, h): + guess = True + break + + results.append(guess) + + assert results == [True, True, False] + assert [{'Pizza': 'Yes'}] in V + + +trivial = [ + {'Pizza': 'Yes', 'Soda': 'No', 'GOAL': True}, + {'Pizza': 'Yes', 'Soda': 'Yes', 'GOAL': True}, + {'Pizza': 'No', 'Soda': 'No', 'GOAL': False} +] animals_umbrellas = [ {'Species': 'Cat', 'Rain': 'Yes', 'Coat': 'No', 'GOAL': True},
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: