Esercizio - Probabilità dai dati - voti e meteo di Padova (laboratorio 5)
Testo (laboratorio 5, Probability and Bayesian networks, part A, corso di Intelligenza Artificiale, Ing. dell'Informazione UniPD). Due parti: un esempio sul calcolo di probabilità da una tabella e l'esercizio del laboratorio.
Esempio (voti). La tabella elenca studenti con il voto finale (A, B o C) ottenuto al primo, secondo e terzo anno. Con tre variabili per i voti dei tre anni, come si calcolano probabilità come , , ?
| Studente | |||
|---|---|---|---|
| John | A | A | B |
| Sarah | C | C | B |
| Eric | A | B | B |
| Paul | B | C | A |
| Susanne | A | A | A |
| Beth | B | A | B |
| Jack | B | C | B |
| Rachel | B | A | A |
| Tom | B | C | C |
| Jenny | B | A | B |
Esercizio (meteo di Padova). Il file (finto) padua_weather.csv contiene lo storico del tempo a Padova: per ogni giorno della settimana, per un anno intero ( settimane), il tempo è piovoso (), nuvoloso () o soleggiato (). Dopo aver formalizzato il problema (variabili aleatorie e formule necessarie), scrivere un programma Python che legge il dataset e calcola:
- la probabilità che sia soleggiato nel fine settimana (uno o entrambi i giorni);
- il tempo atteso per ogni giorno della settimana (un valore atteso di si interpreta come "un misto di nuvoloso e soleggiato");
- supponendo di non sapere che giorno è oggi (poco realistico), come indovinarlo solo dal tempo.
Parte 1: probabilità da una tabella
Si assume che la tabella rappresenti la vera distribuzione : una probabilità è una frequenza (Incertezza - probabilità, regola di Bayes e indipendenza condizionataUn agente con osservazioni parziali non può usare regole logiche rigide ("mal di denti implica carie" è falso): usa la probabilità come grado di credenza e, con la teoria dell'utilità, sceglie l'azione con utilità attesa massima. Strumenti: distribuzione congiunta completa (tabella di $2^n$ valori), marginalizzazione $P(Y\mid e)=\alpha\sum_h P(Y,e,h)$ con costante di normalizzazione $\alpha=1/P(e)$, regola del prodotto $P(a,b)=P(a\mid b)P(b)$, regola di Bayes $P(\text{causa}\mid\text{effetto})=\frac{P(\text{effetto}\mid\text{causa})P(\text{causa})}{P(\text{effetto})}$ e indipendenza condizionata $P(a,b\mid c)=P(a\mid c)P(b\mid c)$, che permette di scomporre la congiunta in tabelle più piccole. Un test con sensibilità 73% e falsi positivi 12% su una malattia con prior 1/700 dà una probabilità a posteriori di appena 0,9%.Incertezza - probabilità, regola di Bayes e indipendenza condizionata →). Più dati si hanno, meglio è, purché coprano bene la distribuzione.
- : tre al primo anno (John, Eric, Susanne): .
- : tre casi (Paul, Jack, Tom): .
- , per conteggio: quattro studenti con (Sarah, Paul, Jack, Tom); tra questi solo Paul ha : .
- Dalla definizione : (Paul), , quindi . Stesso risultato: condizionare significa restringersi alle righe in cui la condizione è vera.
import numpy as np
voti = np.array([["A","A","B"],["C","C","B"],["A","B","B"],["B","C","A"],["A","A","A"],
["B","A","B"],["B","C","B"],["B","A","A"],["B","C","C"],["B","A","B"]])
g1, g2, g3 = voti[:, 0], voti[:, 1], voti[:, 2]
print(np.mean(g1 == "A")) # P(G1=A)
print(np.mean((g1 == "B") & (g2 == "C"))) # P(G1=B, G2=C)
print(np.mean((g2 == "C") & (g3 == "A")) / np.mean(g2 == "C")) # P(G3=A | G2=C)Output: 0.3, 0.3, 0.25.
Parte 2: meteo di Padova
Formalizzazione. Due variabili: il tempo e il giorno . Ogni riga del file è una settimana, ogni colonna un giorno; dunque è la frazione di settimane in cui, in quel giorno, il tempo è .
1. Sole nel fine settimana
La domanda è la probabilità dell'unione "sabato soleggiato o domenica soleggiato" (si conta ogni settimana una volta sola). Dalla soluzione del corso, settimane su hanno almeno un giorno soleggiato: Con sabati e domeniche soleggiati (dai conteggi sotto), weekend hanno entrambi i giorni soleggiati: sommare conterebbe due volte quelle settimane.
2. Tempo atteso per giorno
. Per il lunedì: piovosi, nuvolosi, soleggiati su : È la media dei valori della colonna. Per i sette giorni: . Il weekend è più "piovoso" (valori più bassi).
3. Indovinare il giorno dal tempo
Si usa la regola di Bayes: si cerca e si prende il giorno più probabile (massimo a posteriori). Poiché ha prior uniforme (), , cioè basta contare quanti giorni di quel tipo ci sono per ogni giorno della settimana. Con tempo piovoso: tra i giorni piovosi, lunedì, martedì, mercoledì, giovedì, venerdì, sabato, domeniche: Se piove, il giorno più probabile è la domenica. Con le stesse tabelle: se è nuvoloso (totale ), il giorno più probabile è il sabato (); se c'è il sole (totale ), il lunedì (). La normalizzazione per non cambia quale giorno vince, ma serve per avere una probabilità.
Codice
import numpy as np
dati = np.loadtxt("padua_weather.csv", delimiter=",", skiprows=1, dtype=int) # 52 settimane x 7 giorni
n_sett = dati.shape[0]
# 1) P(almeno uno tra sabato e domenica soleggiato)
p_weekend = np.mean((dati[:, 5] == 3) | (dati[:, 6] == 3))
print(p_weekend)
# 2) tempo atteso per giorno: E(W | D=d) = somma_y y P(W=y | D=d)
valori = np.array([1, 2, 3])
P_W_D = np.stack([(dati == y).mean(axis=0) for y in valori]) # riga y, colonna giorno
print(valori @ P_W_D)
# 3) indovinare il giorno dal tempo: P(D | W=w)
conteggi = np.stack([(dati == y).sum(axis=0) for y in valori]) # 3 x 7
P_D_w = conteggi / conteggi.sum(axis=1, keepdims=True)
print(P_D_w.round(3))
print(np.argmax(P_D_w, axis=1) + 1) # giorno piu' probabile (lunedi = 1, ..., domenica = 7)Output atteso (uguale a quello della soluzione del corso): 0.4423076923076923; [2.077 1.981 2.038 1.942 1.962 1.846 1.75 ]; le tre righe di (la prima è quella sopra) e [7 6 1].
Nota sulla verifica. Il file CSV originale non è fra i materiali: i conteggi (piovosi ; nuvolosi ; soleggiati ) sono stati ricavati dalle probabilità stampate nella soluzione del corso (sono coerenti: ogni giorno somma a e le righe a , , ). Il codice qui sopra è stato eseguito su un dataset ricostruito con questi conteggi e weekend con almeno un giorno soleggiato, e riproduce tutti gli output del corso. La soluzione del corso usa pandas e gdown; la versione qui è equivalente, con solo numpy.
Versione ripasso
- Probabilità da una tabella = frequenze. ; ; (condizionare = restringersi alle righe con la condizione vera).
- Meteo: , = giorno. Sole nel weekend (unione, ogni settimana una volta): ().
- Tempo atteso: ; lunedì ; domenica (la più piovosa).
- Indovinare il giorno: per Bayes, con prior uniformeIncertezza - probabilità, regola di Bayes e indipendenza condizionata →, poi il massimo: pioggia domenica (), nuvoloso sabato, sole lunedì.
- Errori tipici: sommare senza togliere l'intersezione; non normalizzare per il totale di quel tempo; confondere con .
- Conteggi del meteo (piovoso, nuvoloso, soleggiato per lu, ma, me, gi, ve, sa, do): piovoso (totale ); nuvoloso (); soleggiato (); ogni giorno somma a .
- Tempo atteso: (weekend più piovoso).
- Sole nel weekend: sabati e domeniche soleggiati, weekend con entrambi.
- Giorno più probabile dato il tempo: piovoso domenica (), nuvoloso sabato (), soleggiato lunedì (); in codice
np.argmax(P_D_w, axis=1) + 1dà[7 6 1]. - Verifica: il CSV originale non è disponibile; il codice (solo
numpy,np.loadtxt) riproduce gli output del corso su un dataset ricostruito con gli stessi conteggi.