Skip to content

Commit 3e33cd7

Browse files
antmarakisnorvig
authored andcommitted
Knowledge: Version-Space Learning (aimacode#596)
* add version-space learner + small fix * add test for version-space learner + trivial example * Update README.md
1 parent 0db7063 commit 3e33cd7

File tree

3 files changed

+123
-1
lines changed

3 files changed

+123
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ Here is a table of algorithms, the figure, name of the algorithm in the book and
109109
| 18.24 | Back-Prop-Learning | `BackPropagationLearner` | [`learning.py`][learning] |
110110
| 18.34 | AdaBoost | `AdaBoost` | [`learning.py`][learning] |
111111
| 19.2 | Current-Best-Learning | `current_best_learning` | [`knowledge.py`](knowledge.py) |
112-
| 19.3 | Version-Space-Learning | |
112+
| 19.3 | Version-Space-Learning | `version_space_learning` | [`knowledge.py`](knowledge.py) |
113113
| 19.8 | Minimal-Consistent-Det | |
114114
| 19.12 | FOIL | |
115115
| 21.2 | Passive-ADP-Agent | `PassiveADPAgent` | [`rl.py`][rl] |

knowledge.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,97 @@ def add_or(examples_so_far, h):
114114
# ______________________________________________________________________________
115115

116116

117+
def version_space_learning(examples):
118+
""" [Figure 19.3]
119+
The version space is a list of hypotheses, which in turn are a list
120+
of dictionaries/disjunctions."""
121+
V = all_hypotheses(examples)
122+
for e in examples:
123+
if V:
124+
V = version_space_update(V, e)
125+
126+
return V
127+
128+
129+
def version_space_update(V, e):
130+
return [h for h in V if is_consistent(e, h)]
131+
132+
133+
def all_hypotheses(examples):
134+
"""Builds a list of all the possible hypotheses"""
135+
values = values_table(examples)
136+
h_powerset = powerset(values.keys())
137+
hypotheses = []
138+
for s in h_powerset:
139+
hypotheses.extend(build_attr_combinations(s, values))
140+
141+
hypotheses.extend(build_h_combinations(hypotheses))
142+
143+
return hypotheses
144+
145+
146+
def values_table(examples):
147+
"""Builds a table with all the possible values for each attribute.
148+
Returns a dictionary with keys the attribute names and values a list
149+
with the possible values for the corresponding attribute."""
150+
values = defaultdict(lambda: [])
151+
for e in examples:
152+
for k, v in e.items():
153+
if k == 'GOAL':
154+
continue
155+
156+
mod = '!'
157+
if e['GOAL']:
158+
mod = ''
159+
160+
if mod + v not in values[k]:
161+
values[k].append(mod + v)
162+
163+
values = dict(values)
164+
return values
165+
166+
167+
def build_attr_combinations(s, values):
168+
"""Given a set of attributes, builds all the combinations of values.
169+
If the set holds more than one attribute, recursively builds the
170+
combinations."""
171+
if len(s) == 1:
172+
# s holds just one attribute, return its list of values
173+
k = values[s[0]]
174+
h = [[{s[0]: v}] for v in values[s[0]]]
175+
return h
176+
177+
h = []
178+
for i, a in enumerate(s):
179+
rest = build_attr_combinations(s[i+1:], values)
180+
for v in values[a]:
181+
o = {a: v}
182+
for r in rest:
183+
t = o.copy()
184+
for d in r:
185+
t.update(d)
186+
h.append([t])
187+
188+
return h
189+
190+
191+
def build_h_combinations(hypotheses):
192+
"""Given a set of hypotheses, builds and returns all the combinations of the
193+
hypotheses."""
194+
h = []
195+
h_powerset = powerset(range(len(hypotheses)))
196+
197+
for s in h_powerset:
198+
t = []
199+
for i in s:
200+
t.extend(hypotheses[i])
201+
h.append(t)
202+
203+
return h
204+
205+
# ______________________________________________________________________________
206+
207+
117208
def check_all_consistency(examples, h):
118209
"""Check for the consistency of all examples under h"""
119210
for e in examples:

tests/test_knowledge.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,37 @@ def test_current_best_learning():
2323

2424
assert values == [True, True, True, False, False, False, True]
2525

26+
examples = trivial
27+
initial_h = [{'Pizza': 'Yes'}]
28+
h = current_best_learning(examples, initial_h)
29+
values = []
30+
for e in examples:
31+
values.append(guess_value(e, h))
32+
33+
assert values == [True, True, False]
34+
35+
36+
def test_version_space_learning():
37+
V = version_space_learning(trivial)
38+
results = []
39+
for e in trivial:
40+
guess = False
41+
for h in V:
42+
if guess_value(e, h):
43+
guess = True
44+
break
45+
46+
results.append(guess)
47+
48+
assert results == [True, True, False]
49+
assert [{'Pizza': 'Yes'}] in V
50+
51+
52+
trivial = [
53+
{'Pizza': 'Yes', 'Soda': 'No', 'GOAL': True},
54+
{'Pizza': 'Yes', 'Soda': 'Yes', 'GOAL': True},
55+
{'Pizza': 'No', 'Soda': 'No', 'GOAL': False}
56+
]
2657

2758
animals_umbrellas = [
2859
{'Species': 'Cat', 'Rain': 'Yes', 'Coat': 'No', 'GOAL': True},

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy