{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Bygg en logistisk regressionsmodell - Lektion 4\n", "\n", "![Infografik om logistisk vs. linjär regression](../../../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)\n", "\n", "#### **[Quiz före föreläsningen](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n", "\n", "#### Introduktion\n", "\n", "I denna sista lektion om regression, en av de grundläggande *klassiska* ML-teknikerna, ska vi titta på logistisk regression. Du kan använda denna teknik för att upptäcka mönster och förutsäga binära kategorier. Är detta godis choklad eller inte? Är denna sjukdom smittsam eller inte? Kommer denna kund att välja denna produkt eller inte?\n", "\n", "I denna lektion kommer du att lära dig:\n", "\n", "- Tekniker för logistisk regression\n", "\n", "✅ Fördjupa din förståelse för att arbeta med denna typ av regression i detta [Learn-modul](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n", "\n", "## Förkunskaper\n", "\n", "Efter att ha arbetat med pumpadatan är vi nu tillräckligt bekanta med den för att inse att det finns en binär kategori som vi kan arbeta med: `Color`.\n", "\n", "Låt oss bygga en logistisk regressionsmodell för att förutsäga, baserat på vissa variabler, *vilken färg en given pumpa sannolikt har* (orange 🎃 eller vit 👻).\n", "\n", "> Varför pratar vi om binär klassificering i en lektion som handlar om regression? Endast av språklig bekvämlighet, eftersom logistisk regression [egentligen är en klassificeringsmetod](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), om än en linjärbaserad sådan. Lär dig om andra sätt att klassificera data i nästa lektionsgrupp.\n", "\n", "För denna lektion behöver vi följande paket:\n", "\n", "- `tidyverse`: [tidyverse](https://www.tidyverse.org/) är en [samling av R-paket](https://www.tidyverse.org/packages) som är utformade för att göra datavetenskap snabbare, enklare och roligare!\n", "\n", "- `tidymodels`: [tidymodels](https://www.tidymodels.org/) är ett [ramverk av paket](https://www.tidymodels.org/packages/) för modellering och maskininlärning.\n", "\n", "- `janitor`: [janitor-paketet](https://github.com/sfirke/janitor) erbjuder enkla verktyg för att undersöka och rengöra smutsiga data.\n", "\n", "- `ggbeeswarm`: [ggbeeswarm-paketet](https://github.com/eclarke/ggbeeswarm) tillhandahåller metoder för att skapa beeswarm-stil diagram med ggplot2.\n", "\n", "Du kan installera dem med:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n", "\n", "Alternativt kan skriptet nedan kontrollera om du har de paket som krävs för att slutföra denna modul och installera dem åt dig om de saknas.\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": [ "## **Definiera frågan**\n", "\n", "För våra ändamål kommer vi att uttrycka detta som en binär: 'Vit' eller 'Inte Vit'. Det finns också en kategori 'randig' i vår dataset, men det finns få exempel på den, så vi kommer inte att använda den. Den försvinner ändå när vi tar bort nullvärden från datasetet.\n", "\n", "> 🎃 Rolig fakta, vi kallar ibland vita pumpor för 'spök'-pumpor. De är inte så lätta att skära i, så de är inte lika populära som de orangea, men de ser häftiga ut! Så vi skulle också kunna omformulera vår fråga som: 'Spök' eller 'Inte Spök'. 👻\n", "\n", "## **Om logistisk regression**\n", "\n", "Logistisk regression skiljer sig från linjär regression, som du lärde dig om tidigare, på några viktiga sätt.\n", "\n", "#### **Binär klassificering**\n", "\n", "Logistisk regression erbjuder inte samma funktioner som linjär regression. Den förstnämnda ger en förutsägelse om en `binär kategori` (\"orange eller inte orange\") medan den senare kan förutsäga `kontinuerliga värden`, till exempel givet ursprunget av en pumpa och skördetiden, *hur mycket priset kommer att stiga*.\n", "\n", "![Infografik av Dasani Madipalli](../../../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)\n", "\n", "### Andra klassificeringar\n", "\n", "Det finns andra typer av logistisk regression, inklusive multinomial och ordinal:\n", "\n", "- **Multinomial**, som innebär att ha mer än en kategori - \"Orange, Vit och Randig\".\n", "\n", "- **Ordinal**, som innebär ordnade kategorier, användbart om vi vill ordna våra resultat logiskt, som våra pumpor som är ordnade efter ett begränsat antal storlekar (mini,sm,med,lg,xl,xxl).\n", "\n", "![Multinomial vs ordinal regression](../../../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)\n", "\n", "#### **Variabler BEHÖVER INTE korrelera**\n", "\n", "Kommer du ihåg hur linjär regression fungerade bättre med mer korrelerade variabler? Logistisk regression är motsatsen - variablerna behöver inte stämma överens. Det fungerar för denna data som har ganska svaga korrelationer.\n", "\n", "#### **Du behöver mycket ren data**\n", "\n", "Logistisk regression ger mer exakta resultat om du använder mer data; vår lilla dataset är inte optimal för denna uppgift, så ha det i åtanke.\n", "\n", "✅ Fundera på vilka typer av data som skulle passa bra för logistisk regression\n", "\n", "## Övning - städa upp datan\n", "\n", "Först, städa upp datan lite, ta bort nullvärden och välj endast några av kolumnerna:\n", "\n", "1. Lägg till följande kod:\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": [ "Du kan alltid ta en titt på din nya dataframe genom att använda funktionen [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html) enligt nedan:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "pumpkins_select %>% \n", " glimpse()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Låt oss bekräfta att vi faktiskt kommer att arbeta med ett binärt klassificeringsproblem:\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": [ "### Visualisering - kategoriskt diagram\n", "Nu har du laddat upp pumpadatan igen och rensat den för att bevara en dataset som innehåller några variabler, inklusive Färg. Låt oss visualisera dataframen i notebooken med hjälp av ggplot-biblioteket.\n", "\n", "Biblioteket ggplot erbjuder några smarta sätt att visualisera din data. Till exempel kan du jämföra distributionerna av data för varje Sort och Färg i ett kategoriskt diagram.\n", "\n", "1. Skapa ett sådant diagram genom att använda funktionen geombar, med vår pumpadata, och specificera en färgkartläggning för varje pumpakategori (orange eller vit):\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": [ "Genom att observera data kan du se hur färgdata relaterar till sort.\n", "\n", "✅ Givet detta kategoriska diagram, vilka intressanta undersökningar kan du föreställa dig?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Datapreparation: funktionskodning\n", "\n", "Vår pumpadataset innehåller strängvärden för alla sina kolumner. Att arbeta med kategoriska data är intuitivt för människor men inte för maskiner. Maskininlärningsalgoritmer fungerar bra med siffror. Därför är kodning ett mycket viktigt steg i datapreparationsfasen, eftersom det gör det möjligt för oss att omvandla kategoriska data till numeriska data utan att förlora någon information. Bra kodning leder till att bygga en bra modell.\n", "\n", "För funktionskodning finns det två huvudsakliga typer av kodare:\n", "\n", "1. Ordinal kodare: den passar bra för ordnade variabler, som är kategoriska variabler där deras data följer en logisk ordning, som kolumnen `item_size` i vårt dataset. Den skapar en mappning där varje kategori representeras av ett nummer, vilket är ordningen för kategorin i kolumnen.\n", "\n", "2. Kategorisk kodare: den passar bra för nominella variabler, som är kategoriska variabler där deras data inte följer en logisk ordning, som alla funktioner utom `item_size` i vårt dataset. Det är en one-hot-kodning, vilket innebär att varje kategori representeras av en binär kolumn: den kodade variabeln är lika med 1 om pumpan tillhör den sorten och 0 annars.\n", "\n", "Tidymodels erbjuder ytterligare ett smidigt paket: [recipes](https://recipes.tidymodels.org/) - ett paket för datapreparation. Vi kommer att definiera en `recipe` som specificerar att alla prediktorkolumner ska kodas till en uppsättning heltal, `prep` för att uppskatta de nödvändiga mängderna och statistiken som behövs för alla operationer och slutligen `bake` för att tillämpa beräkningarna på ny data.\n", "\n", "> Vanligtvis används recipes som en förprocessor för modellering där den definierar vilka steg som ska tillämpas på en dataset för att göra den redo för modellering. I det fallet är det **starkt rekommenderat** att du använder en `workflow()` istället för att manuellt uppskatta en recipe med prep och bake. Vi kommer att se allt detta om en liten stund.\n", ">\n", "> Men för tillfället använder vi recipes + prep + bake för att specificera vilka steg som ska tillämpas på en dataset för att göra den redo för dataanalys och sedan extrahera den förprocessade datan med de tillämpade stegen.\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": [ "✅ Vilka är fördelarna med att använda en ordinal encoder för kolumnen Item Size?\n", "\n", "### Analysera relationer mellan variabler\n", "\n", "Nu när vi har förbehandlat vår data kan vi analysera relationerna mellan funktionerna och etiketten för att få en uppfattning om hur väl modellen kommer att kunna förutsäga etiketten baserat på funktionerna. Det bästa sättet att utföra denna typ av analys är att visualisera datan. \n", "Vi kommer återigen att använda ggplot-funktionen geom_boxplot_ för att visualisera relationerna mellan Item Size, Variety och Color i ett kategoriskt diagram. För att bättre kunna plotta datan kommer vi att använda den kodade kolumnen Item Size och den okodade kolumnen Variety.\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": [ "#### Använd ett swarm-diagram\n", "\n", "Eftersom Color är en binär kategori (Vit eller Inte), krävs 'ett [specialiserat tillvägagångssätt](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) för visualisering'.\n", "\n", "Prova ett `swarm-diagram` för att visa fördelningen av färg i förhållande till item_size.\n", "\n", "Vi kommer att använda [ggbeeswarm-paketet](https://github.com/eclarke/ggbeeswarm) som erbjuder metoder för att skapa beeswarm-stil diagram med ggplot2. Beeswarm-diagram är ett sätt att plotta punkter som normalt skulle överlappa varandra så att de istället placeras bredvid varandra.\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": [ "Nu när vi har en uppfattning om sambandet mellan de binära färgkategorierna och den större gruppen av storlekar, låt oss utforska logistisk regression för att avgöra en pumpas sannolika färg.\n", "\n", "## Bygg din modell\n", "\n", "Välj de variabler du vill använda i din klassificeringsmodell och dela upp data i tränings- och testuppsättningar. [rsample](https://rsample.tidymodels.org/), ett paket i Tidymodels, erbjuder infrastruktur för effektiv datadelning och återprovtagning:\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": [ "🙌 Vi är nu redo att träna en modell genom att passa träningsfunktionerna till träningsetiketten (färg).\n", "\n", "Vi börjar med att skapa ett recept som anger de förbehandlingssteg som ska utföras på vår data för att göra den redo för modellering, dvs: koda kategoriska variabler till en uppsättning heltal. Precis som `baked_pumpkins` skapar vi ett `pumpkins_recipe` men vi `prep` och `bake` inte eftersom det kommer att paketeras i ett arbetsflöde, vilket du kommer att se om bara några steg.\n", "\n", "Det finns ganska många sätt att specificera en logistisk regressionsmodell i Tidymodels. Se `?logistic_reg()` För tillfället kommer vi att specificera en logistisk regressionsmodell via den förvalda `stats::glm()`-motorn.\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": [ "Nu när vi har ett recept och en modellspecifikation behöver vi hitta ett sätt att kombinera dem i ett objekt som först förbehandlar data (prep+bake i bakgrunden), anpassar modellen på den förbehandlade datan och även möjliggör eventuella efterbehandlingsaktiviteter.\n", "\n", "I Tidymodels kallas detta praktiska objekt för en [`workflow`](https://workflows.tidymodels.org/) och det håller smidigt dina modellkomponenter.\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": [ "Efter att ett arbetsflöde har *specificerats* kan en modell `tränas` med hjälp av [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html)-funktionen. Arbetsflödet kommer att uppskatta ett recept och förbehandla data innan träningen, så vi behöver inte göra det manuellt med prep och 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": [ "Modellen visar de koefficienter som lärts in under träningen.\n", "\n", "Nu när vi har tränat modellen med träningsdata kan vi göra förutsägelser på testdata med [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Låt oss börja med att använda modellen för att förutsäga etiketter för vårt testset och sannolikheterna för varje etikett. När sannolikheten är mer än 0.5 är den förutsagda klassen `WHITE`, annars `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": [ "Väldigt bra! Detta ger några fler insikter i hur logistisk regression fungerar.\n", "\n", "### Bättre förståelse via en förvirringsmatris\n", "\n", "Att jämföra varje förutsägelse med dess motsvarande \"ground truth\"-värde är inte ett särskilt effektivt sätt att avgöra hur väl modellen förutspår. Lyckligtvis har Tidymodels några fler knep i rockärmen: [`yardstick`](https://yardstick.tidymodels.org/) - ett paket som används för att mäta modellers effektivitet med hjälp av prestationsmått.\n", "\n", "Ett prestationsmått som är kopplat till klassificeringsproblem är [`förvirringsmatrisen`](https://wikipedia.org/wiki/Confusion_matrix). En förvirringsmatris beskriver hur väl en klassificeringsmodell presterar. En förvirringsmatris sammanställer hur många exempel i varje klass som korrekt klassificerades av en modell. I vårt fall kommer den att visa hur många orangea pumpor som klassificerades som orangea och hur många vita pumpor som klassificerades som vita; förvirringsmatrisen visar också hur många som klassificerades i de **felaktiga** kategorierna.\n", "\n", "Funktionen [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) från yardstick beräknar denna kors-tabell över observerade och förutspådda klasser.\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": [ "Låt oss tolka förvirringsmatrisen. Vår modell ska klassificera pumpor mellan två binära kategorier, kategori `vit` och kategori `inte-vit`.\n", "\n", "- Om din modell förutspår att en pumpa är vit och den faktiskt tillhör kategorin 'vit' kallar vi det en `sann positiv`, vilket visas av siffran längst upp till vänster.\n", "\n", "- Om din modell förutspår att en pumpa inte är vit och den faktiskt tillhör kategorin 'vit' kallar vi det en `falsk negativ`, vilket visas av siffran längst ner till vänster.\n", "\n", "- Om din modell förutspår att en pumpa är vit och den faktiskt tillhör kategorin 'inte-vit' kallar vi det en `falsk positiv`, vilket visas av siffran längst upp till höger.\n", "\n", "- Om din modell förutspår att en pumpa inte är vit och den faktiskt tillhör kategorin 'inte-vit' kallar vi det en `sann negativ`, vilket visas av siffran längst ner till höger.\n", "\n", "| Sanning |\n", "|:-----:|\n", "\n", "\n", "| | | |\n", "|---------------|--------|-------|\n", "| **Förutspådd** | VIT | ORANGE |\n", "| VIT | TP | FP |\n", "| ORANGE | FN | TN |\n", "\n", "Som du kanske har gissat är det att föredra att ha ett större antal sanna positiva och sanna negativa samt ett lägre antal falska positiva och falska negativa, vilket innebär att modellen presterar bättre.\n", "\n", "Förvirringsmatrisen är användbar eftersom den ger upphov till andra mått som kan hjälpa oss att bättre utvärdera prestandan hos en klassificeringsmodell. Låt oss gå igenom några av dem:\n", "\n", "🎓 Precision: `TP/(TP + FP)` definieras som andelen förutspådda positiva som faktiskt är positiva. Kallas också [positivt prediktivt värde](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n", "\n", "🎓 Recall: `TP/(TP + FN)` definieras som andelen positiva resultat av antalet prover som faktiskt var positiva. Kallas också `sensitivitet`.\n", "\n", "🎓 Specificitet: `TN/(TN + FP)` definieras som andelen negativa resultat av antalet prover som faktiskt var negativa.\n", "\n", "🎓 Noggrannhet: `TP + TN/(TP + TN + FP + FN)` Den procentandel av etiketter som förutspåtts korrekt för ett prov.\n", "\n", "🎓 F-mått: Ett viktat genomsnitt av precision och recall, där det bästa är 1 och det sämsta är 0.\n", "\n", "Låt oss beräkna dessa mått!\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": [ "## Visualisera ROC-kurvan för den här modellen\n", "\n", "Låt oss göra en ytterligare visualisering för att se den så kallade [`ROC-kurvan`](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": [ "ROC-kurvor används ofta för att få en överblick över en klassificerares resultat i termer av dess sanna respektive falska positiva. ROC-kurvor visar vanligtvis `True Positive Rate`/Sensitivitet på Y-axeln och `False Positive Rate`/1-Specificitet på X-axeln. Därför spelar kurvans branthet och avståndet mellan mittlinjen och kurvan roll: du vill ha en kurva som snabbt går upp och över linjen. I vårt fall finns det falska positiva i början, och sedan går linjen upp och över på rätt sätt.\n", "\n", "Slutligen, låt oss använda `yardstick::roc_auc()` för att beräkna det faktiska Area Under the Curve. Ett sätt att tolka AUC är som sannolikheten att modellen rankar ett slumpmässigt positivt exempel högre än ett slumpmässigt negativt exempel.\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": [ "Resultatet är cirka `0.975`. Eftersom AUC sträcker sig från 0 till 1 vill du ha ett högt värde, eftersom en modell som är 100 % korrekt i sina förutsägelser kommer att ha en AUC på 1; i det här fallet är modellen *ganska bra*.\n", "\n", "I framtida lektioner om klassificering kommer du att lära dig hur du kan förbättra modellens resultat (till exempel hantering av obalanserad data i detta fall).\n", "\n", "## 🚀Utmaning\n", "\n", "Det finns mycket mer att utforska kring logistisk regression! Men det bästa sättet att lära sig är att experimentera. Hitta en dataset som lämpar sig för denna typ av analys och bygg en modell med den. Vad lär du dig? tips: prova [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) för intressanta dataset.\n", "\n", "## Granskning & Självstudier\n", "\n", "Läs de första sidorna av [denna artikel från Stanford](https://web.stanford.edu/~jurafsky/slp3/5.pdf) om några praktiska användningsområden för logistisk regression. Fundera på uppgifter som passar bättre för den ena eller andra typen av regressionsuppgifter som vi har studerat hittills. Vad skulle fungera bäst?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Ansvarsfriskrivning**: \nDetta dokument har översatts med hjälp av AI-översättningstjänsten [Co-op Translator](https://github.com/Azure/co-op-translator). Även om vi strävar efter noggrannhet, vänligen notera att automatiska översättningar kan innehålla fel eller felaktigheter. Det ursprungliga dokumentet på sitt ursprungliga språk bör betraktas som den auktoritativa källan. För kritisk information rekommenderas professionell mänsklig översättning. Vi ansvarar inte för eventuella missförstånd eller feltolkningar som uppstår vid användning av denna översättning.\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-09-06T13:33:24+00:00", "source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb", "language_code": "sv" } }, "nbformat": 4, "nbformat_minor": 1 }