Ontdekken
Tot nu toe liep de muis blind, en leerde hij van wat hij tegenkwam. Nu kiest
hij zelf: meestal de kant met de hoogste waarde, en soms een willekeurige,
net als kies bij Nim. Nieuw is dat je die keuze zelf schrijft, als methode
kies(vakje, ontdekken).
Voorspel
import random
acties = ["links", "rechts"]
ontdekken = 0
if random.random() < ontdekken:
print(random.choice(acties))
else:
print("de beste")
Wat print dit programma? En wat als ontdekken 1 is?
Antwoord
Bij 0 altijd de beste: random.random() is nooit kleiner dan 0. Bij 1
altijd een willekeurige actie: random.random() is altijd kleiner dan 1.
Zo werkt het
In de verborgen code staat wandel(muis, ontdekken). Die zet de muis in
vakje 2, en laat hem lopen tot de val of de kaas. Bij elke stap vraagt hij
muis.kies(vakje, ontdekken) welke kant de muis op gaat, en daarna leert de
muis met muis.leer. Na 20 stappen geeft wandel het op, voor als de muis
heen en weer blijft lopen. Hij geeft het vakje terug waar de muis eindigt.
kies werkt zoals kies bij
ontdekken in Nim:
met kans ontdekken een willekeurige actie, en anders de beste. Bij CS50 heet
die kans epsilon.
Opdracht: de muis kiest zelf
Schrijf de methode kies(vakje, ontdekken). Laat daarna een nieuwe muis
100 keer wandelen, en tel hoe vaak hij bij de kaas eindigt. Doe dat voor
ontdekken 0, 0.2 en 1:
99 keer kaas met ontdekken 0
98 keer kaas met ontdekken 0.2
56 keer kaas met ontdekken 1
Begin klein, en breid de code stap voor stap uit:
- Draai de code:
kieszegt altijd links, en de muis loopt tien keer in de val, vakje 0. - Laat
kiesde actie met de hoogste waarde teruggeven, zoalsbeste_actiein methoden. Nu loopt hij één keer in de val, en vindt hij daarna de kaas. - Zet daarvoor: met kans
ontdekkeneen willekeurige actie uitacties. - Tel hoe vaak
wandel(piep, ontdekken)in 100 wandelingen 4 teruggeeft, voor ontdekken 0, 0.2 en 1. Begin elke keer metrandom.seed(1)en een nieuwe muis.
Tip
Zet de if met random.random() bovenaan in kies, met een return erin.
Komt Python daar niet langs, dan zoekt hij daaronder de beste actie.
Antwoord
Dit vervangt alles in de editor. De gang blijft in de verborgen code.
import random
class Muis:
def __init__(self):
self.q = {}
self.tempo = 0.5
def waarde(self, vakje, actie):
if (vakje, actie) in self.q:
return self.q[(vakje, actie)]
return 0
def bijwerken(self, vakje, actie, oud, beloning, toekomst):
self.q[(vakje, actie)] = oud + self.tempo * (beloning + toekomst - oud)
def beste_toekomst(self, vakje):
beste = self.waarde(vakje, acties[0])
for actie in acties:
if self.waarde(vakje, actie) > beste:
beste = self.waarde(vakje, actie)
return beste
def kies(self, vakje, ontdekken):
if random.random() < ontdekken:
return random.choice(acties)
beste = acties[0]
for actie in acties:
if self.waarde(vakje, actie) > self.waarde(vakje, beste):
beste = actie
return beste
def leer(self, vakje, actie, nieuw, beloning):
oud = self.waarde(vakje, actie)
toekomst = self.beste_toekomst(nieuw)
self.bijwerken(vakje, actie, oud, beloning, toekomst)
for ontdekken in [0, 0.2, 1]:
random.seed(1)
piep = Muis()
kaas = 0
for keer in range(100):
if wandel(piep, ontdekken) == 4:
kaas = kaas + 1
print(kaas, "keer kaas met ontdekken", ontdekken)
99 keer kaas met ontdekken 0
98 keer kaas met ontdekken 0.2
56 keer kaas met ontdekken 1
Zonder ontdekken vindt de muis de kaas het vaakst. Toch klopt zijn tabel dan niet overal: een stap die hij na het begin nooit meer zet, zoals links in vakje 3, houdt een waarde die niet klopt. Met ontdekken 1 kent hij de gang het best, maar loopt hij als een blinde. Een kleine kans zoals 0.2 doet allebei: hij leert de gang kennen, en vindt toch bijna altijd de kaas.
Door naar de route van de muis.