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.
686 lines
32 KiB
686 lines
32 KiB
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Építsünk egy logisztikus regressziós modellt - 4. lecke\n",
|
|
"\n",
|
|
"\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",
|
|
"\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",
|
|
"\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
|
|
} |