Esercizio - Campionamento - rejection sampling e likelihood weighting sulla rete sprinkler (slide del corso)
Testo (slide Bayesian Networks (part 2), corso di Intelligenza Artificiale, Ing. dell'Informazione UniPD). Rete sprinkler: archi , , , ( cielo nuvoloso, sprinkler, pioggia, prato bagnato); ; (), (); (), (); (), (), (), ().
- Rejection sampling. Per stimare si generano campioni con il prior sampling: hanno e vengono scartati; dei restanti con , hanno e hanno . Qual è la distribuzione condizionata approssimata? Confrontarla con il valore esatto.
- Likelihood weighting. Query con ordine topologico : calcolare il peso di un campione e, dato il campione di eventi delle slide (tutti con e veri, campionati), stimare la distribuzione. L'esercizio delle slide è: verificare che i risultati siano simili alle probabilità esatte.
- Gibbs sampling. Per la query , con stato iniziale , calcolare le distribuzioni condizionate dei due passi dell'esempio e confrontare la stima con il valore esatto.
- Quiz sul Markov blanket. Qual è il Markov blanket di (Cloudy, Rain, GrassWet, nessuno dei precedenti)?
Soluzione
1. Rejection sampling
Stima. Si normalizza il vettore dei conteggi sui campioni accettati: Esatto. e , quindi . La stima () è troppo alta: con soli campioni utili lo scarto tipico è , e dista circa uno scarto tipico dal valore esatto. Inoltre la frazione di campioni accettati attesa è ( su : in linea). Con campioni la stima è – a seconda del seme, con circa campioni accettati.
2. Likelihood weighting
Peso di un campione. Evidenza ; si campionano e . Peso (il fattore per e per ):
| campione | |
|---|---|
Stima dai campioni. Le slide mostrano campioni con , campioni con e campioni con : Esatto (enumerazione, nascosta): La stima da campioni () è vicina al valore esatto (). Con il codice sotto dà .
3. Gibbs sampling
Variabili libere: e (evidenza fissata). Stato iniziale .
- Ricampionare con blanket (genitori nessuno, figli e ): : per , per ; normalizzando, . Si estrae da : nell'esempio esce .
- Ricampionare con blanket : : per , per ; . Nell'esempio esce : stato .
Esatto. e : . La stima delle slide ( volte su passi: ) è vicina. Con passi dopo di burn-in: .
4. Markov blanket di
ha genitore , figlio e ha un altro genitore, . Dunque il blanket è = : sono corrette tutte e tre le prime opzioni (e quindi "nessuna delle precedenti" è sbagliata). Per vale .
Codice
import random
# rete sprinkler: (genitori, CPT = P(X=vero | genitori))
bn = {
'C': ([], {(): 0.5}),
'S': (['C'], {(True,): 0.1, (False,): 0.5}),
'R': (['C'], {(True,): 0.8, (False,): 0.1}),
'G': (['S', 'R'], {(True, True): 0.95, (True, False): 0.90,
(False, True): 0.90, (False, False): 0.10}),
}
ordine = ['C', 'S', 'R', 'G'] # ordine topologico
def p_vero(var, val):
genitori, cpt = bn[var]
return cpt[tuple(val[g] for g in genitori)]
def prior_sample(rng):
val = {}
for x in ordine: # dai genitori ai figli
val[x] = rng.random() < p_vero(x, val)
return val
def rejection(X, ev, N, rng):
c = {True: 0, False: 0}
for _ in range(N):
s = prior_sample(rng)
if all(s[k] == v for k, v in ev.items()): # scarta se contraddice l'evidenza
c[s[X]] += 1
tot = c[True] + c[False]
return c[True] / tot, tot
def likelihood_weighting(X, ev, N, rng):
W = {True: 0.0, False: 0.0}
for _ in range(N):
val, w = dict(ev), 1.0
for x in ordine:
p = p_vero(x, val)
if x in ev:
w *= p if ev[x] else 1 - p # evidenza: si pesa, non si campiona
else:
val[x] = rng.random() < p # altrimenti si campiona
W[val[X]] += w
return W[True] / (W[True] + W[False])
def gibbs(X, ev, N, rng, burn=1000):
val = {x: rng.random() < 0.5 for x in ordine}
val.update(ev)
libere = [x for x in ordine if x not in ev]
figli = {x: [y for y in ordine if x in bn[y][0]] for x in ordine}
def p_cond(x): # P(x=vero | Markov blanket)
pesi = []
for v in (True, False):
val[x] = v
p = p_vero(x, val) if v else 1 - p_vero(x, val)
for y in figli[x]:
py = p_vero(y, val)
p *= py if val[y] else 1 - py
pesi.append(p)
return pesi[0] / (pesi[0] + pesi[1])
cont = 0
for i in range(N + burn):
x = rng.choice(libere) # una variabile libera alla volta
val[x] = rng.random() < p_cond(x)
if i >= burn:
cont += val[X]
return cont / N
rng = random.Random(1)
print(rejection('R', {'S': True}, 100000, rng))
print(likelihood_weighting('R', {'C': True, 'G': True}, 100000, rng))
print(gibbs('R', {'S': True, 'G': True}, 100000, rng))Output (seme ): (0.2127..., 30204), 0.9533..., 0.22344; valori esatti , , . Con altri semi cambiano le ultime cifre: ad esempio la rejection con campioni dà (seme ) e il likelihood weighting con campioni (seme ), con campioni , con .
Versione ripasso
- Rete: ; ; ; .
- Rejection (rejection samplingsi scartano i campioni incoerenti con l'evidenza e si normalizzano i conteggiInferenza approssimata nelle reti bayesiane - campionamento →): ; esatto . Accettati .
- Likelihood weighting (): : (), (), (). Slide: , , stima ; esatto .
- Gibbs (): ; ; esatto ; slide .
- Markov blanket di : (genitore, altro genitore del figlio e figlio).
- Errori tipici: non normalizzare i pesi; dimenticare nel peso; usare nel blanket solo genitori e figli senza gli altri genitori dei figli.
- Accettazione e precisione: con campioni la rejection ne tiene circa (qui ); lo scarto tipico della stima è , e dista circa uno scarto da . Con campioni: (seme ), (seme ), accettati.
- Esatti da ricordare: ; e ; e .
- Likelihood weighting con più campioni: (seme ): , , , , verso .
- Gibbs: si ricampiona solo o (le altre variabili sono evidenza), la scelta della variabile è casuale e ogni stato è un campione; passi dopo di scarto: .