Esercizio - Inferenza per enumerazione nella rete burglary (slide del corso)
Testo (slide Bayesian Networks (part 1), corso di Intelligenza Artificiale, Ing. dell'Informazione UniPD). Rete dell'allarme antifurto: (furto), (terremoto), (allarme), (Giovanni chiama), (Maria chiama); archi , , , . CPT: , , , , , , , , , .
- (Domanda a risposta multipla delle slide) Quanto vale ? Opzioni: ; ; ; ; nessuna delle precedenti.
- Calcolare con l'inferenza per enumerazione la distribuzione .
- (Estensione) Calcolare con lo stesso metodo e .
Soluzione
1. Un termine della congiunta
La congiunta si scompone nel prodotto delle CPT (Reti bayesiane - semantica, indipendenze e inferenza esattaUna rete bayesiana è un grafo diretto aciclico (DAG) con una variabile per nodo e una tabella delle probabilità condizionate (CPT) $P(X_i\mid\text{Parents}(X_i))$ per nodo; rappresenta la congiunta come prodotto $P(x_1,\dots,x_n)=\prod_i P(x_i\mid\text{parents}(X_i))$, con molti meno numeri della tabella completa (rete dell'allarme: 10 contro 31). Tre strutture elementari: catena $X\to Y\to Z$ e fork $Y\leftarrow X\to Z$ (estremi indipendenti dato il centro), collider $X\to Z\leftarrow Y$ (indipendenti, ma dipendenti se si osserva $Z$ o un suo discendente). Modelli causali (genitori = cause) danno reti più piccole. Inferenza esatta per enumerazione: $\mathbf P(X\mid\mathbf e)=\alpha\sum_{\mathbf y}\mathbf P(X,\mathbf e,\mathbf y)$ calcolata come somma di prodotti, in profondità e da sinistra a destra; per l'allarme $\mathbf P(B\mid j,m)=\langle0{,}284;\ 0{,}716\rangle$. Molti prodotti si ripetono: l'eliminazione di variabili li salva come fattori e li riusa.Reti bayesiane - semantica, indipendenze e inferenza esatta →); per ogni nodo si prende la riga che corrisponde ai valori dei suoi genitori: Valori: ; ; ; ; . La risposta è la quarta opzione. (Le altre sono errori tipici: per esempio dimenticare usando , o prendere la riga .)
2.
Impostazione. Le variabili nascoste sono e ; l'evidenza è . Dalla marginalizzazione:
Passo 1: scomporre e portare fuori i fattori costanti. non dipende né da né da ; non dipende da .
Passo 2: i prodotti (indipendenti da ): per vale ; per vale .
Passo 3: calcolo di . Somma su per ciascun :
- : ;
- : .
Somma su pesata con : . Moltiplicato per :
Passo 4: calcolo di (stesse operazioni con ):
- : ;
- : ;
- pesata: ;
- per : .
Passo 5: normalizzazione. : Anche con entrambe le telefonate il furto ha probabilità solo : il prior del furto è e l'allarme può suonare anche senza furto (terremoto, oppure falso allarme con in una situazione, , che quasi sempre si verifica).
3. Estensione: e
Il denominatore comune è (somma dei due termini sopra).
- : , con (marginale dell'allarme): ; . Normalizzando: .
- : ; per : . Con il totale si ottiene , cioè (verificato anche per enumerazione completa).
Il valore di () mostra che se entrambi chiamano l'allarme è probabilmente suonato, ma la causa più probabile resta un falso allarme o un terremoto.
Codice
# rete burglary: per ogni variabile (genitori, CPT) con CPT = P(X=vero | genitori)
bn = {
'B': ([], {(): 0.001}),
'E': ([], {(): 0.002}),
'A': (['B', 'E'], {(True, True): 0.95, (True, False): 0.94,
(False, True): 0.29, (False, False): 0.001}),
'J': (['A'], {(True,): 0.90, (False,): 0.05}),
'M': (['A'], {(True,): 0.70, (False,): 0.01}),
}
ordine = ['B', 'E', 'A', 'J', 'M'] # ordine topologico
def prob(var, val, ev):
"""P(var=val | genitori), con i valori dei genitori presi da ev."""
genitori, cpt = bn[var]
p = cpt[tuple(ev[g] for g in genitori)]
return p if val else 1 - p
def enumera_tutto(variabili, ev):
"""Somma sulle variabili non osservate, nell'ordine topologico."""
if not variabili:
return 1.0
v, resto = variabili[0], variabili[1:]
if v in ev: # osservata: un solo termine
return prob(v, ev[v], ev) * enumera_tutto(resto, ev)
return sum(prob(v, x, {**ev, v: x}) * enumera_tutto(resto, {**ev, v: x})
for x in (True, False)) # nascosta: si somma sui due valori
def enumeration_ask(X, ev):
q = [enumera_tutto(ordine, {**ev, X: x}) for x in (True, False)]
alfa = 1 / sum(q) # normalizzazione
return [alfa * p for p in q]
print(enumeration_ask('B', {'J': True, 'M': True}))
print(enumera_tutto(ordine, {'B': True, 'E': False, 'A': True, 'J': True, 'M': False}))Output: [0.2841718353643929, 0.7158281646356071] e 0.00025329240000000004.
Versione ripasso
- Rete: ; , , , , .
- Un termine: .
- Enumerazione (inferenza per enumerazionesomma sulle nascoste dei prodotti delle CPT, poi normalizzazioneReti bayesiane - semantica, indipendenze e inferenza esatta →): con .
- Numeri: , . : (), (); . : , ; .
- Risultato: ; . Inoltre , .
- Errori tipici: usare al posto di ; prendere la riga sbagliata di ; sommare anche sulle variabili osservate; non normalizzare.
- Somme interne (con e ): , , , ; poi pesate con e e moltiplicate per o .
- Totale: ; ().