{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Sukurkite logistinės regresijos modelį - Pamoka 4\n", "\n", "![Logistinės ir linijinės regresijos infografikas](../../../../../../translated_images/linear-vs-logistic.ba180bf95e7ee66721ba10ebf2dac2666acbd64a88b003c83928712433a13c7d.lt.png)\n", "\n", "#### **[Klausimynas prieš paskaitą](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n", "\n", "#### Įvadas\n", "\n", "Šioje paskutinėje pamokoje apie regresiją, vieną iš pagrindinių *klasikinių* ML technikų, apžvelgsime logistinę regresiją. Šią techniką galite naudoti norėdami atrasti dėsningumus, kurie padės prognozuoti dvejetaines kategorijas. Ar šis saldainis yra šokoladas, ar ne? Ar ši liga yra užkrečiama, ar ne? Ar šis klientas pasirinks šį produktą, ar ne?\n", "\n", "Šioje pamokoje sužinosite:\n", "\n", "- Logistinės regresijos technikas\n", "\n", "✅ Gilinkite savo supratimą apie darbą su šio tipo regresija šiame [mokymosi modulyje](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n", "\n", "## Būtinos žinios\n", "\n", "Dirbdami su moliūgų duomenimis, jau pakankamai gerai juos pažįstame, kad suprastume, jog yra viena dvejetainė kategorija, su kuria galime dirbti: `Spalva`.\n", "\n", "Sukurkime logistinės regresijos modelį, kuris prognozuotų, remiantis tam tikrais kintamaisiais, *kokia tikėtina moliūgo spalva* (oranžinė 🎃 ar balta 👻).\n", "\n", "> Kodėl kalbame apie dvejetainę klasifikaciją pamokoje, susijusioje su regresija? Tik dėl lingvistinio patogumo, nes logistinė regresija yra [iš tikrųjų klasifikavimo metodas](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), nors ir pagrįstas linijine regresija. Sužinokite apie kitus duomenų klasifikavimo būdus kitame pamokų cikle.\n", "\n", "Šiai pamokai mums reikės šių paketų:\n", "\n", "- `tidyverse`: [tidyverse](https://www.tidyverse.org/) yra [R paketų rinkinys](https://www.tidyverse.org/packages), sukurtas tam, kad duomenų mokslas būtų greitesnis, paprastesnis ir įdomesnis!\n", "\n", "- `tidymodels`: [tidymodels](https://www.tidymodels.org/) sistema yra [paketų rinkinys](https://www.tidymodels.org/packages/) modeliavimui ir mašininio mokymosi užduotims.\n", "\n", "- `janitor`: [janitor paketas](https://github.com/sfirke/janitor) siūlo paprastus įrankius nešvarių duomenų peržiūrai ir valymui.\n", "\n", "- `ggbeeswarm`: [ggbeeswarm paketas](https://github.com/eclarke/ggbeeswarm) leidžia kurti \"bičių spiečiaus\" stiliaus diagramas naudojant ggplot2.\n", "\n", "Galite juos įdiegti naudodami:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n", "\n", "Arba, žemiau pateiktas scenarijus patikrina, ar turite reikalingus paketus šiam moduliui užbaigti, ir, jei jų trūksta, įdiegia juos už jus.\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": [ "## **Apibrėžkite klausimą**\n", "\n", "Mūsų atveju klausimą išreikšime kaip dvejetainį pasirinkimą: „Balta“ arba „Ne balta“. Mūsų duomenų rinkinyje taip pat yra „dryžuota“ kategorija, tačiau jos pavyzdžių yra labai mažai, todėl jos nenaudosime. Be to, ji išnyksta, kai pašaliname null reikšmes iš duomenų rinkinio.\n", "\n", "> 🎃 Smagus faktas: kartais baltus moliūgus vadiname „vaiduoklių“ moliūgais. Juos nėra lengva išskaptuoti, todėl jie nėra tokie populiarūs kaip oranžiniai, bet atrodo tikrai įspūdingai! Taigi, galėtume savo klausimą performuluoti taip: „Vaiduoklis“ arba „Ne vaiduoklis“. 👻\n", "\n", "## **Apie logistinę regresiją**\n", "\n", "Logistinė regresija skiriasi nuo linijinės regresijos, apie kurią jau mokėtės, keliais svarbiais aspektais.\n", "\n", "#### **Dvejetainė klasifikacija**\n", "\n", "Logistinė regresija nepasiūlo tų pačių galimybių kaip linijinė regresija. Pirmoji pateikia prognozę apie `dvejetainę kategoriją` („oranžinis arba ne oranžinis“), o antroji gali prognozuoti `tęstines reikšmes`, pavyzdžiui, atsižvelgiant į moliūgo kilmę ir derliaus nuėmimo laiką, *kaip kils jo kaina*.\n", "\n", "![Infografikas, sukurtas Dasani Madipalli](../../../../../../translated_images/pumpkin-classifier.562771f104ad5436b87d1c67bca02a42a17841133556559325c0a0e348e5b774.lt.png)\n", "\n", "### Kitos klasifikacijos\n", "\n", "Yra ir kitų logistinės regresijos tipų, įskaitant daugialypę ir ranginę:\n", "\n", "- **Daugialypė**, kuri apima daugiau nei vieną kategoriją - „Oranžinis, Baltas ir Dryžuotas“.\n", "\n", "- **Ranginė**, kuri apima tvarkingas kategorijas, naudingas, jei norėtume logiškai išdėstyti savo rezultatus, pavyzdžiui, moliūgus, kurie yra išdėstyti pagal ribotą dydžių skaičių (mini, mažas, vidutinis, didelis, labai didelis, milžiniškas).\n", "\n", "![Daugialypė vs ranginė regresija](../../../../../../translated_images/multinomial-vs-ordinal.36701b4850e37d86c9dd49f7bef93a2f94dbdb8fe03443eb68f0542f97f28f29.lt.png)\n", "\n", "#### **Kintamieji NETURI būti koreliuoti**\n", "\n", "Ar prisimenate, kaip linijinė regresija geriau veikė su labiau koreliuotais kintamaisiais? Logistinė regresija yra priešinga – kintamieji neprivalo būti suderinti. Tai tinka šiems duomenims, kuriuose koreliacijos yra gana silpnos.\n", "\n", "#### **Reikia daug švarių duomenų**\n", "\n", "Logistinė regresija pateiks tikslesnius rezultatus, jei naudosite daugiau duomenų; mūsų mažas duomenų rinkinys nėra optimalus šiai užduočiai, todėl turėkite tai omenyje.\n", "\n", "✅ Pagalvokite apie duomenų tipus, kurie geriausiai tiktų logistinei regresijai.\n", "\n", "## Užduotis – sutvarkykite duomenis\n", "\n", "Pirmiausia šiek tiek išvalykite duomenis, pašalindami null reikšmes ir pasirinkdami tik kai kuriuos stulpelius:\n", "\n", "1. Pridėkite šį 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": [ "Visada galite pažvelgti į savo naują duomenų rėmelį, naudodami funkciją [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html), kaip parodyta žemiau:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "pumpkins_select %>% \n", " glimpse()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Patvirtinkime, kad iš tiesų spręsime dvejetainės klasifikacijos problemą:\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 - kategorinis grafikas\n", "Iki šiol jūs vėl įkėlėte moliūgų duomenis ir juos išvalėte, kad išsaugotumėte duomenų rinkinį, kuriame yra keletas kintamųjų, įskaitant Spalvą. Vizualizuokime duomenų rėmelį užrašų knygelėje naudodami ggplot biblioteką.\n", "\n", "Ggplot biblioteka siūlo puikius būdus vizualizuoti jūsų duomenis. Pavyzdžiui, galite palyginti duomenų pasiskirstymą pagal kiekvieną Veislę ir Spalvą kategoriniame grafike.\n", "\n", "1. Sukurkite tokį grafiką naudodami geombar funkciją, naudodami mūsų moliūgų duomenis ir nurodydami spalvų žymėjimą kiekvienai moliūgų kategorijai (oranžiniai arba balti):\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": [ "Stebėdami duomenis, galite matyti, kaip Spalvos duomenys susiję su Įvairove.\n", "\n", "✅ Atsižvelgiant į šį kategorinį grafiką, kokius įdomius tyrimus galite įsivaizduoti?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Duomenų paruošimas: savybių kodavimas\n", "\n", "Mūsų moliūgų duomenų rinkinyje visos stulpelių reikšmės yra tekstinės. Darbas su kategoriniais duomenimis yra intuityvus žmonėms, tačiau ne mašinoms. Mašininio mokymosi algoritmai geriau veikia su skaičiais. Todėl kodavimas yra labai svarbus duomenų paruošimo etapas, nes jis leidžia paversti kategorinius duomenis į skaitinius, neprarandant informacijos. Geras kodavimas padeda sukurti gerą modelį.\n", "\n", "Savybių kodavimui yra du pagrindiniai kodavimo tipai:\n", "\n", "1. Ordinalinis koduotojas: jis gerai tinka ordinaliniams kintamiesiems, kurie yra kategoriniai kintamieji, kurių duomenys turi logišką tvarką, kaip, pavyzdžiui, `item_size` stulpelis mūsų duomenų rinkinyje. Jis sukuria žemėlapį, kuriame kiekviena kategorija yra atvaizduojama skaičiumi, kuris atitinka kategorijos tvarką stulpelyje.\n", "\n", "2. Kategorinis koduotojas: jis gerai tinka nominaliniams kintamiesiems, kurie yra kategoriniai kintamieji, kurių duomenys neturi logiškos tvarkos, kaip visi kiti požymiai, išskyrus `item_size`, mūsų duomenų rinkinyje. Tai yra vieno karštojo kodavimo metodas, kuris reiškia, kad kiekviena kategorija yra atvaizduojama dvejetainiu stulpeliu: užkoduota reikšmė yra lygi 1, jei moliūgas priklauso tai veislei, ir 0, jei ne.\n", "\n", "Tidymodels siūlo dar vieną naudingą paketą: [recipes](https://recipes.tidymodels.org/) – paketą duomenų paruošimui. Mes apibrėšime `recipe`, kuris nurodo, kad visi prognozuojamieji stulpeliai turėtų būti užkoduoti į skaičių rinkinį, `prep`, kad apskaičiuotume reikalingus kiekius ir statistikas, reikalingas bet kokioms operacijoms, ir galiausiai `bake`, kad pritaikytume skaičiavimus naujiems duomenims.\n", "\n", "> Paprastai recipes dažniausiai naudojamas kaip paruošimo įrankis modeliavimui, kur jis apibrėžia, kokie žingsniai turėtų būti taikomi duomenų rinkiniui, kad jis būtų paruoštas modeliavimui. Tokiu atveju **labai rekomenduojama** naudoti `workflow()` vietoj rankinio recepto apskaičiavimo naudojant prep ir bake. Visa tai pamatysime netrukus.\n", ">\n", "> Tačiau šiuo metu mes naudojame recipes + prep + bake, kad nurodytume, kokie žingsniai turėtų būti taikomi duomenų rinkiniui, kad jis būtų paruoštas duomenų analizei, ir tada išgautume apdorotus duomenis su pritaikytais žingsniais.\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": [ "✅ Kokie yra privalumai naudojant ordinal encoder Item Size stulpeliui?\n", "\n", "### Analizuokite ryšius tarp kintamųjų\n", "\n", "Dabar, kai apdorojome savo duomenis, galime analizuoti ryšius tarp požymių ir etiketės, kad suprastume, kaip gerai modelis galės prognozuoti etiketę remdamasis požymiais. Geriausias būdas atlikti tokio tipo analizę yra duomenų vizualizavimas. \n", "Vėl naudosime ggplot geom_boxplot_ funkciją, kad vizualizuotume ryšius tarp Item Size, Variety ir Color kategoriniame grafike. Kad geriau pavaizduotume duomenis, naudosime užkoduotą Item Size stulpelį ir neužkoduotą Variety stulpelį.\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": [ "#### Naudokite spiečiaus diagramą\n", "\n", "Kadangi spalva yra dvejetainė kategorija (Balta arba Ne), jai reikalingas '[specializuotas požiūris](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf)' vizualizacijai.\n", "\n", "Pabandykite naudoti `spiečiaus diagramą`, kad parodytumėte spalvų pasiskirstymą pagal daikto dydį.\n", "\n", "Naudosime [ggbeeswarm paketą](https://github.com/eclarke/ggbeeswarm), kuris suteikia metodus kurti spiečiaus tipo diagramas naudojant ggplot2. Spiečiaus diagramos leidžia vizualizuoti taškus, kurie paprastai persidengtų, taip, kad jie būtų išdėstyti vienas šalia kito.\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": [ "Dabar, kai turime supratimą apie ryšį tarp dvejetainių spalvų kategorijų ir didesnės dydžių grupės, panagrinėkime logistinės regresijos metodą, kad nustatytume tikėtiną moliūgo spalvą.\n", "\n", "## Sukurkite savo modelį\n", "\n", "Pasirinkite kintamuosius, kuriuos norite naudoti klasifikavimo modelyje, ir padalykite duomenis į mokymo ir testavimo rinkinius. [rsample](https://rsample.tidymodels.org/), Tidymodels paketas, suteikia infrastruktūrą efektyviam duomenų skirstymui ir perskirstymui:\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": [ "🙌 Dabar esame pasiruošę treniruoti modelį, pritaikydami mokymo požymius prie mokymo etiketės (spalvos).\n", "\n", "Pradėsime kurdami receptą, kuris nurodo duomenų apdorojimo veiksmus, reikalingus pasiruošti modeliui, pvz.: kategorinių kintamųjų kodavimą į sveikuosius skaičius. Kaip ir su `baked_pumpkins`, sukuriame `pumpkins_recipe`, tačiau nenaudojame `prep` ir `bake`, nes tai bus įtraukta į darbo eigą, kurią pamatysite vos po kelių žingsnių.\n", "\n", "Yra nemažai būdų, kaip Tidymodels nurodyti logistinės regresijos modelį. Žr. `?logistic_reg()`. Šiuo metu nurodysime logistinės regresijos modelį naudodami numatytąjį `stats::glm()` variklį.\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": [ "Dabar, kai turime receptą ir modelio specifikaciją, turime rasti būdą, kaip juos sujungti į objektą, kuris pirmiausia apdoros duomenis (užkulisiuose atliks paruošimą ir kepimą), pritaikys modelį apdorotiems duomenims ir taip pat leis atlikti galimas poapdorojimo veiklas.\n", "\n", "Tidymodels aplinkoje šis patogus objektas vadinamas [`workflow`](https://workflows.tidymodels.org/) ir patogiai talpina jūsų modeliavimo komponentus.\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": [ "Kai darbo eiga yra *nurodyta*, modelis gali būti `apmokytas` naudojant [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html) funkciją. Darbo eiga įvertins receptą ir apdoros duomenis prieš apmokymą, todėl mums nereikės to daryti rankiniu būdu naudojant prep ir 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": [ "Modelio spausdinimas rodo koeficientus, išmokytus mokymo metu.\n", "\n", "Dabar, kai modelis buvo išmokytas naudojant mokymo duomenis, galime atlikti prognozes su testavimo duomenimis naudodami [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Pradėkime nuo modelio naudojimo, kad prognozuotume etiketes mūsų testavimo rinkiniui ir tikimybes kiekvienai etikečių klasei. Kai tikimybė yra didesnė nei 0.5, prognozuojama klasė yra `WHITE`, kitu atveju - `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": [ "Labai šaunu! Tai suteikia daugiau įžvalgų apie tai, kaip veikia logistinė regresija.\n", "\n", "### Geresnis supratimas naudojant painiavos matricą\n", "\n", "Lyginti kiekvieną prognozę su atitinkama „tikrąja“ faktine verte nėra labai efektyvus būdas nustatyti, kaip gerai modelis prognozuoja. Laimei, Tidymodels turi keletą papildomų gudrybių: [`yardstick`](https://yardstick.tidymodels.org/) - paketą, skirtą modelių efektyvumui matuoti naudojant našumo metrikas.\n", "\n", "Viena iš našumo metrikų, susijusių su klasifikavimo problemomis, yra [`painiavos matrica`](https://wikipedia.org/wiki/Confusion_matrix). Painiavos matrica apibūdina, kaip gerai veikia klasifikavimo modelis. Painiavos matrica parodo, kiek pavyzdžių kiekvienoje klasėje buvo teisingai klasifikuoti modelio. Mūsų atveju ji parodys, kiek oranžinių moliūgų buvo klasifikuoti kaip oranžiniai ir kiek baltų moliūgų buvo klasifikuoti kaip balti; painiavos matrica taip pat parodys, kiek jų buvo klasifikuoti į **neteisingas** kategorijas.\n", "\n", "Funkcija [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) iš yardstick apskaičiuoja šį stebėtų ir prognozuotų klasių kryžminį suskirstymą.\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": [ "Paaiškinkime painiavos matricą. Mūsų modelis turi klasifikuoti moliūgus į dvi kategorijas: kategoriją `baltas` ir kategoriją `ne baltas`.\n", "\n", "- Jei jūsų modelis prognozuoja, kad moliūgas yra baltas, ir jis iš tikrųjų priklauso kategorijai „baltas“, tai vadiname `teigiamu tikruoju` (angl. true positive), kurį rodo viršutinis kairysis skaičius.\n", "\n", "- Jei jūsų modelis prognozuoja, kad moliūgas nėra baltas, bet jis iš tikrųjų priklauso kategorijai „baltas“, tai vadiname `neigiamu klaidingu` (angl. false negative), kurį rodo apatinis kairysis skaičius.\n", "\n", "- Jei jūsų modelis prognozuoja, kad moliūgas yra baltas, bet jis iš tikrųjų priklauso kategorijai „ne baltas“, tai vadiname `teigiamu klaidingu` (angl. false positive), kurį rodo viršutinis dešinysis skaičius.\n", "\n", "- Jei jūsų modelis prognozuoja, kad moliūgas nėra baltas, ir jis iš tikrųjų priklauso kategorijai „ne baltas“, tai vadiname `neigiamu tikruoju` (angl. true negative), kurį rodo apatinis dešinysis skaičius.\n", "\n", "| Tiesa |\n", "|:-----:|\n", "\n", "| | | |\n", "|---------------|--------|-------|\n", "| **Prognozuota** | BALTAS | ORANŽINIS |\n", "| BALTAS | TP | FP |\n", "| ORANŽINIS | FN | TN |\n", "\n", "Kaip turbūt jau supratote, pageidautina turėti didesnį teigiamų tikrųjų ir neigiamų tikrųjų skaičių bei mažesnį klaidingų teigiamų ir klaidingų neigiamų skaičių, nes tai rodo, kad modelis veikia geriau.\n", "\n", "Painiavos matrica yra naudinga, nes ji leidžia apskaičiuoti kitus rodiklius, kurie padeda geriau įvertinti klasifikavimo modelio veikimą. Aptarkime keletą jų:\n", "\n", "🎓 Tikslumas (Precision): `TP/(TP + FP)` apibrėžiamas kaip teigiamų prognozių dalis, kurios iš tikrųjų yra teigiamos. Taip pat vadinamas [teigiamu prognoziniu rodikliu](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n", "\n", "🎓 Atsiminimas (Recall): `TP/(TP + FN)` apibrėžiamas kaip teigiamų rezultatų dalis iš visų pavyzdžių, kurie iš tikrųjų yra teigiami. Taip pat žinomas kaip `jautrumas`.\n", "\n", "🎓 Specifiškumas (Specificity): `TN/(TN + FP)` apibrėžiamas kaip neigiamų rezultatų dalis iš visų pavyzdžių, kurie iš tikrųjų yra neigiami.\n", "\n", "🎓 Tikslumas (Accuracy): `TP + TN/(TP + TN + FP + FN)` procentas teisingai prognozuotų etikečių pavyzdžiui.\n", "\n", "🎓 F matas (F Measure): Tikslumo ir atsiminimo svertinis vidurkis, kur geriausias yra 1, o blogiausias – 0.\n", "\n", "Apskaičiuokime šiuos rodiklius!\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": [ "## Vizualizuokime šio modelio ROC kreivę\n", "\n", "Padarykime dar vieną vizualizaciją, kad pamatytume vadinamąją [`ROC kreivę`](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 kreivės dažnai naudojamos norint įvertinti klasifikatoriaus rezultatą pagal tikrus ir klaidingus teigiamus rezultatus. ROC kreivėse paprastai Y ašyje vaizduojamas `True Positive Rate`/Jautrumas, o X ašyje – `False Positive Rate`/1-Specifiškumas. Taigi, kreivės statumas ir atstumas tarp vidurio linijos bei kreivės yra svarbūs: norite, kad kreivė greitai kiltų aukštyn ir virš linijos. Mūsų atveju pradžioje yra klaidingų teigiamų rezultatų, o vėliau linija tinkamai kyla aukštyn ir virš linijos.\n", "\n", "Galiausiai, pasinaudokime `yardstick::roc_auc()`, kad apskaičiuotume tikrąją plotą po kreive (Area Under the Curve). Vienas iš AUC interpretavimo būdų yra tikimybė, kad modelis atsitiktinį teigiamą pavyzdį įvertins aukščiau nei atsitiktinį neigiamą pavyzdį.\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": [ "Rezultatas yra apie `0.975`. Kadangi AUC svyruoja nuo 0 iki 1, norite gauti aukštą rezultatą, nes modelis, kuris 100% tiksliai prognozuoja, turės AUC lygią 1; šiuo atveju modelis yra *gana geras*.\n", "\n", "Ateities pamokose apie klasifikacijas sužinosite, kaip pagerinti savo modelio rezultatus (pvz., sprendžiant nesubalansuotų duomenų problemą šiuo atveju).\n", "\n", "## 🚀Iššūkis\n", "\n", "Logistinė regresija turi daug daugiau aspektų, kuriuos galima nagrinėti! Tačiau geriausias būdas mokytis yra eksperimentuoti. Suraskite duomenų rinkinį, kuris tiktų tokio tipo analizei, ir sukurkite modelį su juo. Ką sužinote? patarimas: išbandykite [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) ieškodami įdomių duomenų rinkinių.\n", "\n", "## Apžvalga ir savarankiškas mokymasis\n", "\n", "Perskaitykite pirmuosius kelis puslapius [šio Stanfordo straipsnio](https://web.stanford.edu/~jurafsky/slp3/5.pdf) apie praktinius logistikos regresijos panaudojimo būdus. Pagalvokite apie užduotis, kurios geriau tinka vienam ar kitam regresijos tipui, kuriuos iki šiol nagrinėjome. Kas veiktų geriausiai?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Atsakomybės apribojimas**: \nŠis dokumentas buvo išverstas naudojant AI vertimo paslaugą [Co-op Translator](https://github.com/Azure/co-op-translator). Nors siekiame tikslumo, prašome atkreipti dėmesį, kad automatiniai vertimai gali turėti klaidų ar netikslumų. Originalus dokumentas jo gimtąja kalba turėtų būti laikomas autoritetingu šaltiniu. Kritinei informacijai rekomenduojama naudoti profesionalų žmogaus vertimą. Mes neprisiimame atsakomybės už nesusipratimus ar klaidingus interpretavimus, atsiradusius dėl šio vertimo naudojimo.\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-03T19:32:43+00:00", "source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb", "language_code": "lt" } }, "nbformat": 4, "nbformat_minor": 1 }