You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ML-For-Beginners/translations/it/2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb

686 lines
31 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Costruire un modello di regressione logistica - Lezione 4\n",
"\n",
"![Infografica: regressione logistica vs. regressione lineare](../../../../../../translated_images/linear-vs-logistic.ba180bf95e7ee66721ba10ebf2dac2666acbd64a88b003c83928712433a13c7d.it.png)\n",
"\n",
"#### **[Quiz pre-lezione](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n",
"\n",
"#### Introduzione\n",
"\n",
"In questa ultima lezione sulla Regressione, una delle tecniche *classiche* di ML di base, daremo uno sguardo alla Regressione Logistica. Utilizzeresti questa tecnica per scoprire schemi utili a prevedere categorie binarie. Questa caramella è al cioccolato o no? Questa malattia è contagiosa o no? Questo cliente sceglierà questo prodotto o no?\n",
"\n",
"In questa lezione imparerai:\n",
"\n",
"- Tecniche per la regressione logistica\n",
"\n",
"✅ Approfondisci la tua comprensione di questo tipo di regressione in questo [modulo di apprendimento](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n",
"\n",
"## Prerequisiti\n",
"\n",
"Avendo lavorato con i dati delle zucche, ora siamo abbastanza familiari con essi da capire che c'è una categoria binaria su cui possiamo lavorare: `Color`.\n",
"\n",
"Costruiamo un modello di regressione logistica per prevedere, date alcune variabili, *di che colore è probabile che sia una determinata zucca* (arancione 🎃 o bianca 👻).\n",
"\n",
"> Perché stiamo parlando di classificazione binaria in una lezione dedicata alla regressione? Solo per comodità linguistica, poiché la regressione logistica è [in realtà un metodo di classificazione](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), sebbene basato su un approccio lineare. Scopri altri modi per classificare i dati nel prossimo gruppo di lezioni.\n",
"\n",
"Per questa lezione, avremo bisogno dei seguenti pacchetti:\n",
"\n",
"- `tidyverse`: Il [tidyverse](https://www.tidyverse.org/) è una [collezione di pacchetti R](https://www.tidyverse.org/packages) progettata per rendere la scienza dei dati più veloce, semplice e divertente!\n",
"\n",
"- `tidymodels`: Il framework [tidymodels](https://www.tidymodels.org/) è una [collezione di pacchetti](https://www.tidymodels.org/packages/) per la modellazione e il machine learning.\n",
"\n",
"- `janitor`: Il pacchetto [janitor](https://github.com/sfirke/janitor) fornisce semplici strumenti per esaminare e pulire dati disordinati.\n",
"\n",
"- `ggbeeswarm`: Il pacchetto [ggbeeswarm](https://github.com/eclarke/ggbeeswarm) offre metodi per creare grafici in stile \"beeswarm\" utilizzando ggplot2.\n",
"\n",
"Puoi installarli con il seguente comando:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n",
"\n",
"In alternativa, lo script qui sotto verifica se hai i pacchetti necessari per completare questo modulo e li installa per te nel caso in cui manchino.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load(tidyverse, tidymodels, janitor, ggbeeswarm)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **Definire la domanda**\n",
"\n",
"Per i nostri scopi, esprimeremo la domanda come un binario: 'Bianco' o 'Non Bianco'. Nel nostro dataset esiste anche una categoria 'a righe', ma ci sono pochi casi, quindi non la utilizzeremo. Comunque, questa categoria scompare una volta che rimuoviamo i valori nulli dal dataset.\n",
"\n",
"> 🎃 Curiosità: a volte chiamiamo le zucche bianche 'zucche fantasma'. Non sono molto facili da intagliare, quindi non sono popolari come quelle arancioni, ma hanno un aspetto interessante! Potremmo quindi riformulare la nostra domanda come: 'Fantasma' o 'Non Fantasma'. 👻\n",
"\n",
"## **A proposito della regressione logistica**\n",
"\n",
"La regressione logistica si differenzia dalla regressione lineare, che hai già studiato, in alcuni modi importanti.\n",
"\n",
"#### **Classificazione binaria**\n",
"\n",
"La regressione logistica non offre le stesse funzionalità della regressione lineare. La prima fornisce una previsione su una `categoria binaria` (\"arancione o non arancione\"), mentre la seconda è in grado di prevedere `valori continui`, ad esempio, dato l'origine di una zucca e il momento del raccolto, *quanto aumenterà il suo prezzo*.\n",
"\n",
"![Infografica di Dasani Madipalli](../../../../../../translated_images/pumpkin-classifier.562771f104ad5436b87d1c67bca02a42a17841133556559325c0a0e348e5b774.it.png)\n",
"\n",
"### Altre classificazioni\n",
"\n",
"Esistono altri tipi di regressione logistica, tra cui multinomiale e ordinale:\n",
"\n",
"- **Multinomiale**, che coinvolge più di una categoria - \"Arancione, Bianco e a Righe\".\n",
"\n",
"- **Ordinale**, che coinvolge categorie ordinate, utile se volessimo ordinare i nostri risultati in modo logico, come le nostre zucche ordinate per un numero finito di dimensioni (mini, piccola, media, grande, XL, XXL).\n",
"\n",
"![Regressione multinomiale vs ordinale](../../../../../../translated_images/multinomial-vs-ordinal.36701b4850e37d86c9dd49f7bef93a2f94dbdb8fe03443eb68f0542f97f28f29.it.png)\n",
"\n",
"#### **Le variabili NON devono essere correlate**\n",
"\n",
"Ricordi come la regressione lineare funzionava meglio con variabili più correlate? La regressione logistica è l'opposto: le variabili non devono essere allineate. Questo è utile per i nostri dati, che presentano correlazioni piuttosto deboli.\n",
"\n",
"#### **Hai bisogno di molti dati puliti**\n",
"\n",
"La regressione logistica fornirà risultati più accurati se utilizzi più dati; il nostro piccolo dataset non è ottimale per questo compito, quindi tienilo a mente.\n",
"\n",
"✅ Rifletti sui tipi di dati che si prestano bene alla regressione logistica.\n",
"\n",
"## Esercizio - sistemare i dati\n",
"\n",
"Per prima cosa, pulisci un po' i dati, eliminando i valori nulli e selezionando solo alcune colonne:\n",
"\n",
"1. Aggiungi il seguente codice:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Load the core tidyverse packages\n",
"library(tidyverse)\n",
"\n",
"# Import the data and clean column names\n",
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\") %>% \n",
" clean_names()\n",
"\n",
"# Select desired columns\n",
"pumpkins_select <- pumpkins %>% \n",
" select(c(city_name, package, variety, origin, item_size, color)) \n",
"\n",
"# Drop rows containing missing values and encode color as factor (category)\n",
"pumpkins_select <- pumpkins_select %>% \n",
" drop_na() %>% \n",
" mutate(color = factor(color))\n",
"\n",
"# View the first few rows\n",
"pumpkins_select %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Puoi sempre dare un'occhiata al tuo nuovo dataframe utilizzando la funzione [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html) come mostrato di seguito:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"pumpkins_select %>% \n",
" glimpse()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Confermiamo che stiamo effettivamente affrontando un problema di classificazione binaria:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Subset distinct observations in outcome column\n",
"pumpkins_select %>% \n",
" distinct(color)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Visualizzazione - grafico categorico\n",
"A questo punto hai caricato nuovamente i dati sulle zucche e li hai puliti per ottenere un dataset contenente alcune variabili, tra cui il Colore. Visualizziamo il dataframe nel notebook utilizzando la libreria ggplot.\n",
"\n",
"La libreria ggplot offre modi interessanti per visualizzare i tuoi dati. Ad esempio, puoi confrontare le distribuzioni dei dati per ogni Varietà e Colore in un grafico categorico.\n",
"\n",
"1. Crea un grafico di questo tipo utilizzando la funzione geombar, i dati delle zucche e specificando una mappatura dei colori per ciascuna categoria di zucca (arancione o bianca):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "python"
}
},
"outputs": [],
"source": [
"# Specify colors for each value of the hue variable\n",
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
"\n",
"# Create the bar plot\n",
"ggplot(pumpkins_select, aes(y = variety, fill = color)) +\n",
" geom_bar(position = \"dodge\") +\n",
" scale_fill_manual(values = palette) +\n",
" labs(y = \"Variety\", fill = \"Color\") +\n",
" theme_minimal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Osservando i dati, puoi vedere come i dati sul Colore siano correlati alla Varietà.\n",
"\n",
"✅ Considerando questo grafico categoriale, quali esplorazioni interessanti riesci a immaginare?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Pre-elaborazione dei dati: codifica delle caratteristiche\n",
"\n",
"Il nostro dataset di zucche contiene valori stringa per tutte le sue colonne. Lavorare con dati categorici è intuitivo per gli esseri umani, ma non per le macchine. Gli algoritmi di machine learning funzionano meglio con i numeri. Ecco perché la codifica è un passaggio molto importante nella fase di pre-elaborazione dei dati, poiché ci consente di trasformare i dati categorici in dati numerici senza perdere alcuna informazione. Una buona codifica porta alla costruzione di un buon modello.\n",
"\n",
"Per la codifica delle caratteristiche esistono due tipi principali di encoder:\n",
"\n",
"1. **Ordinal encoder**: è adatto per variabili ordinali, che sono variabili categoriche in cui i dati seguono un ordine logico, come la colonna `item_size` nel nostro dataset. Crea una mappatura in cui ogni categoria è rappresentata da un numero, che corrisponde all'ordine della categoria nella colonna.\n",
"\n",
"2. **Categorical encoder**: è adatto per variabili nominali, che sono variabili categoriche in cui i dati non seguono un ordine logico, come tutte le caratteristiche diverse da `item_size` nel nostro dataset. Si tratta di una codifica one-hot, il che significa che ogni categoria è rappresentata da una colonna binaria: la variabile codificata è uguale a 1 se la zucca appartiene a quella varietà e 0 altrimenti.\n",
"\n",
"Tidymodels offre un altro pacchetto interessante: [recipes](https://recipes.tidymodels.org/) - un pacchetto per la pre-elaborazione dei dati. Definiremo una `recipe` che specifica che tutte le colonne predittive devono essere codificate in un insieme di numeri interi, la `prep` per stimare le quantità e le statistiche necessarie per qualsiasi operazione e infine la `bake` per applicare i calcoli ai nuovi dati.\n",
"\n",
"> Normalmente, recipes viene solitamente utilizzato come preprocessore per la modellazione, dove definisce quali passaggi devono essere applicati a un dataset per prepararlo alla modellazione. In tal caso è **altamente consigliato** utilizzare un `workflow()` invece di stimare manualmente una recipe utilizzando prep e bake. Vedremo tutto questo tra poco.\n",
">\n",
"> Tuttavia, per ora, stiamo utilizzando recipes + prep + bake per specificare quali passaggi devono essere applicati a un dataset per prepararlo all'analisi dei dati e quindi estrarre i dati pre-elaborati con i passaggi applicati.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Preprocess and extract data to allow some data analysis\n",
"baked_pumpkins <- recipe(color ~ ., data = pumpkins_select) %>%\n",
" # Define ordering for item_size column\n",
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
" # Convert factors to numbers using the order defined above (Ordinal encoding)\n",
" step_integer(item_size, zero_based = F) %>%\n",
" # Encode all other predictors using one hot encoding\n",
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE) %>%\n",
" prep(data = pumpkin_select) %>%\n",
" bake(new_data = NULL)\n",
"\n",
"# Display the first few rows of preprocessed data\n",
"baked_pumpkins %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"✅ Quali sono i vantaggi dell'utilizzo di un ordinal encoder per la colonna Item Size?\n",
"\n",
"### Analizzare le relazioni tra le variabili\n",
"\n",
"Ora che abbiamo pre-elaborato i nostri dati, possiamo analizzare le relazioni tra le caratteristiche e l'etichetta per avere un'idea di quanto bene il modello sarà in grado di prevedere l'etichetta a partire dalle caratteristiche. Il modo migliore per effettuare questo tipo di analisi è rappresentare graficamente i dati. \n",
"Utilizzeremo nuovamente la funzione ggplot geom_boxplot_ per visualizzare le relazioni tra Item Size, Variety e Color in un grafico categoriale. Per rappresentare meglio i dati, utilizzeremo la colonna Item Size codificata e la colonna Variety non codificata.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Define the color palette\n",
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
"\n",
"# We need the encoded Item Size column to use it as the x-axis values in the plot\n",
"pumpkins_select_plot<-pumpkins_select\n",
"pumpkins_select_plot$item_size <- baked_pumpkins$item_size\n",
"\n",
"# Create the grouped box plot\n",
"ggplot(pumpkins_select_plot, aes(x = `item_size`, y = color, fill = color)) +\n",
" geom_boxplot() +\n",
" facet_grid(variety ~ ., scales = \"free_x\") +\n",
" scale_fill_manual(values = palette) +\n",
" labs(x = \"Item Size\", y = \"\") +\n",
" theme_minimal() +\n",
" theme(strip.text = element_text(size = 12)) +\n",
" theme(axis.text.x = element_text(size = 10)) +\n",
" theme(axis.title.x = element_text(size = 12)) +\n",
" theme(axis.title.y = element_blank()) +\n",
" theme(legend.position = \"bottom\") +\n",
" guides(fill = guide_legend(title = \"Color\")) +\n",
" theme(panel.spacing = unit(0.5, \"lines\"))+\n",
" theme(strip.text.y = element_text(size = 4, hjust = 0)) \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Utilizzare un grafico a sciame\n",
"\n",
"Poiché il colore è una categoria binaria (Bianco o Non Bianco), necessita di '[un approccio specializzato](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) per la visualizzazione'.\n",
"\n",
"Prova un `grafico a sciame` per mostrare la distribuzione del colore rispetto alla dimensione dell'oggetto.\n",
"\n",
"Utilizzeremo il [pacchetto ggbeeswarm](https://github.com/eclarke/ggbeeswarm), che fornisce metodi per creare grafici in stile sciame utilizzando ggplot2. I grafici a sciame sono un modo per rappresentare punti che normalmente si sovrapporrebbero, disponendoli invece uno accanto all'altro.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Create beeswarm plots of color and item_size\n",
"baked_pumpkins %>% \n",
" mutate(color = factor(color)) %>% \n",
" ggplot(mapping = aes(x = color, y = item_size, color = color)) +\n",
" geom_quasirandom() +\n",
" scale_color_brewer(palette = \"Dark2\", direction = -1) +\n",
" theme(legend.position = \"none\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ora che abbiamo un'idea della relazione tra le categorie binarie di colore e il gruppo più ampio delle dimensioni, esploriamo la regressione logistica per determinare il probabile colore di una determinata zucca.\n",
"\n",
"## Costruisci il tuo modello\n",
"\n",
"Seleziona le variabili che desideri utilizzare nel tuo modello di classificazione e suddividi i dati in set di addestramento e di test. [rsample](https://rsample.tidymodels.org/), un pacchetto di Tidymodels, fornisce un'infrastruttura per una suddivisione e un campionamento dei dati efficienti:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Split data into 80% for training and 20% for testing\n",
"set.seed(2056)\n",
"pumpkins_split <- pumpkins_select %>% \n",
" initial_split(prop = 0.8)\n",
"\n",
"# Extract the data in each split\n",
"pumpkins_train <- training(pumpkins_split)\n",
"pumpkins_test <- testing(pumpkins_split)\n",
"\n",
"# Print out the first 5 rows of the training set\n",
"pumpkins_train %>% \n",
" slice_head(n = 5)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"🙌 Siamo pronti per addestrare un modello adattando le caratteristiche di addestramento all'etichetta di addestramento (colore).\n",
"\n",
"Inizieremo creando una ricetta che specifichi i passaggi di pre-elaborazione da eseguire sui nostri dati per prepararli alla modellazione, ad esempio: codificare le variabili categoriche in un insieme di interi. Proprio come `baked_pumpkins`, creiamo una `pumpkins_recipe` ma non utilizziamo `prep` e `bake` poiché verrà integrata in un workflow, che vedrai tra pochi passaggi.\n",
"\n",
"Ci sono diversi modi per specificare un modello di regressione logistica in Tidymodels. Vedi `?logistic_reg()`. Per ora, specificheremo un modello di regressione logistica tramite il motore predefinito `stats::glm()`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Create a recipe that specifies preprocessing steps for modelling\n",
"pumpkins_recipe <- recipe(color ~ ., data = pumpkins_train) %>% \n",
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
" step_integer(item_size, zero_based = F) %>% \n",
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE)\n",
"\n",
"# Create a logistic model specification\n",
"log_reg <- logistic_reg() %>% \n",
" set_engine(\"glm\") %>% \n",
" set_mode(\"classification\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ora che abbiamo una ricetta e una specifica del modello, dobbiamo trovare un modo per unirle in un oggetto che prima pre-elabori i dati (prep+bake dietro le quinte), adatti il modello ai dati pre-elaborati e consenta anche eventuali attività di post-elaborazione.\n",
"\n",
"In Tidymodels, questo pratico oggetto si chiama [`workflow`](https://workflows.tidymodels.org/) e contiene comodamente i tuoi componenti di modellazione.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Bundle modelling components in a workflow\n",
"log_reg_wf <- workflow() %>% \n",
" add_recipe(pumpkins_recipe) %>% \n",
" add_model(log_reg)\n",
"\n",
"# Print out the workflow\n",
"log_reg_wf\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dopo che un workflow è stato *specificato*, un modello può essere `addestrato` utilizzando la funzione [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html). Il workflow stimerà una ricetta e pre-processerà i dati prima dell'addestramento, quindi non sarà necessario farlo manualmente utilizzando prep e bake.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Train the model\n",
"wf_fit <- log_reg_wf %>% \n",
" fit(data = pumpkins_train)\n",
"\n",
"# Print the trained workflow\n",
"wf_fit\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Il modello stampa i coefficienti appresi durante l'addestramento.\n",
"\n",
"Ora che abbiamo addestrato il modello utilizzando i dati di training, possiamo fare previsioni sui dati di test usando [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Iniziamo utilizzando il modello per prevedere le etichette del nostro set di test e le probabilità per ciascuna etichetta. Quando la probabilità è maggiore di 0.5, la classe prevista è `WHITE`, altrimenti è `ORANGE`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Make predictions for color and corresponding probabilities\n",
"results <- pumpkins_test %>% select(color) %>% \n",
" bind_cols(wf_fit %>% \n",
" predict(new_data = pumpkins_test)) %>%\n",
" bind_cols(wf_fit %>%\n",
" predict(new_data = pumpkins_test, type = \"prob\"))\n",
"\n",
"# Compare predictions\n",
"results %>% \n",
" slice_head(n = 10)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Molto interessante! Questo offre ulteriori spunti su come funziona la regressione logistica.\n",
"\n",
"### Migliore comprensione tramite una matrice di confusione\n",
"\n",
"Confrontare ogni previsione con il corrispondente valore reale \"ground truth\" non è un modo molto efficiente per determinare quanto bene il modello stia prevedendo. Fortunatamente, Tidymodels ha qualche altro asso nella manica: [`yardstick`](https://yardstick.tidymodels.org/) - un pacchetto utilizzato per misurare l'efficacia dei modelli tramite metriche di performance.\n",
"\n",
"Una metrica di performance associata ai problemi di classificazione è la [`matrice di confusione`](https://wikipedia.org/wiki/Confusion_matrix). Una matrice di confusione descrive quanto bene un modello di classificazione si comporta. Essa riassume quanti esempi di ciascuna classe sono stati classificati correttamente da un modello. Nel nostro caso, ti mostrerà quante zucche arancioni sono state classificate come arancioni e quante zucche bianche sono state classificate come bianche; la matrice di confusione ti mostrerà anche quante sono state classificate nelle categorie **sbagliate**.\n",
"\n",
"La funzione [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) di yardstick calcola questa tabulazione incrociata delle classi osservate e previste.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Confusion matrix for prediction results\n",
"conf_mat(data = results, truth = color, estimate = .pred_class)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Interpretiamo la matrice di confusione. Al nostro modello viene chiesto di classificare le zucche in due categorie binarie, categoria `bianca` e categoria `non-bianca`.\n",
"\n",
"- Se il tuo modello predice una zucca come bianca e appartiene alla categoria 'bianca' nella realtà, la chiamiamo `vero positivo`, indicato dal numero in alto a sinistra.\n",
"\n",
"- Se il tuo modello predice una zucca come non bianca e appartiene alla categoria 'bianca' nella realtà, la chiamiamo `falso negativo`, indicato dal numero in basso a sinistra.\n",
"\n",
"- Se il tuo modello predice una zucca come bianca e appartiene alla categoria 'non-bianca' nella realtà, la chiamiamo `falso positivo`, indicato dal numero in alto a destra.\n",
"\n",
"- Se il tuo modello predice una zucca come non bianca e appartiene alla categoria 'non-bianca' nella realtà, la chiamiamo `vero negativo`, indicato dal numero in basso a destra.\n",
"\n",
"| Verità |\n",
"|:-----:|\n",
"\n",
"\n",
"| | | |\n",
"|---------------|--------|-------|\n",
"| **Predetto** | BIANCA | ARANCIONE |\n",
"| BIANCA | VP | FP |\n",
"| ARANCIONE | FN | VN |\n",
"\n",
"Come avrai intuito, è preferibile avere un numero maggiore di veri positivi e veri negativi e un numero minore di falsi positivi e falsi negativi, il che implica che il modello funziona meglio.\n",
"\n",
"La matrice di confusione è utile perché dà origine ad altre metriche che possono aiutarci a valutare meglio le prestazioni di un modello di classificazione. Esaminiamone alcune:\n",
"\n",
"🎓 Precisione: `VP/(VP + FP)` definita come la proporzione di positivi predetti che sono effettivamente positivi. Chiamata anche [valore predittivo positivo](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n",
"\n",
"🎓 Richiamo: `VP/(VP + FN)` definito come la proporzione di risultati positivi sul numero di campioni che erano effettivamente positivi. Conosciuto anche come `sensibilità`.\n",
"\n",
"🎓 Specificità: `VN/(VN + FP)` definita come la proporzione di risultati negativi sul numero di campioni che erano effettivamente negativi.\n",
"\n",
"🎓 Accuratezza: `VP + VN/(VP + VN + FP + FN)` La percentuale di etichette predette correttamente per un campione.\n",
"\n",
"🎓 Misura F: Una media ponderata della precisione e del richiamo, con il valore migliore pari a 1 e il peggiore pari a 0.\n",
"\n",
"Calcoliamo queste metriche!\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Combine metric functions and calculate them all at once\n",
"eval_metrics <- metric_set(ppv, recall, spec, f_meas, accuracy)\n",
"eval_metrics(data = results, truth = color, estimate = .pred_class)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualizzare la curva ROC di questo modello\n",
"\n",
"Facciamo un'altra visualizzazione per osservare la cosiddetta [`curva ROC`](https://en.wikipedia.org/wiki/Receiver_operating_characteristic):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Make a roc_curve\n",
"results %>% \n",
" roc_curve(color, .pred_ORANGE) %>% \n",
" autoplot()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Le curve ROC sono spesso utilizzate per ottenere una visione dell'output di un classificatore in termini di veri positivi rispetto ai falsi positivi. Le curve ROC presentano tipicamente il `True Positive Rate`/Sensibilità sull'asse Y e il `False Positive Rate`/1-Specificità sull'asse X. Pertanto, l'inclinazione della curva e lo spazio tra la linea di mezzo e la curva sono importanti: si desidera una curva che salga rapidamente e superi la linea. Nel nostro caso, ci sono falsi positivi all'inizio, e poi la linea sale e supera correttamente.\n",
"\n",
"Infine, utilizziamo `yardstick::roc_auc()` per calcolare l'effettiva Area Sotto la Curva. Un modo per interpretare l'AUC è come la probabilità che il modello classifichi un esempio positivo casuale più in alto di un esempio negativo casuale.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Calculate area under curve\n",
"results %>% \n",
" roc_auc(color, .pred_ORANGE)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Il risultato è circa `0.975`. Considerando che l'AUC varia da 0 a 1, si desidera un punteggio alto, poiché un modello che è corretto al 100% nelle sue previsioni avrà un AUC di 1; in questo caso, il modello è *abbastanza buono*.\n",
"\n",
"Nelle lezioni future sulle classificazioni, imparerai come migliorare i punteggi del tuo modello (ad esempio, affrontando il problema dei dati sbilanciati in questo caso).\n",
"\n",
"## 🚀Sfida\n",
"\n",
"C'è molto di più da scoprire sulla regressione logistica! Ma il modo migliore per imparare è sperimentare. Trova un dataset che si presti a questo tipo di analisi e costruisci un modello con esso. Cosa impari? suggerimento: prova [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) per dataset interessanti.\n",
"\n",
"## Revisione e Studio Autonomo\n",
"\n",
"Leggi le prime pagine di [questo articolo di Stanford](https://web.stanford.edu/~jurafsky/slp3/5.pdf) su alcuni usi pratici della regressione logistica. Rifletti sui compiti che sono più adatti per uno o l'altro tipo di regressione tra quelli che abbiamo studiato fino a questo punto. Cosa funzionerebbe meglio?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Disclaimer (Avvertenza)**: \nQuesto documento è stato tradotto utilizzando il servizio di traduzione automatica [Co-op Translator](https://github.com/Azure/co-op-translator). Sebbene ci impegniamo per garantire l'accuratezza, si prega di tenere presente che le traduzioni automatiche possono contenere errori o imprecisioni. Il documento originale nella sua lingua nativa dovrebbe essere considerato la fonte autorevole. Per informazioni critiche, si raccomanda una traduzione professionale effettuata da un traduttore umano. Non siamo responsabili per eventuali malintesi o interpretazioni errate derivanti dall'uso di questa traduzione.\n"
]
}
],
"metadata": {
"anaconda-cloud": "",
"kernelspec": {
"display_name": "R",
"langauge": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.4.1"
},
"coopTranslator": {
"original_hash": "feaf125f481a89c468fa115bf2aed580",
"translation_date": "2025-08-29T23:05:27+00:00",
"source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb",
"language_code": "it"
}
},
"nbformat": 4,
"nbformat_minor": 1
}