{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Építsünk egy logisztikus regressziós modellt - 4. lecke\n", "\n", "![Logisztikus vs. lineáris regresszió infografika](../../../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)\n", "\n", "#### **[Előadás előtti kvíz](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n", "\n", "#### Bevezetés\n", "\n", "Ebben az utolsó leckében a regresszióról, amely az egyik alapvető *klasszikus* gépi tanulási technika, a logisztikus regresszióval fogunk foglalkozni. Ezt a technikát akkor használjuk, amikor mintákat szeretnénk felfedezni bináris kategóriák előrejelzéséhez. Ez a cukorka csokoládé vagy sem? Ez a betegség fertőző vagy sem? Ez az ügyfél választja-e ezt a terméket vagy sem?\n", "\n", "Ebben a leckében megtanulod:\n", "\n", "- A logisztikus regresszió technikáit\n", "\n", "✅ Mélyítsd el a logisztikus regresszióval kapcsolatos tudásodat ebben a [Learn modulban](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n", "\n", "## Előfeltétel\n", "\n", "A tök adatokkal való munka során már elég jól megismerkedtünk ahhoz, hogy felismerjük, van egy bináris kategória, amellyel dolgozhatunk: `Color`.\n", "\n", "Építsünk egy logisztikus regressziós modellt, hogy megjósoljuk, adott változók alapján *milyen színű lehet egy adott tök* (narancssárga 🎃 vagy fehér 👻).\n", "\n", "> Miért beszélünk bináris osztályozásról egy regresszióval kapcsolatos leckében? Csak nyelvi egyszerűség kedvéért, mivel a logisztikus regresszió [valójában egy osztályozási módszer](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), bár lineáris alapú. A következő leckecsoportban további adat-osztályozási módszerekről tanulhatsz.\n", "\n", "Ehhez a leckéhez a következő csomagokra lesz szükségünk:\n", "\n", "- `tidyverse`: A [tidyverse](https://www.tidyverse.org/) egy [R csomagok gyűjteménye](https://www.tidyverse.org/packages), amely gyorsabbá, könnyebbé és szórakoztatóbbá teszi az adatelemzést!\n", "\n", "- `tidymodels`: A [tidymodels](https://www.tidymodels.org/) keretrendszer egy [csomaggyűjtemény](https://www.tidymodels.org/packages/) modellezéshez és gépi tanuláshoz.\n", "\n", "- `janitor`: A [janitor csomag](https://github.com/sfirke/janitor) egyszerű eszközöket kínál a piszkos adatok vizsgálatához és tisztításához.\n", "\n", "- `ggbeeswarm`: A [ggbeeswarm csomag](https://github.com/eclarke/ggbeeswarm) lehetőséget nyújt beeswarm-stílusú diagramok készítésére a ggplot2 használatával.\n", "\n", "A csomagokat az alábbi módon telepítheted:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n", "\n", "Alternatívaként az alábbi szkript ellenőrzi, hogy megvannak-e a szükséges csomagok a modul elvégzéséhez, és telepíti őket, ha hiányoznak.\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": [ "## **Határozd meg a kérdést**\n", "\n", "A mi céljainkhoz ezt bináris formában fogjuk kifejezni: 'Fehér' vagy 'Nem fehér'. Az adatainkban van egy 'csíkos' kategória is, de kevés példa van rá, ezért nem fogjuk használni. Egyébként is eltűnik, amikor eltávolítjuk az üres értékeket az adatállományból.\n", "\n", "> 🎃 Érdekesség: néha a fehér tököket 'szellem' tököknek hívjuk. Nem túl könnyű őket faragni, ezért nem olyan népszerűek, mint a narancssárgák, de nagyon menők! Így a kérdésünket átfogalmazhatnánk úgy is, hogy: 'Szellem' vagy 'Nem szellem'. 👻\n", "\n", "## **A logisztikus regresszióról**\n", "\n", "A logisztikus regresszió néhány fontos szempontból különbözik a lineáris regressziótól, amelyről korábban tanultál.\n", "\n", "#### **Bináris osztályozás**\n", "\n", "A logisztikus regresszió nem kínálja ugyanazokat a funkciókat, mint a lineáris regresszió. Az előbbi egy `bináris kategóriára` (\"narancssárga vagy nem narancssárga\") ad előrejelzést, míg az utóbbi képes `folyamatos értékeket` megjósolni, például a tök származási helye és betakarítási ideje alapján *mennyivel fog emelkedni az ára*.\n", "\n", "![Infografika: Dasani Madipalli](../../../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)\n", "\n", "### Egyéb osztályozások\n", "\n", "A logisztikus regressziónak más típusai is vannak, például multinomiális és ordinális:\n", "\n", "- **Multinomiális**, amely több kategóriát foglal magában - \"Narancssárga, Fehér és Csíkos\".\n", "\n", "- **Ordinális**, amely rendezett kategóriákat tartalmaz, hasznos, ha logikusan szeretnénk sorrendbe állítani az eredményeket, például a tököket, amelyek egy véges számú méret szerint vannak rendezve (mini, kicsi, közepes, nagy, extra nagy, extra extra nagy).\n", "\n", "![Multinomiális vs ordinális regresszió](../../../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)\n", "\n", "#### **A változóknak NEM kell korrelálniuk**\n", "\n", "Emlékszel, hogy a lineáris regresszió jobban működött, ha a változók erősebben korreláltak? A logisztikus regresszió ennek az ellenkezője - a változóknak nem kell egymással összhangban lenniük. Ez jól működik az olyan adatokkal, amelyeknél a korrelációk viszonylag gyengék.\n", "\n", "#### **Sok tiszta adatra van szükséged**\n", "\n", "A logisztikus regresszió pontosabb eredményeket ad, ha több adatot használsz; a mi kis adatállományunk nem optimális ehhez a feladathoz, ezért ezt tartsd szem előtt.\n", "\n", "✅ Gondold át, milyen típusú adatok alkalmasak a logisztikus regresszióra\n", "\n", "## Gyakorlat - tisztítsd meg az adatokat\n", "\n", "Először tisztítsd meg az adatokat egy kicsit, távolítsd el az üres értékeket, és válassz ki csak néhány oszlopot:\n", "\n", "1. Add hozzá a következő kódot:\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": [ "Mindig megtekintheted az új adatkeretedet a [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html) függvény használatával, az alábbi módon:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "pumpkins_select %>% \n", " glimpse()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ellenőrizzük, hogy valóban egy bináris osztályozási problémát fogunk megoldani:\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": [ "### Vizualizáció - kategóriális diagram\n", "Mostanra újra betöltötted a tök adatokat, és megtisztítottad őket, hogy megmaradjon egy olyan adatállomány, amely néhány változót, például a Színt tartalmazza. Vizualizáljuk az adatkeretet a notebookban a ggplot könyvtár segítségével.\n", "\n", "A ggplot könyvtár remek lehetőségeket kínál az adatok vizualizálására. Például összehasonlíthatod az adatok eloszlását minden Fajta és Szín esetében egy kategóriális diagramon.\n", "\n", "1. Hozz létre egy ilyen diagramot a geombar függvény használatával, a tök adatainkat felhasználva, és adj meg egy színkódolást minden tök kategóriához (narancs vagy fehér):\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": [ "Adatait megfigyelve látható, hogyan kapcsolódik a Szín adata a Fajtához.\n", "\n", "✅ Ezen kategóriális ábra alapján milyen érdekes vizsgálatokat tudsz elképzelni?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Adatelőkészítés: jellemzők kódolása\n", "\n", "A tökök adatállományunkban minden oszlop sztring értékeket tartalmaz. A kategóriális adatokkal való munka intuitív az emberek számára, de nem a gépek számára. A gépi tanulási algoritmusok számokkal működnek jól. Ezért a kódolás nagyon fontos lépés az adatelőkészítési fázisban, mivel lehetővé teszi, hogy a kategóriális adatokat numerikus adatokká alakítsuk anélkül, hogy információt veszítenénk. A jó kódolás segít egy jó modell felépítésében.\n", "\n", "A jellemzők kódolásához két fő típusú kódoló létezik:\n", "\n", "1. Ordinális kódoló: jól alkalmazható ordinális változók esetében, amelyek olyan kategóriális változók, ahol az adatok logikai sorrendet követnek, mint például az `item_size` oszlop az adatállományunkban. Ez egy olyan leképezést hoz létre, amelyben minden kategóriát egy szám képvisel, amely a kategória sorrendjét jelöli az oszlopban.\n", "\n", "2. Kategóriális kódoló: jól alkalmazható nominális változók esetében, amelyek olyan kategóriális változók, ahol az adatok nem követnek logikai sorrendet, mint például az összes `item_size`-től eltérő jellemző az adatállományunkban. Ez egy one-hot kódolás, ami azt jelenti, hogy minden kategóriát egy bináris oszlop képvisel: a kódolt változó értéke 1, ha a tök az adott Variety-hez tartozik, és 0, ha nem.\n", "\n", "A Tidymodels egy újabb remek csomagot kínál: [recipes](https://recipes.tidymodels.org/) - egy csomag az adatok előfeldolgozásához. Meghatározunk egy `recipe`-t, amely specifikálja, hogy az összes prediktor oszlopot egész számokká kell kódolni, `prep`-eljük, hogy megbecsülje a szükséges mennyiségeket és statisztikákat bármely művelethez, majd végül `bake`, hogy az új adatokra alkalmazza a számításokat.\n", "\n", "> Általában a recipes-t általában modellezés előfeldolgozójaként használják, ahol meghatározza, hogy milyen lépéseket kell alkalmazni egy adathalmazra annak érdekében, hogy készen álljon a modellezésre. Ebben az esetben **erősen ajánlott**, hogy a `workflow()`-t használja ahelyett, hogy manuálisan becsülné meg a receptet a prep és bake segítségével. Ezt mindjárt látni fogjuk.\n", ">\n", "> Azonban most a recipes + prep + bake kombinációt használjuk annak meghatározására, hogy milyen lépéseket kell alkalmazni egy adathalmazra annak érdekében, hogy készen álljon az adatelemzésre, majd kinyerjük az előfeldolgozott adatokat az alkalmazott lépésekkel.\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": [ "✅ Milyen előnyei vannak az ordinal encoder használatának az Item Size oszlophoz?\n", "\n", "### Kapcsolatok elemzése a változók között\n", "\n", "Miután előfeldolgoztuk az adatainkat, elemezhetjük a jellemzők és a címke közötti kapcsolatokat, hogy képet kapjunk arról, mennyire jól tudja a modell előre jelezni a címkét a jellemzők alapján. Az ilyen típusú elemzés legjobb módja az adatok ábrázolása. \n", "Ismét a ggplot geom_boxplot_ függvényt fogjuk használni, hogy kategóriális ábrán szemléltessük az Item Size, Variety és Color közötti kapcsolatokat. Az adatok jobb ábrázolása érdekében az Item Size kódolt oszlopát és a Variety nem kódolt oszlopát fogjuk használni.\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": [ "#### Használj rajzás diagramot\n", "\n", "Mivel a Color egy bináris kategória (Fehér vagy Nem), 'egy [speciális megközelítést](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) igényel a vizualizációhoz'.\n", "\n", "Próbálj ki egy `rajzás diagramot`, hogy bemutasd a szín eloszlását az item_size függvényében.\n", "\n", "Ehhez a [ggbeeswarm csomagot](https://github.com/eclarke/ggbeeswarm) fogjuk használni, amely módszereket kínál a méhraj-stílusú diagramok létrehozására a ggplot2 segítségével. A méhraj diagramok olyan módot kínálnak a pontok ábrázolására, amelyek normál esetben átfedésben lennének, így egymás mellé kerülnek.\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": [ "Most, hogy van némi elképzelésünk a színek bináris kategóriái és a méretek nagyobb csoportja közötti kapcsolatról, vizsgáljuk meg a logisztikus regressziót, hogy meghatározzuk egy adott tök valószínű színét.\n", "\n", "## Építsd fel a modelledet\n", "\n", "Válaszd ki azokat a változókat, amelyeket az osztályozási modelledben használni szeretnél, és oszd fel az adatokat tanuló és tesztelő halmazokra. Az [rsample](https://rsample.tidymodels.org/), a Tidymodels egyik csomagja, hatékony adatfelosztási és újramintavételi infrastruktúrát biztosít:\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": [ "🙌 Most már készen állunk arra, hogy egy modellt tanítsunk azáltal, hogy az edzési jellemzőket illesztjük az edzési címkéhez (szín).\n", "\n", "Először készítünk egy receptet, amely meghatározza az adatainkon végrehajtandó előfeldolgozási lépéseket, hogy azokat modellezésre alkalmassá tegyük, például: a kategóriaváltozók egész számokká történő kódolását. Hasonlóan a `baked_pumpkins`-hez, létrehozunk egy `pumpkins_recipe`-t, de nem használjuk a `prep` és `bake` funkciókat, mivel ezeket egy munkafolyamatba fogjuk csomagolni, amit néhány lépés múlva látni fogsz.\n", "\n", "A Tidymodels-ben számos módja van egy logisztikus regressziós modell meghatározásának. Lásd `?logistic_reg()`. Egyelőre az alapértelmezett `stats::glm()` motorral fogunk meghatározni egy logisztikus regressziós modellt.\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": [ "Most, hogy van egy receptünk és egy modell specifikációnk, meg kell találnunk egy módot arra, hogy ezeket egy objektumba csomagoljuk, amely először előkészíti az adatokat (a háttérben prep+bake), illeszti a modellt az előkészített adatokra, és lehetővé teszi az esetleges utófeldolgozási tevékenységeket is.\n", "\n", "A Tidymodels-ben ez a praktikus objektum [`workflow`](https://workflows.tidymodels.org/) néven ismert, és kényelmesen tartalmazza a modellezési komponenseket.\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": [ "Miután egy munkafolyamatot *meghatároztunk*, egy modell `betanítható` a [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html) függvény segítségével. A munkafolyamat kiértékeli a receptet és előfeldolgozza az adatokat a betanítás előtt, így nem kell manuálisan elvégeznünk ezt a prep és bake használatával.\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": [ "A modell nyomtatási eredményei megmutatják a tanítás során megtanult együtthatókat.\n", "\n", "Most, hogy betanítottuk a modellt a tanító adatokkal, előrejelzéseket készíthetünk a teszt adatokra a [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html) segítségével. Kezdjük azzal, hogy a modellt használjuk a tesztkészlet címkéinek előrejelzésére, valamint az egyes címkékhez tartozó valószínűségek meghatározására. Ha a valószínűség nagyobb, mint 0.5, az előrejelzett osztály `WHITE`, különben `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": [ "Nagyszerű! Ez további betekintést nyújt abba, hogyan működik a logisztikus regresszió.\n", "\n", "### Jobb megértés egy zavaró mátrix segítségével\n", "\n", "Az egyes előrejelzések összehasonlítása a hozzájuk tartozó \"valós\" értékekkel nem túl hatékony módja annak, hogy meghatározzuk, mennyire jól teljesít a modell. Szerencsére a Tidymodels néhány további trükköt is tartogat: [`yardstick`](https://yardstick.tidymodels.org/) - egy csomag, amelyet a modellek hatékonyságának mérésére használnak teljesítménymutatók segítségével.\n", "\n", "Az osztályozási problémákhoz kapcsolódó egyik teljesítménymutató a [`zavaró mátrix`](https://wikipedia.org/wiki/Confusion_matrix). A zavaró mátrix leírja, hogy egy osztályozási modell milyen jól teljesít. A zavaró mátrix összesíti, hogy az egyes osztályokban hány példát osztályozott helyesen a modell. Esetünkben megmutatja, hogy hány narancssárga tököt osztályoztak narancssárgának, és hány fehér tököt osztályoztak fehérnek; a zavaró mátrix azt is megmutatja, hogy hányat osztályoztak **rossz** kategóriákba.\n", "\n", "A yardstick [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) függvénye kiszámítja az előrejelzett és megfigyelt osztályok kereszt-táblázatát.\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": [ "Értelmezzük a zavaró mátrixot. A modellünknek az a feladata, hogy a tököket két bináris kategória között osztályozza: `fehér` és `nem-fehér`.\n", "\n", "- Ha a modell egy tököt fehérnek jósol, és az a valóságban is a 'fehér' kategóriába tartozik, akkor ezt `igaz pozitívnak` nevezzük, amit a bal felső szám mutat.\n", "\n", "- Ha a modell egy tököt nem fehérnek jósol, és az a valóságban a 'fehér' kategóriába tartozik, akkor ezt `hamis negatívnak` nevezzük, amit a bal alsó szám mutat.\n", "\n", "- Ha a modell egy tököt fehérnek jósol, és az a valóságban a 'nem-fehér' kategóriába tartozik, akkor ezt `hamis pozitívnak` nevezzük, amit a jobb felső szám mutat.\n", "\n", "- Ha a modell egy tököt nem fehérnek jósol, és az a valóságban a 'nem-fehér' kategóriába tartozik, akkor ezt `igaz negatívnak` nevezzük, amit a jobb alsó szám mutat.\n", "\n", "| Valóság |\n", "|:-------:|\n", "\n", "\n", "| | | |\n", "|---------------|--------|-------|\n", "| **Jósolt** | FEHÉR | NARANCSSÁRGA |\n", "| FEHÉR | TP | FP |\n", "| NARANCSSÁRGA | FN | TN |\n", "\n", "Ahogy valószínűleg kitaláltad, előnyös, ha az igaz pozitív és igaz negatív értékek száma nagyobb, míg a hamis pozitív és hamis negatív értékek száma kisebb, mivel ez azt jelzi, hogy a modell jobban teljesít.\n", "\n", "A zavaró mátrix hasznos, mivel más mutatókat is létrehoz, amelyek segítenek jobban értékelni egy osztályozási modell teljesítményét. Nézzük meg ezeket:\n", "\n", "🎓 Pontosság: `TP/(TP + FP)` A pozitívnak jósolt értékek közül hány valóban pozitív. Más néven [pozitív prediktív érték](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n", "\n", "🎓 Visszahívás: `TP/(TP + FN)` Azoknak a pozitív eredményeknek az aránya, amelyek valóban pozitív mintákból származnak. Más néven `érzékenység`.\n", "\n", "🎓 Specificitás: `TN/(TN + FP)` Azoknak a negatív eredményeknek az aránya, amelyek valóban negatív mintákból származnak.\n", "\n", "🎓 Pontosság (Accuracy): `TP + TN/(TP + TN + FP + FN)` Azon címkék százaléka, amelyeket egy mintánál pontosan jósoltak meg.\n", "\n", "🎓 F-mérték: A pontosság és a visszahívás súlyozott átlaga, ahol a legjobb érték 1, a legrosszabb pedig 0.\n", "\n", "Számoljuk ki ezeket a mutatókat!\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": [ "## Ennek a modellnek az ROC görbéjének megjelenítése\n", "\n", "Készítsünk még egy vizualizációt, hogy megnézzük az úgynevezett [`ROC görbét`](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": [ "A ROC görbék gyakran használatosak annak szemléltetésére, hogy egy osztályozó milyen teljesítményt nyújt a valódi és hamis pozitív találatok tekintetében. A ROC görbék általában a `True Positive Rate`/Érzékenységet ábrázolják az Y tengelyen, míg a `False Positive Rate`/1-Specificitást az X tengelyen. Ezért a görbe meredeksége és a középvonal és a görbe közötti tér fontos: olyan görbét szeretnénk, amely gyorsan felfelé és a vonal fölé halad. A mi esetünkben kezdetben vannak hamis pozitív találatok, majd a vonal megfelelően felfelé és fölé halad.\n", "\n", "Végül használjuk a `yardstick::roc_auc()` függvényt a görbe alatti terület (Area Under the Curve) kiszámításához. Az AUC egyik értelmezési módja az, hogy ez annak a valószínűsége, hogy a modell egy véletlenszerűen kiválasztott pozitív példát magasabbra rangsorol, mint egy véletlenszerűen kiválasztott negatív példát.\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": [ "Az eredmény körülbelül `0.975`. Mivel az AUC 0 és 1 között mozog, magas értéket szeretnél elérni, hiszen egy modell, amely 100%-ban helyes előrejelzéseket ad, AUC értéke 1 lesz; ebben az esetben a modell *elég jó*.\n", "\n", "A jövőbeli leckékben a klasszifikációkról megtanulod, hogyan javíthatod a modell pontszámait (például az egyensúlyhiányos adatok kezelésével ebben az esetben).\n", "\n", "## 🚀Kihívás\n", "\n", "A logisztikus regresszióval kapcsolatban még sok felfedeznivaló van! De a legjobb módja a tanulásnak az, ha kísérletezel. Keress egy adathalmazt, amely alkalmas erre a típusú elemzésre, és építs egy modellt vele. Mit tanulsz? Tipp: próbáld ki [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) oldalt érdekes adathalmazokért.\n", "\n", "## Áttekintés és önálló tanulás\n", "\n", "Olvasd el [ennek a Stanford-i tanulmánynak](https://web.stanford.edu/~jurafsky/slp3/5.pdf) az első néhány oldalát a logisztikus regresszió gyakorlati alkalmazásairól. Gondolkodj el azon, hogy mely feladatok alkalmasabbak az egyik vagy másik típusú regressziós feladatra, amelyeket eddig tanulmányoztunk. Mi működne a legjobban?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Felelősségkizárás**: \nEz a dokumentum az [Co-op Translator](https://github.com/Azure/co-op-translator) AI fordítási szolgáltatás segítségével készült. Bár törekszünk a pontosságra, kérjük, vegye figyelembe, hogy az automatikus fordítások hibákat vagy pontatlanságokat tartalmazhatnak. Az eredeti dokumentum az eredeti nyelvén tekintendő hiteles forrásnak. Kritikus információk esetén javasolt a professzionális, emberi fordítás igénybevétele. Nem vállalunk felelősséget a fordítás használatából eredő félreértésekért vagy téves értelmezésekért.\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-04T06:56:58+00:00", "source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb", "language_code": "hu" } }, "nbformat": 4, "nbformat_minor": 1 }