{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Ustvarite model logistične regresije - Lekcija 4\n", "\n", "![Infografika: Logistična vs. linearna regresija](../../../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)\n", "\n", "#### **[Predhodni kviz](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n", "\n", "#### Uvod\n", "\n", "V tej zadnji lekciji o regresiji, eni izmed osnovnih *klasičnih* tehnik strojnega učenja, si bomo ogledali logistično regresijo. To tehniko bi uporabili za odkrivanje vzorcev za napovedovanje binarnih kategorij. Ali je ta sladkarija čokolada ali ne? Ali je ta bolezen nalezljiva ali ne? Ali bo ta stranka izbrala ta izdelek ali ne?\n", "\n", "V tej lekciji boste spoznali:\n", "\n", "- Tehnike za logistično regresijo\n", "\n", "✅ Poglobite svoje razumevanje dela s to vrsto regresije v tem [učnem modulu](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n", "\n", "## Predpogoji\n", "\n", "Ker smo že delali s podatki o bučah, smo zdaj dovolj seznanjeni z njimi, da ugotovimo, da obstaja ena binarna kategorija, s katero lahko delamo: `Barva`.\n", "\n", "Zgradimo model logistične regresije, da napovemo, glede na nekatere spremenljivke, *kakšne barve bo določena buča verjetno* (oranžna 🎃 ali bela 👻).\n", "\n", "> Zakaj govorimo o binarni klasifikaciji v lekciji, ki se ukvarja z regresijo? Izključno zaradi jezikovne priročnosti, saj je logistična regresija [pravzaprav metoda klasifikacije](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), čeprav temelji na linearni metodi. Več o drugih načinih klasifikacije podatkov boste izvedeli v naslednji skupini lekcij.\n", "\n", "Za to lekcijo bomo potrebovali naslednje pakete:\n", "\n", "- `tidyverse`: [Tidyverse](https://www.tidyverse.org/) je [zbirka paketov za R](https://www.tidyverse.org/packages), zasnovana za hitrejše, lažje in bolj zabavno delo z podatki!\n", "\n", "- `tidymodels`: [Tidymodels](https://www.tidymodels.org/) je okvir [zbirke paketov](https://www.tidymodels.org/packages/) za modeliranje in strojno učenje.\n", "\n", "- `janitor`: Paket [janitor](https://github.com/sfirke/janitor) ponuja preprosta orodja za pregledovanje in čiščenje umazanih podatkov.\n", "\n", "- `ggbeeswarm`: Paket [ggbeeswarm](https://github.com/eclarke/ggbeeswarm) omogoča ustvarjanje grafov v slogu \"beeswarm\" z uporabo ggplot2.\n", "\n", "Namestite jih lahko z ukazom:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n", "\n", "Alternativno, spodnji skript preveri, ali imate potrebne pakete za dokončanje tega modula, in jih namesti, če manjkajo.\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": [ "## **Določite vprašanje**\n", "\n", "Za naše namene bomo to izrazili kot binarno: 'Bela' ali 'Ne bela'. V našem naboru podatkov obstaja tudi kategorija 'črtasta', vendar je primerov te kategorije malo, zato je ne bomo uporabili. Kategorija tako ali tako izgine, ko odstranimo ničelne vrednosti iz nabora podatkov.\n", "\n", "> 🎃 Zabavno dejstvo: bele buče včasih imenujemo 'duhove' buče. Niso zelo enostavne za rezljanje, zato niso tako priljubljene kot oranžne, vendar so videti kul! Tako bi lahko naše vprašanje preoblikovali tudi kot: 'Duh' ali 'Ne duh'. 👻\n", "\n", "## **O logistični regresiji**\n", "\n", "Logistična regresija se od linearne regresije, o kateri ste se že učili, razlikuje v nekaj pomembnih vidikih.\n", "\n", "#### **Binarna klasifikacija**\n", "\n", "Logistična regresija ne ponuja enakih funkcij kot linearna regresija. Prva ponuja napoved o `binarni kategoriji` (\"oranžna ali ne oranžna\"), medtem ko je druga sposobna napovedovati `neprekinjene vrednosti`, na primer glede na izvor buče in čas žetve, *koliko se bo njena cena zvišala*.\n", "\n", "![Infografika avtorja Dasani Madipalli](../../../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)\n", "\n", "### Druge klasifikacije\n", "\n", "Obstajajo tudi druge vrste logistične regresije, vključno z multinomno in ordinalno:\n", "\n", "- **Multinomna**, ki vključuje več kot eno kategorijo - \"Oranžna, Bela in Črtasta\".\n", "\n", "- **Ordinalna**, ki vključuje urejene kategorije, uporabna, če želimo logično urediti naše rezultate, na primer naše buče, ki so razvrščene po končnem številu velikosti (mini,sm,med,lg,xl,xxl).\n", "\n", "![Multinomna vs ordinalna regresija](../../../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)\n", "\n", "#### **Spremenljivke NI NUJNO, da so povezane**\n", "\n", "Se spomnite, kako je linearna regresija bolje delovala z bolj povezanimi spremenljivkami? Logistična regresija je nasprotje - spremenljivke ni nujno, da se ujemajo. To ustreza tem podatkom, ki imajo nekoliko šibke korelacije.\n", "\n", "#### **Potrebujete veliko čistih podatkov**\n", "\n", "Logistična regresija bo dala natančnejše rezultate, če uporabite več podatkov; naš majhen nabor podatkov ni optimalen za to nalogo, zato imejte to v mislih.\n", "\n", "✅ Razmislite o vrstah podatkov, ki bi bile primerne za logistično regresijo.\n", "\n", "## Naloga - uredite podatke\n", "\n", "Najprej nekoliko očistite podatke, odstranite ničelne vrednosti in izberite le nekatere stolpce:\n", "\n", "1. Dodajte naslednjo kodo:\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": [ "Vedno lahko pogledate svoj novi podatkovni okvir z uporabo funkcije [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html), kot je prikazano spodaj:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "pumpkins_select %>% \n", " glimpse()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Potrdimo, da bomo dejansko reševali problem binarne klasifikacije:\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": [ "### Vizualizacija - kategorni graf\n", "Do sedaj ste znova naložili podatke o bučah in jih očistili, da ste ohranili podatkovni niz, ki vsebuje nekaj spremenljivk, vključno z Barvo. Vizualizirajmo podatkovni okvir v zvezku z uporabo knjižnice ggplot.\n", "\n", "Knjižnica ggplot ponuja nekaj odličnih načinov za vizualizacijo vaših podatkov. Na primer, lahko primerjate porazdelitve podatkov za vsako Sorto in Barvo v kategorni graf.\n", "\n", "1. Ustvarite takšen graf z uporabo funkcije geombar, pri čemer uporabite naše podatke o bučah in določite barvno preslikavo za vsako kategorijo buč (oranžna ali bela):\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": [ "Z opazovanjem podatkov lahko vidite, kako so podatki o barvi povezani z vrsto.\n", "\n", "✅ Glede na ta kategorni graf, katere zanimive raziskave si lahko predstavljate?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Predobdelava podatkov: kodiranje značilnosti\n", "\n", "Naš nabor podatkov o bučah vsebuje nize kot vrednosti za vse stolpce. Delo s kategorialnimi podatki je za ljudi intuitivno, za računalnike pa ne. Algoritmi strojnega učenja delujejo dobro s številkami. Zato je kodiranje zelo pomemben korak v fazi predobdelave podatkov, saj nam omogoča, da kategorialne podatke pretvorimo v številske, ne da bi pri tem izgubili informacije. Dobro kodiranje vodi do gradnje dobrega modela.\n", "\n", "Za kodiranje značilnosti obstajata dve glavni vrsti kodirnikov:\n", "\n", "1. **Ordinalni kodirnik**: Ta je primeren za ordinalne spremenljivke, torej kategorialne spremenljivke, kjer podatki sledijo logičnemu vrstnemu redu, kot je stolpec `item_size` v našem naboru podatkov. Ustvari preslikavo, kjer je vsaka kategorija predstavljena s številko, ki ustreza vrstnemu redu kategorije v stolpcu.\n", "\n", "2. **Kategorialni kodirnik**: Ta je primeren za nominalne spremenljivke, torej kategorialne spremenljivke, kjer podatki ne sledijo logičnemu vrstnemu redu, kot so vse značilnosti, ki niso `item_size` v našem naboru podatkov. Gre za kodiranje \"ena-vroča\" (one-hot encoding), kar pomeni, da je vsaka kategorija predstavljena z binarnim stolpcem: kodirana spremenljivka je enaka 1, če buča pripada tej sorti, in 0 sicer.\n", "\n", "Tidymodels ponuja še eno uporabno knjižnico: [recipes](https://recipes.tidymodels.org/) - knjižnico za predobdelavo podatkov. Določili bomo `recipe`, ki opredeljuje, da je treba vse stolpce napovedovalcev zakodirati v nabor celih števil, nato pa ga `prep`-irati, da ocenimo potrebne količine in statistike za posamezne operacije, in na koncu `bake`, da uporabimo izračune na novih podatkih.\n", "\n", "> Običajno se recipes uporablja kot predprocesor za modeliranje, kjer določa, kateri koraki naj se uporabijo na naboru podatkov, da ga pripravimo za modeliranje. V tem primeru je **zelo priporočljivo**, da uporabite `workflow()` namesto ročnega ocenjevanja recepta z uporabo prep in bake. Vse to bomo videli v kratkem.\n", ">\n", "> Zaenkrat pa uporabljamo recipes + prep + bake, da določimo, kateri koraki naj se uporabijo na naboru podatkov, da ga pripravimo za analizo podatkov, in nato izvlečemo predobdelane podatke z uporabljenimi koraki.\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": [ "✅ Kakšne so prednosti uporabe ordinalnega kodirnika za stolpec Velikost artikla?\n", "\n", "### Analizirajte odnose med spremenljivkami\n", "\n", "Zdaj, ko smo predhodno obdelali naše podatke, lahko analiziramo odnose med značilnostmi in oznako, da dobimo predstavo o tem, kako dobro bo model lahko napovedal oznako glede na značilnosti. Najboljši način za izvedbo takšne analize je vizualizacija podatkov. \n", "Ponovno bomo uporabili funkcijo ggplot geom_boxplot_, da vizualiziramo odnose med Velikostjo artikla, Sorto in Barvo v kategorijskem grafu. Za boljšo vizualizacijo podatkov bomo uporabili kodiran stolpec Velikost artikla in nekodiran stolpec Sorta.\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": [ "#### Uporaba swarm plota\n", "\n", "Ker je Barva binarna kategorija (Bela ali Ne), zahteva 'poseben pristop [k vizualizaciji](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf)'.\n", "\n", "Poskusite uporabiti `swarm plot`, da prikažete porazdelitev barve glede na velikost predmeta.\n", "\n", "Uporabili bomo [paket ggbeeswarm](https://github.com/eclarke/ggbeeswarm), ki ponuja metode za ustvarjanje grafov v slogu beeswarm z uporabo ggplot2. Beeswarm grafi so način prikaza točk, ki bi se sicer prekrivale, tako da so razporejene ena poleg druge.\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": [ "Zdaj, ko imamo predstavo o razmerju med binarnimi kategorijami barve in večjo skupino velikosti, raziščimo logistično regresijo za določitev verjetne barve določene buče.\n", "\n", "## Ustvarite svoj model\n", "\n", "Izberite spremenljivke, ki jih želite uporabiti v svojem klasifikacijskem modelu, in razdelite podatke na učne in testne sklope. [rsample](https://rsample.tidymodels.org/), paket v Tidymodels, zagotavlja infrastrukturo za učinkovito razdeljevanje podatkov in ponovno vzorčenje:\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": [ "🙌 Zdaj smo pripravljeni, da model naučimo tako, da prilagodimo učne značilnosti učni oznaki (barvi).\n", "\n", "Začeli bomo z ustvarjanjem recepta, ki določa korake predobdelave, ki jih je treba izvesti na naših podatkih, da jih pripravimo za modeliranje, tj. kodiranje kategornih spremenljivk v niz celih števil. Tako kot `baked_pumpkins`, ustvarimo `pumpkins_recipe`, vendar ga ne `prep` in `bake`, saj bo vključen v delovni tok, kar boste videli v le nekaj korakih.\n", "\n", "Obstaja kar nekaj načinov za določitev logistične regresije v Tidymodels. Oglejte si `?logistic_reg()`. Za zdaj bomo določili model logistične regresije prek privzetega pogona `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": [ "Zdaj, ko imamo recept in specifikacijo modela, moramo najti način, kako ju združiti v objekt, ki bo najprej predobdelal podatke (v ozadju uporabil funkciji prep + bake), nato prilagodil model na predobdelane podatke in omogočil tudi morebitne aktivnosti po obdelavi.\n", "\n", "V Tidymodels se ta priročen objekt imenuje [`workflow`](https://workflows.tidymodels.org/) in priročno združuje vaše komponente modeliranja.\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": [ "Ko je potek dela *določen*, lahko model `usposobimo` z uporabo funkcije [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html). Potek dela bo ocenil recept in predhodno obdelal podatke pred usposabljanjem, zato tega ne bo treba ročno narediti z uporabo funkcij prep in 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": [ "Model izpiše koeficiente, pridobljene med usposabljanjem.\n", "\n", "Zdaj, ko smo model usposobili z uporabo učnih podatkov, lahko naredimo napovedi na testnih podatkih z uporabo [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Začnimo z uporabo modela za napovedovanje oznak za naš testni niz in verjetnosti za vsako oznako. Ko je verjetnost večja od 0.5, je napovedan razred `WHITE`, sicer `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": [ "Zelo lepo! To ponuja nekaj več vpogleda v delovanje logistične regresije.\n", "\n", "### Boljše razumevanje prek matrike zmede\n", "\n", "Primerjanje vsake napovedi z ustrezno \"resnično vrednostjo\" ni zelo učinkovit način za določanje, kako dobro model napoveduje. Na srečo ima Tidymodels še nekaj trikov v rokavu: [`yardstick`](https://yardstick.tidymodels.org/) - paket, ki se uporablja za merjenje učinkovitosti modelov z uporabo metrik uspešnosti.\n", "\n", "Ena od metrik uspešnosti, povezanih s klasifikacijskimi problemi, je [`matrika zmede`](https://wikipedia.org/wiki/Confusion_matrix). Matrika zmede opisuje, kako dobro klasifikacijski model deluje. Matrika zmede prikazuje, koliko primerov v vsakem razredu je model pravilno klasificiral. V našem primeru bo pokazala, koliko oranžnih buč je bilo klasificiranih kot oranžne in koliko belih buč kot bele; matrika zmede prav tako prikazuje, koliko jih je bilo klasificiranih v **napačne** kategorije.\n", "\n", "Funkcija [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) iz paketa yardstick izračuna to križno tabelo opazovanih in napovedanih razredov.\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": [ "Poglejmo, kako interpretirati matriko zmede. Naš model mora razvrstiti buče v dve binarni kategoriji, kategorijo `bela` in kategorijo `ne-bela`.\n", "\n", "- Če vaš model napove, da je buča bela, in ta v resnici spada v kategorijo 'bela', temu pravimo `prava pozitivna napoved` (true positive), kar je prikazano s številom v zgornjem levem kotu.\n", "\n", "- Če vaš model napove, da buča ni bela, in ta v resnici spada v kategorijo 'bela', temu pravimo `napačna negativna napoved` (false negative), kar je prikazano s številom v spodnjem levem kotu.\n", "\n", "- Če vaš model napove, da je buča bela, in ta v resnici spada v kategorijo 'ne-bela', temu pravimo `napačna pozitivna napoved` (false positive), kar je prikazano s številom v zgornjem desnem kotu.\n", "\n", "- Če vaš model napove, da buča ni bela, in ta v resnici spada v kategorijo 'ne-bela', temu pravimo `prava negativna napoved` (true negative), kar je prikazano s številom v spodnjem desnem kotu.\n", "\n", "| Resnica |\n", "|:-------:|\n", "\n", "| | | |\n", "|---------------|--------|-------|\n", "| **Napovedano** | BELA | ORANŽNA |\n", "| BELA | TP | FP |\n", "| ORANŽNA | FN | TN |\n", "\n", "Kot ste morda uganili, je zaželeno imeti večje število pravih pozitivnih in pravih negativnih napovedi ter manjše število napačnih pozitivnih in napačnih negativnih napovedi, saj to pomeni, da model deluje bolje.\n", "\n", "Matrika zmede je koristna, saj omogoča izračun drugih metrik, ki nam pomagajo bolje oceniti uspešnost klasifikacijskega modela. Poglejmo si nekatere od njih:\n", "\n", "🎓 Natančnost (Precision): `TP/(TP + FP)` je definirana kot delež napovedanih pozitivnih primerov, ki so dejansko pozitivni. Imenujemo jo tudi [pozitivna napovedna vrednost](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n", "\n", "🎓 Priklic (Recall): `TP/(TP + FN)` je definiran kot delež pozitivnih rezultatov glede na število vzorcev, ki so dejansko pozitivni. Imenujemo ga tudi `občutljivost` (sensitivity).\n", "\n", "🎓 Specifičnost (Specificity): `TN/(TN + FP)` je definirana kot delež negativnih rezultatov glede na število vzorcev, ki so dejansko negativni.\n", "\n", "🎓 Točnost (Accuracy): `TP + TN/(TP + TN + FP + FN)` je odstotek oznak, ki so bile pravilno napovedane za vzorec.\n", "\n", "🎓 F-metrika (F Measure): Tehtano povprečje natančnosti in priklica, kjer je najboljša vrednost 1, najslabša pa 0.\n", "\n", "Izračunajmo te metrike!\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": [ "## Vizualizirajmo ROC krivuljo tega modela\n", "\n", "Naredimo še eno vizualizacijo, da si ogledamo tako imenovano [`ROC krivuljo`](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 krivulje se pogosto uporabljajo za prikaz rezultatov klasifikatorja glede na njegove prave in lažne pozitivne zadetke. ROC krivulje običajno prikazujejo `True Positive Rate`/občutljivost na Y osi in `False Positive Rate`/1-specifičnost na X osi. Zato sta strmina krivulje in prostor med sredinsko črto ter krivuljo pomembna: želite krivuljo, ki se hitro dvigne in preseže črto. V našem primeru se začne z lažnimi pozitivnimi zadetki, nato pa se črta pravilno dvigne in preseže.\n", "\n", "Na koncu uporabimo `yardstick::roc_auc()` za izračun dejanskega območja pod krivuljo (Area Under the Curve). Eden od načinov interpretacije AUC je kot verjetnost, da model naključno pozitivni primer razvrsti višje kot naključno negativni primer.\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": [ "Rezultat je približno `0.975`. Ker se AUC giblje med 0 in 1, si želite visok rezultat, saj bo model, ki je 100 % natančen v svojih napovedih, imel AUC vrednost 1; v tem primeru je model *kar dober*.\n", "\n", "V prihodnjih lekcijah o klasifikacijah boste spoznali, kako izboljšati rezultate svojega modela (na primer obravnavanje neuravnoteženih podatkov v tem primeru).\n", "\n", "## 🚀Izziv\n", "\n", "Logistična regresija ponuja še veliko več! Najboljši način za učenje je eksperimentiranje. Poiščite podatkovni niz, ki je primeren za tovrstno analizo, in zgradite model z njim. Kaj ste se naučili? namig: poskusite [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) za zanimive podatkovne nize.\n", "\n", "## Pregled in samostojno učenje\n", "\n", "Preberite prvih nekaj strani [tega dokumenta iz Stanforda](https://web.stanford.edu/~jurafsky/slp3/5.pdf) o praktični uporabi logistične regresije. Razmislite o nalogah, ki so bolj primerne za eno ali drugo vrsto regresijskih nalog, ki smo jih preučevali do zdaj. Kaj bi delovalo najbolje?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Omejitev odgovornosti**: \nTa dokument je bil preveden z uporabo storitve za strojno prevajanje [Co-op Translator](https://github.com/Azure/co-op-translator). Čeprav si prizadevamo za natančnost, vas prosimo, da se zavedate, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem izvirnem jeziku je treba obravnavati kot avtoritativni vir. Za ključne informacije priporočamo strokovno človeško prevajanje. Ne prevzemamo odgovornosti za morebitna nesporazumevanja ali napačne razlage, ki izhajajo iz uporabe tega prevoda.\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:31:00+00:00", "source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb", "language_code": "sl" } }, "nbformat": 4, "nbformat_minor": 1 }