{ "cells": [ { "attachments": {}, "cell_type": "markdown", "id": "3dca7bbb-b8df-4815-8222-fd145dea8717", "metadata": {}, "source": [ "# ✏️ Esercizi" ] }, { "cell_type": "markdown", "id": "b41bb8cd-5c0a-46ea-9a60-63b9249498ca", "metadata": {}, "source": [ "## Preparazione del Notebook" ] }, { "cell_type": "code", "execution_count": 2, "id": "3a5a0852-abb5-46bc-a8f8-d1d5f7d538eb", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import matplotlib as mpl\n", "import matplotlib.pyplot as plt\n", "import arviz as az\n", "import seaborn as sns" ] }, { "cell_type": "code", "execution_count": 3, "id": "01c7391f-333e-4ac0-b7f1-f1e1a5931c59", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_format = 'retina'\n", "RANDOM_SEED = 42\n", "rng = np.random.default_rng(RANDOM_SEED)\n", "az.style.use(\"arviz-darkgrid\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "5a448a6b-64ed-4b63-8dbe-45893df0f57d", "metadata": {}, "source": [ "### Il problema delle due urne\n", "\n", "Supponiamo che vi siano due urne.\n", "\n", "- L'urna 1 ($U_1$) contiene 30 palline bianche (B) e 10 palline nere (N).\n", "- L'urna 2 ($U_2$) contiene 20 palline bianche e 20 palline nere.\n", "\n", "Supponiamo di scegliere una delle urne a caso e, senza guardare, di scegliere una pallina a caso. Se la pallina è bianca, qual è la probabilità che provenga dall'urna 1?\n", "\n", "Quello che vogliamo è la probabilità condizionata che abbiamo scelto dall'Urna 1 dato che abbiamo ottenuto una pallina bianca, $P(U_1 \\mid B)$.\n", "\n", "Il problema ci fornisce le seguenti informazioni:\n", "\n", "- $P(B \\mid U_1)$ = 3/4,\n", "- $P(B \\mid U_2)$ = 1/2.\n", "\n", "Il teorema di Bayes ci dice come le informazioni a disposizione si possono mettere in relazione con la domanda del problema:\n", "\n", "$$\n", "P(U_1 \\mid B) = \\frac{P(B \\mid U_1) P(U_1)}{P(B)}\n", "$$\n", "\n", "Per calcolare la probabilità $P(B)$ usiamo il teorema della probabilità totale:\n", "\n", "$$\n", "P(B) = P(B \\mid U_1) P(U_1) + P(B \\mid U_2) P(U_2),\n", "$$\n", "\n", "ovvero\n", "\n", "$$\n", "P(B) = 3/4 \\cdot 1/2 + 1/2 \\cdot 1/2 = 5/8.\n", "$$\n", "\n", "Concludiamo applicando il teorema di Bayes:\n", "\n", "$$\n", "P(U_1 \\mid B) = \\frac{3/4 \\cdot 1/2}{5/8} = 3/5.\n", "$$\n" ] }, { "attachments": {}, "cell_type": "markdown", "id": "b3c30fa9-c0e9-4174-a8e1-451418f2de20", "metadata": {}, "source": [ "Il processo di aggiornamento bayesiano può essere anche svolto nel modo seguente. Riscrivo il teorema di Bayes nel modo seguente:\n", "\n", "$$\n", "P(H \\mid D) = \\frac{P(D \\mid H) P(H)}{P(D)}\n", "$$" ] }, { "attachments": {}, "cell_type": "markdown", "id": "1957506a-4ffd-4731-9921-8b609ab12bfd", "metadata": {}, "source": [ "La probabilità $P(H)$ è la probabilità delle ipotesi prima di avere osservato i dati. Nel nostro caso, le due ipotesi sono \"Urna 1\" e \"Urna 2\", entrambe con la stessa probabilità, dato che non abbiamo ragioni a priori per dare più peso ad un'ipotesi rispetto all'altra. Costruiamo una tabella con un DataFrame in cui inseriamo la colonna `prior`:" ] }, { "cell_type": "code", "execution_count": 21, "id": "0760591a-ec48-4d4e-8d5a-f8290b44871d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
prior
Urn 10.5
Urn 20.5
\n", "
" ], "text/plain": [ " prior\n", "Urn 1 0.5\n", "Urn 2 0.5" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table = pd.DataFrame(index=[\"Urn 1\", \"Urn 2\"])\n", "table[\"prior\"] = 1 / 2, 1 / 2\n", "table" ] }, { "attachments": {}, "cell_type": "markdown", "id": "4949b830-3e18-476b-adb8-53dd5380b2fb", "metadata": {}, "source": [ "La probabilità $P(D \\mid H)$ è la probabilità dei dati, data l'ipotesi. È chiamata verosimiglianza. La probabilità di una pallina bianca dato che viene estratta dall'Urna 1 è 3/4. La probabilità di una pallina bianca dato che viene estratta dall'Urna 1 è 1/2. Aggiungo alla tabella la colonna `likelihood`." ] }, { "cell_type": "code", "execution_count": 22, "id": "bb3a7837-5821-4246-bff1-ef89b0a94467", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
priorlikelihood
Urn 10.50.75
Urn 20.50.50
\n", "
" ], "text/plain": [ " prior likelihood\n", "Urn 1 0.5 0.75\n", "Urn 2 0.5 0.50" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table[\"likelihood\"] = 3 / 4, 1 / 2\n", "table" ] }, { "attachments": {}, "cell_type": "markdown", "id": "38657867-09d6-4621-800e-8644c794be1a", "metadata": {}, "source": [ "La probabilità $P(H \\mid D)$ è la probabilità dell'ipotesi dopo avere osservato i dati. Si ottiene come il prodotto della verosimiglianza per la probabilità a priori, diviso per una *costante di normalizzazione*. Iniziamo a calcolare il la distribuzione a posteriori non normalizzata." ] }, { "cell_type": "code", "execution_count": 23, "id": "a0025d79-766e-4bba-b444-68224481f32a", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
priorlikelihoodunnorm
Urn 10.50.750.375
Urn 20.50.500.250
\n", "
" ], "text/plain": [ " prior likelihood unnorm\n", "Urn 1 0.5 0.75 0.375\n", "Urn 2 0.5 0.50 0.250" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table[\"unnorm\"] = table[\"prior\"] * table[\"likelihood\"]\n", "table" ] }, { "attachments": {}, "cell_type": "markdown", "id": "b8472a91-bbce-4680-9d56-2f207ab2686e", "metadata": {}, "source": [ "La probabilità dei dati, $P(D)$, ovvero il numeratore bayesiano, è dato dalla somma di tutti i valori della distribuzione a posteriori non normalizzata:" ] }, { "cell_type": "code", "execution_count": 24, "id": "be7d4f40-8a32-4440-acf0-d69eb586ab22", "metadata": {}, "outputs": [], "source": [ "prob_data = table[\"unnorm\"].sum()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "2f5a6d7c-a674-49e4-ac47-7a6abe64bda4", "metadata": {}, "source": [ "Possiamo ora normalizzare la distribuzione a posteriori:" ] }, { "cell_type": "code", "execution_count": 25, "id": "334b3018-8f30-4fce-b71f-8654403db366", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
priorlikelihoodunnormposterior
Urn 10.50.750.3750.6
Urn 20.50.500.2500.4
\n", "
" ], "text/plain": [ " prior likelihood unnorm posterior\n", "Urn 1 0.5 0.75 0.375 0.6\n", "Urn 2 0.5 0.50 0.250 0.4" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table[\"posterior\"] = table[\"unnorm\"] / prob_data\n", "table" ] }, { "attachments": {}, "cell_type": "markdown", "id": "fd862ee5-5166-456c-99ae-419fd72dbd02", "metadata": {}, "source": [ "### Il problema dei dadi\n", "\n", "Il metodo precedente può anche essere usato quando ci sono più di due ipotesi. {cite:t}`downey2021think` discute il seguente problema. Supponiamo che nell'Urna 1 ci sia un dado a 6 facce, nell'Urna 2 un dado a 8 facce e nell'Urna 3 un dado a 12 facce. Un dado viene estratto a caso da un'urna e produce il risultato 1. Qual è la probabilità che ho usato un dado a 6 facce?\n", "\n", "Inizio a definire le tre ipotesi." ] }, { "cell_type": "code", "execution_count": 26, "id": "64d3a7aa-0ec8-474f-9aa1-ecee0d73bf2c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
6
8
12
\n", "
" ], "text/plain": [ "Empty DataFrame\n", "Columns: []\n", "Index: [6, 8, 12]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table2 = pd.DataFrame(index=[6, 8, 12])\n", "table2" ] }, { "attachments": {}, "cell_type": "markdown", "id": "51f915d1-55d7-46c3-a8ab-c9fda6831d73", "metadata": {}, "source": [ "Per evitare arrotondamenti uso la funzione `Fraction()`. Inizio a definire la distribuzione a priori." ] }, { "cell_type": "code", "execution_count": 27, "id": "a1d63cce-ea2b-498c-b47b-9d506ec0b082", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
prior
61/3
81/3
121/3
\n", "
" ], "text/plain": [ " prior\n", "6 1/3\n", "8 1/3\n", "12 1/3" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from fractions import Fraction\n", "\n", "table2[\"prior\"] = Fraction(1, 3)\n", "table2" ] }, { "attachments": {}, "cell_type": "markdown", "id": "e696d008-3146-4548-a14e-77ca30502ebf", "metadata": {}, "source": [ "Definisco la verosimiglianza. Se il dado è a 6 facce, la probabilità di ottenere 1 è 1/6; se il dado ha 8 facce è 1/8; se il dado ha 12 facce è 1/12." ] }, { "cell_type": "code", "execution_count": 28, "id": "cad9e96a-e6ec-4e00-a30f-ea066caf6741", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
priorlikelihood
61/31/6
81/31/8
121/31/12
\n", "
" ], "text/plain": [ " prior likelihood\n", "6 1/3 1/6\n", "8 1/3 1/8\n", "12 1/3 1/12" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table2[\"likelihood\"] = Fraction(1, 6), Fraction(1, 8), Fraction(1, 12)\n", "table2" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3f25bffe-bc1c-45b3-bfed-6cc1ad647a35", "metadata": {}, "source": [ "Trovo la distribuzione a posteriori non normalizzata." ] }, { "cell_type": "code", "execution_count": 29, "id": "11e5e720-b365-4b18-9216-4f8b09464f1f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
priorlikelihoodunnorm
61/31/61/18
81/31/81/24
121/31/121/36
\n", "
" ], "text/plain": [ " prior likelihood unnorm\n", "6 1/3 1/6 1/18\n", "8 1/3 1/8 1/24\n", "12 1/3 1/12 1/36" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table2[\"unnorm\"] = table2[\"prior\"] * table2[\"likelihood\"]\n", "table2" ] }, { "attachments": {}, "cell_type": "markdown", "id": "457a877a-1ea0-4ba1-9def-64fe1106d0d9", "metadata": {}, "source": [ "Normalizzo." ] }, { "cell_type": "code", "execution_count": 30, "id": "a0f4a0f4-13cd-44b0-b812-74a9050ddd2b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
priorlikelihoodunnormposterior
61/31/61/184/9
81/31/81/241/3
121/31/121/362/9
\n", "
" ], "text/plain": [ " prior likelihood unnorm posterior\n", "6 1/3 1/6 1/18 4/9\n", "8 1/3 1/8 1/24 1/3\n", "12 1/3 1/12 1/36 2/9" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "prob_data = table2[\"unnorm\"].sum()\n", "table2[\"posterior\"] = table2[\"unnorm\"] / prob_data\n", "table2" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3d31b96a-d077-4ff7-bc32-9f0699e95646", "metadata": {}, "source": [ "La probabilità posteriore del dado a 6 facce è 4/9, che è più grande delle probabilità degli altri dadi, 3/9 e 2/9. Intuitivamente, il dado a 6 facce è il più probabile perché ha la probabilità più grande di produrre il risultato che abbiamo osservato." ] }, { "cell_type": "markdown", "id": "88be1c01-e642-4545-b144-d6372fabdec7", "metadata": {}, "source": [ "### L'errore dell'avvocato difensore\n", "\n", "Una donna è stata assassinata e il marito è sotto processo per questo crimine. Durante il processo emerge che l'imputato aveva un passato di abusi sulla moglie. L'avvocato difensore sostiene che questa prova dovrebbe essere esclusa perché irrilevante, dato che solo 1 uomo su 10000 che abusa della moglie finisce poi per ucciderla. Dovrebbe il giudice accettare la richiesta dell'avvocato difensore di escludere questa prova?\n", "\n", "Supponiamo che la cifra 1 su 10000 fornita dall'avvocato difensore sia corretta e assumiamo inoltre le seguenti probabilità per una popolazione rilevante di mariti e mogli: 1 marito su 10 abusa della moglie, 1 moglie su 5 assassinata viene uccisa dal marito, e il 50% dei mariti che uccidono le loro mogli le aveva precedentemente abusate.\n", "\n", "Definiamo $ A $ come l'evento in cui il marito abusa della moglie, e $ G $ come l'evento in cui il marito è colpevole. L'argomento della difesa è che $ P(G \\mid A) = \\frac{1}{10000} $, quindi la colpevolezza è estremamente improbabile condizionata a una storia pregressa di abusi.\n", "\n", "Tuttavia, l'avvocato difensore omette di considerare un fatto cruciale: in questo caso, sappiamo che la moglie è stata assassinata. Pertanto, la probabilità rilevante non è $ P(G \\mid A) $, ma $ P(G \\mid A,M) $, dove $ M $ è l'evento in cui la moglie è stata assassinata.\n", "\n", "Applicando la regola di Bayes con un ulteriore fattore di condizionamento, otteniamo:\n", "\n", "$$\n", "P(G \\mid A,M) = \\frac{P(A \\mid G,M)P(G \\mid M)}{P(A \\mid G,M)P(G \\mid M) + P(A \\mid G^c,M)P(G^c \\mid M)} \n", "= \\frac{0.5 \\cdot 0.2}{0.5 \\cdot 0.2 + 0.1 \\cdot 0.8} \n", "= \\frac{59}{100}.\n", "$$\n", "\n", "La condizionata della Regola di Bayes e include le seguenti componenti:\n", "\n", "- $ P(G \\mid A,M) $: La probabilità che il marito sia colpevole, dato che ha abusato della moglie e che questa è stata assassinata.\n", "- $ P(A \\mid G,M) $: La probabilità che il marito abbia abusato della moglie, dato che è colpevole e che la moglie è stata assassinata. Questa è stata assunta come $0.5$ nel problema.\n", "- $ P(G \\mid M) $: La probabilità che il marito sia colpevole, dato che la moglie è stata assassinata. Questa è stata assunta come $0.2$ nel problema.\n", "- $ P(A \\mid G^c,M) $: La probabilità che il marito abbia abusato della moglie, dato che non è colpevole ma la moglie è stata assassinata. Questa è stata assunta come $0.1$ nel problema.\n", "- $ P(G^c \\mid M) $: La probabilità che il marito non sia colpevole, dato che la moglie è stata assassinata. Questa è semplicemente $1 - P(G \\mid M) = 0.8$.\n", "\n", "La formula permette di combinare diverse fonti di informazione per arrivare a una stima più accurata della probabilità di colpevolezza. In questo caso, la probabilità a posteriori di colpevolezza, $ P(G \\mid A,M) $, si rivela essere molto più alta della probabilità iniziale $ P(G \\mid A) $ proposta dall'avvocato difensore. Pertanto, contrariamente all'argomento dell'avvocato, la storia di abusi del marito è un'informazione molto importante che non dovrebbe essere ignorata nel processo. Condizionando sulla prova degli abusi, la probabilità di colpevolezza sale da $ P(G \\mid M) = 0.2 $ a $ P(G \\mid A,M) \\approx 0.59 $, contraddicendo quindi l'argomento dell'avvocato difensore.\n", "\n", "Nel calcolo di $ P(G \\mid A,M) $, non abbiamo utilizzato la probabilità $ P(G\\mid A) $ fornita dall'avvocato difensore; è irrilevante per il nostro calcolo perché non tiene conto del fatto che la moglie è stata assassinata. \n", "\n", "Questo esempio mette in evidenza come sia necessario condizionare su tutte le prove disponibili. Inoltre, questo esempio mette in luce le complessità e le potenziali insidie nell'utilizzo della probabilità condizionata, soprattutto quando sono in gioco variabili di confondimento." ] }, { "cell_type": "markdown", "id": "a5f31d80-9217-44ff-bbe0-0a58586f34f6", "metadata": {}, "source": [ "## Watermark" ] }, { "cell_type": "code", "execution_count": 14, "id": "81fad084-8635-4f05-84b1-6752c753a0f0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Last updated: Sat Mar 16 2024\n", "\n", "Python implementation: CPython\n", "Python version : 3.11.8\n", "IPython version : 8.22.2\n", "\n", "Compiler : Clang 16.0.6 \n", "OS : Darwin\n", "Release : 23.4.0\n", "Machine : arm64\n", "Processor : arm\n", "CPU cores : 8\n", "Architecture: 64bit\n", "\n", "seaborn : 0.13.2\n", "pandas : 2.2.1\n", "matplotlib: 3.8.3\n", "numpy : 1.26.4\n", "arviz : 0.17.0\n", "\n", "Watermark: 2.4.3\n", "\n" ] } ], "source": [ "%load_ext watermark\n", "%watermark -n -u -v -iv -w -m" ] } ], "metadata": { "kernelspec": { "display_name": "pymc", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" }, "vscode": { "interpreter": { "hash": "cbb367cc0128e23b7454d788d5a4229ca1f9848fd2e857f4797fbd26ab3b0776" } } }, "nbformat": 4, "nbformat_minor": 2 }