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.
ML-For-Beginners/translations/bg/2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb

685 lines
43 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Създаване на модел за логистична регресия - Урок 4\n",
"\n",
"![Инфографика за логистична срещу линейна регресия](../../../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)\n",
"\n",
"#### **[Тест преди лекцията](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n",
"\n",
"#### Въведение\n",
"\n",
"В този последен урок за регресия, една от основните *класически* техники в машинното обучение, ще разгледаме логистичната регресия. Тази техника се използва за откриване на модели, които предсказват бинарни категории. Това бонбон шоколад ли е или не? Това заболяване заразно ли е или не? Този клиент ще избере този продукт или не?\n",
"\n",
"В този урок ще научите:\n",
"\n",
"- Техники за логистична регресия\n",
"\n",
"✅ Задълбочете разбирането си за работа с този тип регресия в този [учебен модул](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n",
"\n",
"## Предпоставки\n",
"\n",
"След като работихме с данните за тиквите, вече сме достатъчно запознати с тях, за да осъзнаем, че има една бинарна категория, с която можем да работим: `Color`.\n",
"\n",
"Нека създадем модел за логистична регресия, за да предскажем, въз основа на някои променливи, *какъв цвят вероятно ще има дадена тиква* (оранжева 🎃 или бяла 👻).\n",
"\n",
"> Защо говорим за бинарна класификация в урок, посветен на регресия? Само за езиково удобство, тъй като логистичната регресия е [всъщност метод за класификация](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), макар и базиран на линейни принципи. Научете за други начини за класифициране на данни в следващата група уроци.\n",
"\n",
"За този урок ще са ни необходими следните пакети:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) е [колекция от R пакети](https://www.tidyverse.org/packages), създадена да направи науката за данни по-бърза, лесна и забавна!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) е рамка, представляваща [колекция от пакети](https://www.tidymodels.org/packages/) за моделиране и машинно обучение.\n",
"\n",
"- `janitor`: [janitor пакетът](https://github.com/sfirke/janitor) предоставя прости инструменти за изследване и почистване на \"мръсни\" данни.\n",
"\n",
"- `ggbeeswarm`: [ggbeeswarm пакетът](https://github.com/eclarke/ggbeeswarm) предлага методи за създаване на диаграми тип \"пчелно рояк\" с помощта на ggplot2.\n",
"\n",
"Можете да ги инсталирате със следната команда:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n",
"\n",
"Алтернативно, скриптът по-долу проверява дали имате необходимите пакети за завършване на този модул и ги инсталира, ако липсват.\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": [
"## **Определяне на въпроса**\n",
"\n",
"За нашите цели ще го изразим като бинарен: 'Бял' или 'Не бял'. В нашия набор от данни има и категория 'райе', но тя съдържа малко примери, затова няма да я използваме. Тя така или иначе изчезва, когато премахнем стойностите null от набора от данни.\n",
"\n",
"> 🎃 Забавен факт: понякога наричаме белите тикви 'призрачни' тикви. Те не са много лесни за издълбаване, затова не са толкова популярни, колкото оранжевите, но изглеждат страхотно! Така че можем да преформулираме въпроса си като: 'Призрачна' или 'Не призрачна'. 👻\n",
"\n",
"## **За логистичната регресия**\n",
"\n",
"Логистичната регресия се различава от линейната регресия, за която научихте преди, по няколко важни начина.\n",
"\n",
"#### **Бинарна класификация**\n",
"\n",
"Логистичната регресия не предлага същите функции като линейната регресия. Първата предлага прогноза за `бинарна категория` (\"оранжева или не оранжева\"), докато втората е способна да прогнозира `непрекъснати стойности`, например, въз основа на произхода на тиквата и времето на прибиране на реколтата, *колко ще се повиши цената ѝ*.\n",
"\n",
"![Инфографика от Dasani Madipalli](../../../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)\n",
"\n",
"### Други класификации\n",
"\n",
"Съществуват и други видове логистична регресия, включително мултиномна и ординална:\n",
"\n",
"- **Мултиномна**, която включва повече от една категория - \"Оранжева, Бяла и Райе\".\n",
"\n",
"- **Ординална**, която включва подредени категории, полезна ако искаме да подредим резултатите си логично, като например тикви, които са подредени по краен брой размери (мини, малък, среден, голям, XL, XXL).\n",
"\n",
"![Мултиномна срещу ординална регресия](../../../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)\n",
"\n",
"#### **Променливите НЕ трябва да са корелирани**\n",
"\n",
"Помните ли как линейната регресия работеше по-добре с повече корелирани променливи? Логистичната регресия е обратното - променливите не трябва да са свързани. Това е подходящо за тези данни, които имат сравнително слаби корелации.\n",
"\n",
"#### **Нуждаете се от много чисти данни**\n",
"\n",
"Логистичната регресия ще даде по-точни резултати, ако използвате повече данни; нашият малък набор от данни не е оптимален за тази задача, така че имайте това предвид.\n",
"\n",
"✅ Помислете за типовете данни, които биха били подходящи за логистична регресия.\n",
"\n",
"## Упражнение - почистете данните\n",
"\n",
"Първо, почистете данните малко, като премахнете стойностите null и изберете само някои от колоните:\n",
"\n",
"1. Добавете следния код:\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": [
"Винаги можете да хвърлите поглед към новия си dataframe, като използвате функцията [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html), както е показано по-долу:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"pumpkins_select %>% \n",
" glimpse()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Нека потвърдим, че всъщност ще решаваме задача за бинарна класификация:\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": [
"### Визуализация - категориален график\n",
"Дотук вече сте заредили данните за тиквите отново и сте ги почистили, за да запазите набор от данни, съдържащ няколко променливи, включително Цвят. Нека визуализираме таблицата в тетрадката, използвайки библиотеката ggplot.\n",
"\n",
"Библиотеката ggplot предлага някои удобни начини за визуализация на вашите данни. Например, можете да сравните разпределенията на данните за всяка разновидност и цвят в категориален график.\n",
"\n",
"1. Създайте такъв график, като използвате функцията geombar, използвайки нашите данни за тиквите, и задайте цветово картографиране за всяка категория тикви (оранжеви или бели):\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": [
"Като наблюдавате данните, можете да видите как информацията за Цвят се свързва с Разновидност.\n",
"\n",
"✅ Като се има предвид този категориален график, какви интересни изследвания можете да си представите?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Предварителна обработка на данни: кодиране на признаци\n",
"\n",
"Нашият набор от данни за тикви съдържа текстови стойности за всички свои колони. Работата с категорийни данни е интуитивна за хората, но не и за машините. Алгоритмите за машинно обучение работят добре с числа. Затова кодиране е много важна стъпка в етапа на предварителна обработка на данни, тъй като ни позволява да преобразуваме категорийни данни в числови, без да губим информация. Добро кодиране води до изграждане на добър модел.\n",
"\n",
"За кодиране на признаци има два основни типа кодери:\n",
"\n",
"1. Ординален кодер: подходящ е за ординални променливи, които са категорийни променливи, при които данните следват логическа подредба, като колоната `item_size` в нашия набор от данни. Той създава съответствие, при което всяка категория се представя с число, което е редът на категорията в колоната.\n",
"\n",
"2. Категориен кодер: подходящ е за номинални променливи, които са категорийни променливи, при които данните не следват логическа подредба, като всички признаци, различни от `item_size` в нашия набор от данни. Това е кодиране тип \"едно-горещо\", което означава, че всяка категория се представя с двоична колона: кодираната променлива е равна на 1, ако тиквата принадлежи към съответния сорт, и 0 в противен случай.\n",
"\n",
"Tidymodels предоставя още един удобен пакет: [recipes](https://recipes.tidymodels.org/) - пакет за предварителна обработка на данни. Ще дефинираме `recipe`, който уточнява, че всички колони с предиктори трябва да бъдат кодирани в набор от цели числа, ще го `prep`, за да изчислим необходимите количества и статистики за всяка операция, и накрая ще го `bake`, за да приложим изчисленията към нови данни.\n",
"\n",
"> Обикновено recipes се използва като предварителен процесор за моделиране, където се определя какви стъпки трябва да бъдат приложени към набор от данни, за да бъде готов за моделиране. В този случай е **силно препоръчително** да използвате `workflow()` вместо ръчното изчисляване на recipe чрез prep и bake. Ще разгледаме всичко това след малко.\n",
">\n",
"> Засега обаче използваме recipes + prep + bake, за да уточним какви стъпки трябва да бъдат приложени към набор от данни, за да бъде готов за анализ на данни, и след това извличаме предварително обработените данни с приложените стъпки.\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": [
"✅ Какви са предимствата от използването на ординален енкодер за колоната Item Size?\n",
"\n",
"### Анализ на връзките между променливите\n",
"\n",
"След като сме обработили данните си, можем да анализираме връзките между характеристиките и етикета, за да добием представа колко добре моделът ще може да предскаже етикета въз основа на характеристиките. Най-добрият начин за извършване на този вид анализ е чрез визуализация на данните. \n",
"Ще използваме отново функцията ggplot geom_boxplot_, за да визуализираме връзките между Item Size, Variety и Color в категориален график. За по-добра визуализация на данните ще използваме кодираната колона Item Size и некодираната колона Variety.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "r"
}
},
"outputs": [],
"source": [
"# Define the color palette\n",
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
"\n",
"# We need the encoded Item Size column to use it as the x-axis values in the plot\n",
"pumpkins_select_plot<-pumpkins_select\n",
"pumpkins_select_plot$item_size <- baked_pumpkins$item_size\n",
"\n",
"# Create the grouped box plot\n",
"ggplot(pumpkins_select_plot, aes(x = `item_size`, y = color, fill = color)) +\n",
" geom_boxplot() +\n",
" facet_grid(variety ~ ., scales = \"free_x\") +\n",
" scale_fill_manual(values = palette) +\n",
" labs(x = \"Item Size\", y = \"\") +\n",
" theme_minimal() +\n",
" theme(strip.text = element_text(size = 12)) +\n",
" theme(axis.text.x = element_text(size = 10)) +\n",
" theme(axis.title.x = element_text(size = 12)) +\n",
" theme(axis.title.y = element_blank()) +\n",
" theme(legend.position = \"bottom\") +\n",
" guides(fill = guide_legend(title = \"Color\")) +\n",
" theme(panel.spacing = unit(0.5, \"lines\"))+\n",
" theme(strip.text.y = element_text(size = 4, hjust = 0)) \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Използване на swarm plot\n",
"\n",
"Тъй като Color е бинарна категория (Бяло или Не), тя изисква '[специализиран подход](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) за визуализация'.\n",
"\n",
"Опитайте `swarm plot`, за да покажете разпределението на цвета спрямо item_size.\n",
"\n",
"Ще използваме [пакета ggbeeswarm](https://github.com/eclarke/ggbeeswarm), който предоставя методи за създаване на графики в стил beeswarm с ggplot2. Beeswarm графиките са начин за визуализиране на точки, които обикновено биха се припокривали, така че да се разположат една до друга вместо това.\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": [
"Сега, когато имаме представа за връзката между бинарните категории на цвета и по-голямата група размери, нека разгледаме логистичната регресия, за да определим вероятния цвят на дадена тиква.\n",
"\n",
"## Създайте своя модел\n",
"\n",
"Изберете променливите, които искате да използвате във вашия класификационен модел, и разделете данните на тренировъчни и тестови набори. [rsample](https://rsample.tidymodels.org/), пакет в Tidymodels, предоставя инфраструктура за ефективно разделяне и повторно извадково тестване на данни:\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": [
"🙌 Сега сме готови да обучим модел, като свържем тренировъчните характеристики с тренировъчния етикет (цвят).\n",
"\n",
"Ще започнем, като създадем рецепта, която определя стъпките за предварителна обработка, които трябва да се извършат върху нашите данни, за да ги подготвим за моделиране, например: кодиране на категориални променливи в набор от цели числа. Точно както `baked_pumpkins`, създаваме `pumpkins_recipe`, но не използваме `prep` и `bake`, тъй като това ще бъде включено в работен процес, който ще видите само след няколко стъпки.\n",
"\n",
"Има доста начини за задаване на модел за логистична регресия в Tidymodels. Вижте `?logistic_reg()`. Засега ще зададем модел за логистична регресия чрез стандартния двигател `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": [
"Сега, когато имаме рецепта и спецификация на модела, трябва да намерим начин да ги обединим в един обект, който първо ще обработи данните (подготовка + изпичане зад кулисите), ще обучи модела върху предварително обработените данни и също така ще позволи потенциални дейности по последваща обработка.\n",
"\n",
"В Tidymodels този удобен обект се нарича [`workflow`](https://workflows.tidymodels.org/) и удобно съхранява вашите компоненти за моделиране.\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": [
"След като работният процес бъде *уточнен*, моделът може да бъде `обучен` с помощта на функцията [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html). Работният процес ще оцени рецептата и ще обработи данните преди обучението, така че няма да се налага да го правим ръчно с prep и 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": [
"Моделът отпечатва коефициентите, научени по време на обучението.\n",
"\n",
"Сега, след като сме обучили модела с тренировъчните данни, можем да правим прогнози върху тестовите данни, използвайки [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Нека започнем, като използваме модела, за да предвидим етикетите за нашия тестов набор и вероятностите за всеки етикет. Когато вероятността е повече от 0.5, предсказаният клас е `WHITE`, в противен случай е `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": [
"Много добре! Това предоставя допълнителна информация за начина, по който работи логистичната регресия.\n",
"\n",
"### По-добро разбиране чрез матрица на объркване\n",
"\n",
"Сравняването на всяка прогноза с нейното съответстващо \"истинско\" реално значение не е много ефективен начин за определяне на точността на модела. За щастие, Tidymodels има още няколко трика в ръкава си: [`yardstick`](https://yardstick.tidymodels.org/) - пакет, използван за измерване на ефективността на моделите чрез метрики за производителност.\n",
"\n",
"Една метрика за производителност, свързана с проблемите на класификацията, е [`матрицата на объркване`](https://wikipedia.org/wiki/Confusion_matrix). Матрицата на объркване описва колко добре се представя моделът за класификация. Тя показва колко примери от всяка категория са правилно класифицирани от модела. В нашия случай, тя ще покаже колко оранжеви тикви са класифицирани като оранжеви и колко бели тикви са класифицирани като бели; матрицата на объркване също показва колко са класифицирани в **грешните** категории.\n",
"\n",
"Функцията [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) от yardstick изчислява тази кръстосана таблица на наблюдаваните и предсказаните категории.\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": [
"Нека интерпретираме матрицата на объркване. Нашият модел трябва да класифицира тиквите в две бинарни категории: категория `бяла` и категория `не-бяла`.\n",
"\n",
"- Ако вашият модел предскаже тиква като бяла и тя наистина принадлежи към категорията 'бяла', това наричаме `истински положителен` (true positive), показано с числото в горния ляв ъгъл.\n",
"\n",
"- Ако вашият модел предскаже тиква като не-бяла и тя наистина принадлежи към категорията 'бяла', това наричаме `фалшиво отрицателен` (false negative), показано с числото в долния ляв ъгъл.\n",
"\n",
"- Ако вашият модел предскаже тиква като бяла и тя наистина принадлежи към категорията 'не-бяла', това наричаме `фалшиво положителен` (false positive), показано с числото в горния десен ъгъл.\n",
"\n",
"- Ако вашият модел предскаже тиква като не-бяла и тя наистина принадлежи към категорията 'не-бяла', това наричаме `истински отрицателен` (true negative), показано с числото в долния десен ъгъл.\n",
"\n",
"| Истина |\n",
"|:-----:|\n",
"\n",
"| | | |\n",
"|---------------|--------|-------|\n",
"| **Предсказано** | БЯЛА | ОРАНЖЕВА |\n",
"| БЯЛА | TP | FP |\n",
"| ОРАНЖЕВА | FN | TN |\n",
"\n",
"Както може би се досещате, е за предпочитане да имаме по-голям брой истински положителни и истински отрицателни, както и по-малък брой фалшиво положителни и фалшиво отрицателни, което означава, че моделът се представя по-добре.\n",
"\n",
"Матрицата на объркване е полезна, защото води до други метрики, които могат да ни помогнат по-добре да оценим представянето на класификационния модел. Нека разгледаме някои от тях:\n",
"\n",
"🎓 Прецизност (Precision): `TP/(TP + FP)` дефинирана като пропорцията на предсказаните положителни, които наистина са положителни. Нарича се също [положителна предсказателна стойност](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n",
"\n",
"🎓 Чувствителност (Recall): `TP/(TP + FN)` дефинирана като пропорцията на положителните резултати спрямо броя на пробите, които наистина са положителни. Известна също като `чувствителност`.\n",
"\n",
"🎓 Специфичност (Specificity): `TN/(TN + FP)` дефинирана като пропорцията на отрицателните резултати спрямо броя на пробите, които наистина са отрицателни.\n",
"\n",
"🎓 Точност (Accuracy): `TP + TN/(TP + TN + FP + FN)` Процентът на етикетите, предсказани правилно за дадена проба.\n",
"\n",
"🎓 F Мярка (F Measure): Претеглена средна стойност на прецизността и чувствителността, като най-добрата стойност е 1, а най-лошата е 0.\n",
"\n",
"Нека изчислим тези метрики!\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": [
"## Визуализиране на ROC кривата на този модел\n",
"\n",
"Нека направим още една визуализация, за да видим така наречената [`ROC крива`](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 кривите често се използват, за да се получи представа за резултатите на класификатор в контекста на истински спрямо фалшиви положителни стойности. ROC кривите обикновено показват `True Positive Rate`/Чувствителност на оста Y и `False Positive Rate`/1-Специфичност на оста X. Следователно, стръмността на кривата и пространството между средната линия и кривата са от значение: желаете крива, която бързо се изкачва нагоре и преминава над линията. В нашия случай има фалшиви положителни стойности в началото, след което линията се изкачва нагоре и преминава правилно.\n",
"\n",
"Накрая, нека използваме `yardstick::roc_auc()`, за да изчислим действителната площ под кривата (Area Under the Curve). Един от начините за интерпретиране на AUC е като вероятността моделът да класира случайно избран положителен пример по-високо от случайно избран отрицателен пример.\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": [
"Резултатът е около `0.975`. Като се има предвид, че AUC варира от 0 до 1, искате висок резултат, тъй като модел, който е 100% точен в своите прогнози, ще има AUC от 1; в този случай моделът е *доста добър*.\n",
"\n",
"В бъдещи уроци за класификации ще научите как да подобрите резултатите на вашия модел (например справяне с небалансирани данни в този случай).\n",
"\n",
"## 🚀Предизвикателство\n",
"\n",
"Има много повече за разглеждане относно логистичната регресия! Но най-добрият начин да научите е чрез експериментиране. Намерете набор от данни, който е подходящ за този тип анализ, и изградете модел с него. Какво научавате? съвет: опитайте [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) за интересни набори от данни.\n",
"\n",
"## Преглед и самостоятелно обучение\n",
"\n",
"Прочетете първите няколко страници от [тази статия от Станфорд](https://web.stanford.edu/~jurafsky/slp3/5.pdf) за някои практически приложения на логистичната регресия. Помислете за задачи, които са по-подходящи за единия или другия тип регресионни задачи, които сме изучавали до този момент. Какво би работило най-добре?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.\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:46:31+00:00",
"source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb",
"language_code": "bg"
}
},
"nbformat": 4,
"nbformat_minor": 1
}