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/sr/2-Regression/3-Linear/solution/R/lesson_3-R.ipynb

1084 lines
55 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.

{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_3-R.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "5015d65d61ba75a223bfc56c273aa174",
"translation_date": "2025-09-06T13:18:01+00:00",
"source_file": "2-Regression/3-Linear/solution/R/lesson_3-R.ipynb",
"language_code": "sr"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "EgQw8osnsUV-"
}
},
{
"cell_type": "markdown",
"source": [
"## Линеарна и полиномијална регресија за одређивање цене бундева - Лекција 3\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Инфографика: Дасани Мадипали</figcaption>\n",
"\n",
"\n",
"#### Увод\n",
"\n",
"До сада сте истраживали шта је регресија користећи пример података из скупа података о ценама бундева који ћемо користити током ове лекције. Такође сте је визуализовали помоћу `ggplot2`. 💪\n",
"\n",
"Сада сте спремни да дубље уђете у регресију за машинско учење. У овој лекцији ћете научити више о две врсте регресије: *основна линеарна регресија* и *полиномијална регресија*, као и нешто од математике која стоји иза ових техника.\n",
"\n",
"> Кроз овај курикулум претпостављамо минимално знање математике и настојимо да га учинимо доступним студентима из других области, па обратите пажњу на напомене, 🧮 дијаграме и друге алате за учење који ће вам помоћи у разумевању.\n",
"\n",
"#### Припрема\n",
"\n",
"Подсећамо, учитавате ове податке како бисте постављали питања о њима.\n",
"\n",
"- Када је најбоље време за куповину бундева?\n",
"\n",
"- Коју цену могу да очекујем за кутију минијатурних бундева?\n",
"\n",
"- Да ли да их купим у корпама од пола бушела или у кутијама од 1 1/9 бушела? Хајде да наставимо са истраживањем ових података.\n",
"\n",
"У претходној лекцији, креирали сте `tibble` (модерно преобликовање оквира података) и попунили га делом оригиналног скупа података, стандардизујући цене по бушелу. Међутим, на тај начин сте успели да сакупите само око 400 података и то само за јесење месеце. Можда можемо добити мало више детаља о природи података ако их боље очистимо? Видећемо... 🕵️‍♀️\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",
"- `corrplot`: [corrplot пакет](https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html) пружа визуелни алат за истраживање корелационе матрице који подржава аутоматско ређање променљивих како би се открили скривени обрасци међу променљивима.\n",
"\n",
"Можете их инсталирати на следећи начин:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"corrplot\"))`\n",
"\n",
"Скрипта испод проверава да ли имате потребне пакете за завршетак овог модула и инсталира их за вас у случају да недостају.\n"
],
"metadata": {
"id": "WqQPS1OAsg3H"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if (!require(\"pacman\")) install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load(tidyverse, tidymodels, janitor, corrplot)"
],
"outputs": [],
"metadata": {
"id": "tA4C2WN3skCf",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "c06cd805-5534-4edc-f72b-d0d1dab96ac0"
}
},
{
"cell_type": "markdown",
"source": [
"Учитаћемо ове сјајне пакете и учинити их доступним у нашој тренутној R сесији. (Ово је само за илустрацију, `pacman::p_load()` је то већ урадио за вас)\n",
"\n",
"## 1. Линија линеарне регресије\n",
"\n",
"Као што сте научили у Лекцији 1, циљ вежбе линеарне регресије је да се нацрта *линија* *најбољег* *прилагођавања* како би се:\n",
"\n",
"- **Приказали односи између променљивих**. Приказао однос између променљивих.\n",
"\n",
"- **Направиле предикције**. Направиле тачне предикције о томе где би нова тачка података могла пасти у односу на ту линију.\n",
"\n",
"Да бисмо нацртали ову врсту линије, користимо статистичку технику која се зове **Регресија најмањих квадрата**. Термин `најмањи квадрати` значи да су све тачке података које окружују регресиону линију подигнуте на квадрат и затим сабране. Идеално, та коначна сума је што је могуће мања, јер желимо низак број грешака, односно `најмање квадрате`. Као таква, линија најбољег прилагођавања је линија која нам даје најнижу вредност за збир квадрата грешака - отуда назив *регресија најмањих квадрата*.\n",
"\n",
"Ово радимо јер желимо да моделирамо линију која има најмању кумулативну удаљеност од свих наших тачака података. Такође подижемо термине на квадрат пре него што их саберемо, јер нас занима њихова величина, а не правац.\n",
"\n",
"> **🧮 Покажите ми математику**\n",
">\n",
"> Ова линија, названа *линија најбољег прилагођавања*, може се изразити [једначином](https://en.wikipedia.org/wiki/Simple_linear_regression):\n",
">\n",
"> Y = a + bX\n",
">\n",
"> `X` је '`објашњавајућа променљива` или `предиктор`'. `Y` је '`зависна променљива` или `исход`'. Нагиб линије је `b`, а `a` је пресек са Y-осом, што се односи на вредност `Y` када је `X = 0`.\n",
">\n",
"\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/slope.png \"нагиб = $y/x$\")\n",
" Инфографика: Џен Лупер\n",
">\n",
"> Прво, израчунајте нагиб `b`.\n",
">\n",
"> Другим речима, и позивајући се на оригинално питање о подацима о бундевама: \"предвидите цену бундеве по бушелу по месецу\", `X` би се односио на цену, а `Y` на месец продаје.\n",
">\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/calculation.png)\n",
" Инфографика: Џен Лупер\n",
"> \n",
"> Израчунајте вредност Y. Ако плаћате око 4 долара, мора да је април!\n",
">\n",
"> Математика која израчунава линију мора показати нагиб линије, који такође зависи од пресека, односно где се `Y` налази када је `X = 0`.\n",
">\n",
"> Можете видети метод израчунавања ових вредности на веб сајту [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html). Такође посетите [овај калкулатор најмањих квадрата](https://www.mathsisfun.com/data/least-squares-calculator.html) да бисте видели како вредности бројева утичу на линију.\n",
"\n",
"Није тако страшно, зар не? 🤓\n",
"\n",
"#### Корелација\n",
"\n",
"Још један термин који треба разумети је **Коефицијент корелације** између датих X и Y променљивих. Користећи дијаграм расејања, можете брзо визуализовати овај коефицијент. Дијаграм са тачкама података распоређеним у уредну линију има високу корелацију, али дијаграм са тачкама података распршеним свуда између X и Y има ниску корелацију.\n",
"\n",
"Добар модел линеарне регресије биће онај који има висок (ближи 1 него 0) Коефицијент корелације користећи метод Регресије најмањих квадрата са линијом регресије.\n"
],
"metadata": {
"id": "cdX5FRpvsoP5"
}
},
{
"cell_type": "markdown",
"source": [
"## **2. Плес са подацима: креирање дата фрејма који ће се користити за моделирање**\n",
"\n",
"<p >\n",
" <img src=\"../../images/janitor.jpg\"\n",
" width=\"700\"/>\n",
" <figcaption>Илустрација: @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Илустрација: \\@allison_horst](../../../../../../2-Regression/3-Linear/images/janitor.jpg){width=\"700\"}-->\n"
],
"metadata": {
"id": "WdUKXk7Bs8-V"
}
},
{
"cell_type": "markdown",
"source": [
"Учитајте потребне библиотеке и скуп података. Претворите податке у оквир података који садржи подскуп података:\n",
"\n",
"- Узмите само тикве чија је цена одређена по бушелу\n",
"\n",
"- Претворите датум у месец\n",
"\n",
"- Израчунајте цену као просек високих и ниских цена\n",
"\n",
"- Претворите цену тако да одражава цену по количини бушела\n",
"\n",
"> Ове кораке смо обрадили у [претходној лекцији](https://github.com/microsoft/ML-For-Beginners/blob/main/2-Regression/2-Data/solution/lesson_2-R.ipynb).\n"
],
"metadata": {
"id": "fMCtu2G2s-p8"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the core Tidyverse packages\n",
"library(tidyverse)\n",
"library(lubridate)\n",
"\n",
"# Import the pumpkins data\n",
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\")\n",
"\n",
"\n",
"# Get a glimpse and dimensions of the data\n",
"glimpse(pumpkins)\n",
"\n",
"\n",
"# Print the first 50 rows of the data set\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "ryMVZEEPtERn"
}
},
{
"cell_type": "markdown",
"source": [
"У духу чисте авантуре, хајде да истражимо [`janitor package`](../../../../../../2-Regression/3-Linear/solution/R/github.com/sfirke/janitor) који пружа једноставне функције за испитивање и чишћење неуређених података. На пример, хајде да погледамо називе колона за наше податке:\n"
],
"metadata": {
"id": "xcNxM70EtJjb"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Return column names\n",
"pumpkins %>% \n",
" names()"
],
"outputs": [],
"metadata": {
"id": "5XtpaIigtPfW"
}
},
{
"cell_type": "markdown",
"source": [
"🤔 Можемо боље. Хајде да направимо ова имена колона `friendR` тако што ћемо их претворити у [snake_case](https://en.wikipedia.org/wiki/Snake_case) конвенцију користећи `janitor::clean_names`. Да бисте сазнали више о овој функцији: `?clean_names`\n"
],
"metadata": {
"id": "IbIqrMINtSHe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Clean names to the snake_case convention\n",
"pumpkins <- pumpkins %>% \n",
" clean_names(case = \"snake\")\n",
"\n",
"# Return column names\n",
"pumpkins %>% \n",
" names()"
],
"outputs": [],
"metadata": {
"id": "a2uYvclYtWvX"
}
},
{
"cell_type": "markdown",
"source": [
"Толико tidyR 🧹! Сада, плес са подацима користећи `dplyr`, као у претходној лекцији! 💃\n"
],
"metadata": {
"id": "HfhnuzDDtaDd"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select desired columns\n",
"pumpkins <- pumpkins %>% \n",
" select(variety, city_name, package, low_price, high_price, date)\n",
"\n",
"\n",
"\n",
"# Extract the month from the dates to a new column\n",
"pumpkins <- pumpkins %>%\n",
" mutate(date = mdy(date),\n",
" month = month(date)) %>% \n",
" select(-date)\n",
"\n",
"\n",
"\n",
"# Create a new column for average Price\n",
"pumpkins <- pumpkins %>% \n",
" mutate(price = (low_price + high_price)/2)\n",
"\n",
"\n",
"# Retain only pumpkins with the string \"bushel\"\n",
"new_pumpkins <- pumpkins %>% \n",
" filter(str_detect(string = package, pattern = \"bushel\"))\n",
"\n",
"\n",
"# Normalize the pricing so that you show the pricing per bushel, not per 1 1/9 or 1/2 bushel\n",
"new_pumpkins <- new_pumpkins %>% \n",
" mutate(price = case_when(\n",
" str_detect(package, \"1 1/9\") ~ price/(1.1),\n",
" str_detect(package, \"1/2\") ~ price*2,\n",
" TRUE ~ price))\n",
"\n",
"# Relocate column positions\n",
"new_pumpkins <- new_pumpkins %>% \n",
" relocate(month, .before = variety)\n",
"\n",
"\n",
"# Display the first 5 rows\n",
"new_pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "X0wU3gQvtd9f"
}
},
{
"cell_type": "markdown",
"source": [
"Одличан посао!👌 Сада имате чист, уредан скуп података на којем можете изградити свој нови регресиони модел!\n",
"\n",
"Шта кажете на расејани графикон?\n"
],
"metadata": {
"id": "UpaIwaxqth82"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Set theme\n",
"theme_set(theme_light())\n",
"\n",
"# Make a scatter plot of month and price\n",
"new_pumpkins %>% \n",
" ggplot(mapping = aes(x = month, y = price)) +\n",
" geom_point(size = 1.6)\n"
],
"outputs": [],
"metadata": {
"id": "DXgU-j37tl5K"
}
},
{
"cell_type": "markdown",
"source": [
"Дијаграм распршивања нас подсећа да имамо податке о месецима само од августа до децембра. Вероватно нам је потребно више података како бисмо могли да извучемо закључке на линеаран начин.\n",
"\n",
"Хајде да поново погледамо наше податке за моделирање:\n"
],
"metadata": {
"id": "Ve64wVbwtobI"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Display first 5 rows\n",
"new_pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "HFQX2ng1tuSJ"
}
},
{
"cell_type": "markdown",
"source": [
"Шта ако бисмо желели да предвидимо `price` тикве на основу колона `city` или `package`, које су типа карактер? Или још једноставније, како бисмо могли да пронађемо корелацију (која захтева да оба уноса буду нумеричка) између, рецимо, `package` и `price`? 🤷🤷\n",
"\n",
"Модели машинског учења најбоље функционишу са нумеричким карактеристикама уместо текстуалних вредности, тако да је генерално потребно претворити категоријалне карактеристике у нумеричке репрезентације.\n",
"\n",
"То значи да морамо пронаћи начин да преобликујемо наше предикторе како бисмо их учинили погоднијим за ефикасно коришћење у моделу, процес познат као `feature engineering`.\n"
],
"metadata": {
"id": "7hsHoxsStyjJ"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Предобрада података за моделирање са рецептурама 👩‍🍳👨‍🍳\n",
"\n",
"Активности које преобликују вредности предиктора како би их учиниле лакшим за ефикасно коришћење модела називају се `инжењеринг карактеристика`.\n",
"\n",
"Различити модели имају различите захтеве за предобраду. На пример, метода најмањих квадрата захтева `кодирање категоријалних променљивих` као што су месец, сорта и назив града. Ово једноставно подразумева `превод` колоне са `категоријалним вредностима` у једну или више `нумеричких колона` које замењују оригиналну.\n",
"\n",
"На пример, претпоставимо да ваши подаци укључују следећу категоријалну карактеристику:\n",
"\n",
"| град |\n",
"|:-------:|\n",
"| Денвер |\n",
"| Најроби |\n",
"| Токио |\n",
"\n",
"Можете применити *ордирално кодирање* да замените јединствену целобројну вредност за сваку категорију, овако:\n",
"\n",
"| град |\n",
"|:----:|\n",
"| 0 |\n",
"| 1 |\n",
"| 2 |\n",
"\n",
"И то је оно што ћемо урадити са нашим подацима!\n",
"\n",
"У овом одељку, истражићемо још један невероватан пакет из Tidymodels-а: [recipes](https://tidymodels.github.io/recipes/) - који је осмишљен да вам помогне да предобрадите своје податке **пре** тренинга модела. У својој суштини, рецепт је објекат који дефинише које кораке треба применити на скуп података како би био спреман за моделирање.\n",
"\n",
"Сада, хајде да направимо рецепт који припрема наше податке за моделирање заменом јединственог целобројног броја за све опсервације у колонама предиктора:\n"
],
"metadata": {
"id": "AD5kQbcvt3Xl"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Specify a recipe\n",
"pumpkins_recipe <- recipe(price ~ ., data = new_pumpkins) %>% \n",
" step_integer(all_predictors(), zero_based = TRUE)\n",
"\n",
"\n",
"# Print out the recipe\n",
"pumpkins_recipe"
],
"outputs": [],
"metadata": {
"id": "BNaFKXfRt9TU"
}
},
{
"cell_type": "markdown",
"source": [
"Сјајно! 👏 Управо смо направили наш први рецепт који одређује исход (цену) и његове одговарајуће предикторе, а такође и да све колоне предиктора треба да буду кодиране у скуп целих бројева 🙌! Хајде да брзо разложимо шта смо урадили:\n",
"\n",
"- Позив функције `recipe()` са формулом говори рецепту *улоге* променљивих користећи податке `new_pumpkins` као референцу. На пример, колона `price` је добила улогу `outcome`, док су остале колоне добиле улогу `predictor`.\n",
"\n",
"- `step_integer(all_predictors(), zero_based = TRUE)` одређује да сви предиктори треба да буду претворени у скуп целих бројева, при чему нумерација почиње од 0.\n",
"\n",
"Сигурни смо да вам можда падају на памет мисли попут: \"Ово је тако кул!! Али шта ако треба да проверим да ли рецепти раде тачно оно што очекујем? 🤔\"\n",
"\n",
"То је сјајна мисао! Видите, када једном дефинишете рецепт, можете проценити параметре који су потребни за стварну претобраду података, а затим извући обрађене податке. Обично ово није потребно када користите Tidymodels (ускоро ћемо видети уобичајену конвенцију -\\> `workflows`), али може бити корисно када желите да урадите неку врсту провере како бисте потврдили да рецепти раде оно што очекујете.\n",
"\n",
"За то ће вам бити потребна још два глагола: `prep()` и `bake()`, а као и увек, наши мали пријатељи из R-а од стране [`Allison Horst`](https://github.com/allisonhorst/stats-illustrations) помоћи ће вам да ово боље разумете!\n",
"\n",
"<p >\n",
" <img src=\"../../images/recipes.png\"\n",
" width=\"550\"/>\n",
" <figcaption>Илустрација од @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Илустрација од \\@allison_horst](../../../../../../2-Regression/3-Linear/images/recipes.png){width=\"550\"}-->\n"
],
"metadata": {
"id": "KEiO0v7kuC9O"
}
},
{
"cell_type": "markdown",
"source": [
"[`prep()`](https://recipes.tidymodels.org/reference/prep.html): процењује потребне параметре из тренинг скупа који касније могу бити примењени на друге скупове података. На пример, за дату колону предиктора, који посматрач ће бити додељен као цео број 0, 1, 2 итд.\n",
"\n",
"[`bake()`](https://recipes.tidymodels.org/reference/bake.html): узима припремљен рецепт и примењује операције на било који скуп података.\n",
"\n",
"С тим речено, хајде да припремимо и применимо наше рецепте како бисмо заиста потврдили да ће, у позадини, колоне предиктора прво бити кодиране пре него што се модел прилагоди.\n"
],
"metadata": {
"id": "Q1xtzebuuTCP"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Prep the recipe\n",
"pumpkins_prep <- prep(pumpkins_recipe)\n",
"\n",
"# Bake the recipe to extract a preprocessed new_pumpkins data\n",
"baked_pumpkins <- bake(pumpkins_prep, new_data = NULL)\n",
"\n",
"# Print out the baked data set\n",
"baked_pumpkins %>% \n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "FGBbJbP_uUUn"
}
},
{
"cell_type": "markdown",
"source": [
"Ура! 🥳 Обрађени подаци `baked_pumpkins` имају све своје предикторе кодиране, што потврђује да ће кораци предобраде дефинисани као наш рецепт функционисати како је очекивано. Ово чини податке теже читљивим за вас, али много разумљивијим за Tidymodels! Одвојите мало времена да откријете која је опсервација мапирана на одговарајући целобројни вредност.\n",
"\n",
"Такође је вредно напоменути да је `baked_pumpkins` оквир података на којем можемо изводити прорачуне.\n",
"\n",
"На пример, хајде да покушамо да пронађемо добру корелацију између две тачке ваших података како бисмо потенцијално изградили добар предиктивни модел. Користићемо функцију `cor()` да то урадимо. Укуцајте `?cor()` да бисте сазнали више о функцији.\n"
],
"metadata": {
"id": "1dvP0LBUueAW"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the correlation between the city_name and the price\n",
"cor(baked_pumpkins$city_name, baked_pumpkins$price)\n",
"\n",
"# Find the correlation between the package and the price\n",
"cor(baked_pumpkins$package, baked_pumpkins$price)\n"
],
"outputs": [],
"metadata": {
"id": "3bQzXCjFuiSV"
}
},
{
"cell_type": "markdown",
"source": [
"Испоставило се да постоји само слаба корелација између Града и Цене. Међутим, постоји нешто боља корелација између Пакета и његове Цене. То има смисла, зар не? Обично, што је већа кутија са производима, то је виша цена.\n",
"\n",
"Док смо већ код тога, хајде да покушамо и да визуализујемо матрицу корелације свих колона користећи пакет `corrplot`.\n"
],
"metadata": {
"id": "BToPWbgjuoZw"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the corrplot package\n",
"library(corrplot)\n",
"\n",
"# Obtain correlation matrix\n",
"corr_mat <- cor(baked_pumpkins %>% \n",
" # Drop columns that are not really informative\n",
" select(-c(low_price, high_price)))\n",
"\n",
"# Make a correlation plot between the variables\n",
"corrplot(corr_mat, method = \"shade\", shade.col = NA, tl.col = \"black\", tl.srt = 45, addCoef.col = \"black\", cl.pos = \"n\", order = \"original\")"
],
"outputs": [],
"metadata": {
"id": "ZwAL3ksmutVR"
}
},
{
"cell_type": "markdown",
"source": [
"🤩🤩 Много боље.\n",
"\n",
"Добро питање које сада можемо поставити о овим подацима је: '`Коју цену могу очекивати за одређени пакет бундева?`' Хајде да одмах пређемо на то!\n",
"\n",
"> Напомена: Када **`bake()`** припремљени рецепт **`pumpkins_prep`** са **`new_data = NULL`**, добијате обрађене (тј. кодиране) податке за обуку. Ако имате други скуп података, на пример тест сет, и желите да видите како би рецепт обрадио те податке, једноставно бисте испекли **`pumpkins_prep`** са **`new_data = test_set`**.\n",
"\n",
"## 4. Изградња модела линеарне регресије\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Инфографика: Дасани Мадипали</figcaption>\n"
],
"metadata": {
"id": "YqXjLuWavNxW"
}
},
{
"cell_type": "markdown",
"source": [
"Сада када смо направили рецепт и заправо потврдили да ће подаци бити одговарајуће претходно обрађени, хајде сада да направимо регресиони модел како бисмо одговорили на питање: `Коју цену могу очекивати за одређени пакет бундеве?`\n",
"\n",
"#### Обучавање линеарног регресионог модела користећи тренинг сет\n",
"\n",
"Као што сте вероватно већ закључили, колона *price* је `излазна` променљива, док је колона *package* `предикторска` променљива.\n",
"\n",
"Да бисмо то урадили, прво ћемо поделити податке тако да 80% иде у тренинг сет, а 20% у тест сет, затим ћемо дефинисати рецепт који ће кодирати предикторску колону у скуп целих бројева, а потом ћемо направити спецификацију модела. Нећемо припремати и обрађивати наш рецепт јер већ знамо да ће он претходно обрадити податке како је очекивано.\n"
],
"metadata": {
"id": "Pq0bSzCevW-h"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"set.seed(2056)\n",
"# Split the data into training and test sets\n",
"pumpkins_split <- new_pumpkins %>% \n",
" initial_split(prop = 0.8)\n",
"\n",
"\n",
"# Extract training and test data\n",
"pumpkins_train <- training(pumpkins_split)\n",
"pumpkins_test <- testing(pumpkins_split)\n",
"\n",
"\n",
"\n",
"# Create a recipe for preprocessing the data\n",
"lm_pumpkins_recipe <- recipe(price ~ package, data = pumpkins_train) %>% \n",
" step_integer(all_predictors(), zero_based = TRUE)\n",
"\n",
"\n",
"\n",
"# Create a linear model specification\n",
"lm_spec <- linear_reg() %>% \n",
" set_engine(\"lm\") %>% \n",
" set_mode(\"regression\")"
],
"outputs": [],
"metadata": {
"id": "CyoEh_wuvcLv"
}
},
{
"cell_type": "markdown",
"source": [
"Одлично! Сада када имамо рецепт и спецификацију модела, потребно је да пронађемо начин да их спојимо у један објекат који ће прво обрадити податке (припрема + обрада у позадини), затим обучити модел на обрађеним подацима, а такође омогућити потенцијалне активности пост-обраде. Како ти се то чини за мир у души!🤩\n",
"\n",
"У оквиру Tidymodels-а, овај практични објекат се зове [`workflow`](https://workflows.tidymodels.org/) и згодно чува све компоненте твог модела! Ово је оно што бисмо у *Python*-у назвали *pipelines*.\n",
"\n",
"Хајде да све спакујемо у један workflow!📦\n"
],
"metadata": {
"id": "G3zF_3DqviFJ"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Hold modelling components in a workflow\n",
"lm_wf <- workflow() %>% \n",
" add_recipe(lm_pumpkins_recipe) %>% \n",
" add_model(lm_spec)\n",
"\n",
"# Print out the workflow\n",
"lm_wf"
],
"outputs": [],
"metadata": {
"id": "T3olroU3v-WX"
}
},
{
"cell_type": "markdown",
"source": [
"Узгред, ток рада може бити прилагођен/трениран на сличан начин као што се тренира модел.\n"
],
"metadata": {
"id": "zd1A5tgOwEPX"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Train the model\n",
"lm_wf_fit <- lm_wf %>% \n",
" fit(data = pumpkins_train)\n",
"\n",
"# Print the model coefficients learned \n",
"lm_wf_fit"
],
"outputs": [],
"metadata": {
"id": "NhJagFumwFHf"
}
},
{
"cell_type": "markdown",
"source": [
"Из излаза модела можемо видети коефицијенте који су научени током тренинга. Они представљају коефицијенте праве најбољег прилагођавања која нам даје најмању укупну грешку између стварне и предвиђене променљиве.\n",
"\n",
"#### Процена перформанси модела коришћењем тест скупа\n",
"\n",
"Време је да видимо како се модел показао 📏! Како то радимо?\n",
"\n",
"Сада када смо обучили модел, можемо га користити за прављење предвиђања за test_set користећи `parsnip::predict()`. Затим можемо упоредити ова предвиђања са стварним вредностима ознака како бисмо проценили колико добро (или не!) модел функционише.\n",
"\n",
"Хајде да почнемо са прављењем предвиђања за тест скуп, а затим да повежемо колоне са тест скупом.\n"
],
"metadata": {
"id": "_4QkGtBTwItF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make predictions for the test set\n",
"predictions <- lm_wf_fit %>% \n",
" predict(new_data = pumpkins_test)\n",
"\n",
"\n",
"# Bind predictions to the test set\n",
"lm_results <- pumpkins_test %>% \n",
" select(c(package, price)) %>% \n",
" bind_cols(predictions)\n",
"\n",
"\n",
"# Print the first ten rows of the tibble\n",
"lm_results %>% \n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "UFZzTG0gwTs9"
}
},
{
"cell_type": "markdown",
"source": [
"Да, управо сте обучили модел и користили га за прављење предикција! 🔮 Да ли је добар? Хајде да проценимо перформансе модела!\n",
"\n",
"У оквиру Tidymodels-а, ово радимо помоћу `yardstick::metrics()`! За линеарну регресију, фокусираћемо се на следеће метрике:\n",
"\n",
"- `Root Mean Square Error (RMSE)`: Квадратни корен од [MSE](https://en.wikipedia.org/wiki/Mean_squared_error). Ова метрика даје апсолутну вредност у истој јединици као и ознака (у овом случају, цена бундеве). Што је вредност мања, то је модел бољи (у поједностављеном смислу, представља просечну цену за коју су предикције погрешне!).\n",
"\n",
"- `Coefficient of Determination (обично познат као R-squared или R2)`: Релативна метрика код које је већа вредност боља за модел. У суштини, ова метрика представља колико варијансе између предвиђених и стварних вредности ознака модел може да објасни.\n"
],
"metadata": {
"id": "0A5MjzM7wW9M"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Evaluate performance of linear regression\n",
"metrics(data = lm_results,\n",
" truth = price,\n",
" estimate = .pred)"
],
"outputs": [],
"metadata": {
"id": "reJ0UIhQwcEH"
}
},
{
"cell_type": "markdown",
"source": [
"Ту иде перформанс модела. Хајде да видимо да ли можемо добити бољу индикацију визуелизацијом расејаног графикона пакета и цене, а затим користити предвиђања за преклапање линије најбољег уклапања.\n",
"\n",
"То значи да ћемо морати припремити и обрадити тестни сет како бисмо кодирали колону пакета, а затим је повезати са предвиђањима која је наш модел направио.\n"
],
"metadata": {
"id": "fdgjzjkBwfWt"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Encode package column\n",
"package_encode <- lm_pumpkins_recipe %>% \n",
" prep() %>% \n",
" bake(new_data = pumpkins_test) %>% \n",
" select(package)\n",
"\n",
"\n",
"# Bind encoded package column to the results\n",
"lm_results <- lm_results %>% \n",
" bind_cols(package_encode %>% \n",
" rename(package_integer = package)) %>% \n",
" relocate(package_integer, .after = package)\n",
"\n",
"\n",
"# Print new results data frame\n",
"lm_results %>% \n",
" slice_head(n = 5)\n",
"\n",
"\n",
"# Make a scatter plot\n",
"lm_results %>% \n",
" ggplot(mapping = aes(x = package_integer, y = price)) +\n",
" geom_point(size = 1.6) +\n",
" # Overlay a line of best fit\n",
" geom_line(aes(y = .pred), color = \"orange\", size = 1.2) +\n",
" xlab(\"package\")\n",
" \n"
],
"outputs": [],
"metadata": {
"id": "R0nw719lwkHE"
}
},
{
"cell_type": "markdown",
"source": [
"Одлично! Као што можете видети, линеарни регресиони модел не успева добро да генерализује однос између пакета и његове одговарајуће цене.\n",
"\n",
"🎃 Честитамо, управо сте направили модел који може помоћи у предвиђању цене неколико врста бундева. Ваш празнични бундева врт ће бити прелеп. Али вероватно можете направити бољи модел!\n",
"\n",
"## 5. Направите полиномијални регресиони модел\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Инфографик од Дасани Мадипали</figcaption>\n",
"\n",
"\n",
"<!--![Инфографик од Дасани Мадипали](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n"
],
"metadata": {
"id": "HOCqJXLTwtWI"
}
},
{
"cell_type": "markdown",
"source": [
"Понекад наши подаци можда немају линеарну везу, али и даље желимо да предвидимо исход. Полиномијална регресија може нам помоћи да направимо предвиђања за сложеније нелинеарне односе.\n",
"\n",
"Узмимо, на пример, однос између паковања и цене у нашем скупу података о бундевама. Иако понекад постоји линеарна веза између променљивих - што је већа бундева по запремини, то је већа цена - понекад се ти односи не могу приказати као раван или права линија.\n",
"\n",
"> ✅ Ево [још неких примера](https://online.stat.psu.edu/stat501/lesson/9/9.8) података који би могли користити полиномијалну регресију\n",
">\n",
"> Поново погледајте однос између сорте и цене на претходном графикону. Да ли овај распршени графикон изгледа као да би нужно требало да се анализира правом линијом? Можда не. У овом случају, можете пробати полиномијалну регресију.\n",
">\n",
"> ✅ Полиноми су математички изрази који могу садржати једну или више променљивих и коефицијената\n",
"\n",
"#### Тренирајте модел полиномијалне регресије користећи скуп за тренирање\n",
"\n",
"Полиномијална регресија креира *закривљену линију* како би боље одговарала нелинеарним подацима.\n",
"\n",
"Хајде да видимо да ли ће полиномијални модел боље функционисати у прављењу предвиђања. Следићемо донекле сличан поступак као што смо радили раније:\n",
"\n",
"- Направите рецепт који одређује кораке предобраде који треба да се спроведу на нашим подацима како би били спремни за моделирање, тј. кодирање предиктора и израчунавање полинома степена *n*\n",
"\n",
"- Направите спецификацију модела\n",
"\n",
"- Спојите рецепт и спецификацију модела у радни ток\n",
"\n",
"- Креирајте модел тако што ћете прилагодити радни ток\n",
"\n",
"- Процените колико добро модел функционише на тест подацима\n",
"\n",
"Хајде да почнемо!\n"
],
"metadata": {
"id": "VcEIpRV9wzYr"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Specify a recipe\r\n",
"poly_pumpkins_recipe <-\r\n",
" recipe(price ~ package, data = pumpkins_train) %>%\r\n",
" step_integer(all_predictors(), zero_based = TRUE) %>% \r\n",
" step_poly(all_predictors(), degree = 4)\r\n",
"\r\n",
"\r\n",
"# Create a model specification\r\n",
"poly_spec <- linear_reg() %>% \r\n",
" set_engine(\"lm\") %>% \r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Bundle recipe and model spec into a workflow\r\n",
"poly_wf <- workflow() %>% \r\n",
" add_recipe(poly_pumpkins_recipe) %>% \r\n",
" add_model(poly_spec)\r\n",
"\r\n",
"\r\n",
"# Create a model\r\n",
"poly_wf_fit <- poly_wf %>% \r\n",
" fit(data = pumpkins_train)\r\n",
"\r\n",
"\r\n",
"# Print learned model coefficients\r\n",
"poly_wf_fit\r\n",
"\r\n",
" "
],
"outputs": [],
"metadata": {
"id": "63n_YyRXw3CC"
}
},
{
"cell_type": "markdown",
"source": [
"#### Оцена перформанси модела\n",
"\n",
"👏👏 Направили сте полиномни модел, хајде да направимо предвиђања на тест скупу!\n"
],
"metadata": {
"id": "-LHZtztSxDP0"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make price predictions on test data\r\n",
"poly_results <- poly_wf_fit %>% predict(new_data = pumpkins_test) %>% \r\n",
" bind_cols(pumpkins_test %>% select(c(package, price))) %>% \r\n",
" relocate(.pred, .after = last_col())\r\n",
"\r\n",
"\r\n",
"# Print the results\r\n",
"poly_results %>% \r\n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "YUFpQ_dKxJGx"
}
},
{
"cell_type": "markdown",
"source": [
"Ву-ху, хајде да проценимо како је модел извршио на test_set користећи `yardstick::metrics()`.\n"
],
"metadata": {
"id": "qxdyj86bxNGZ"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"metrics(data = poly_results, truth = price, estimate = .pred)"
],
"outputs": [],
"metadata": {
"id": "8AW5ltkBxXDm"
}
},
{
"cell_type": "markdown",
"source": [
"🤩🤩 Много бољи учинак.\n",
"\n",
"`rmse` се смањио са отприлике 7 на отприлике 3, што указује на смањење грешке између стварне цене и предвиђене цене. Ово можете *слободно* тумачити као да су у просеку нетачне прогнозе погрешне за око \\$3. `rsq` се повећао са отприлике 0.4 на 0.8.\n",
"\n",
"Сви ови показатељи указују на то да полиномски модел ради много боље од линеарног модела. Одличан посао!\n",
"\n",
"Хајде да видимо да ли можемо ово да визуализујемо!\n"
],
"metadata": {
"id": "6gLHNZDwxYaS"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Bind encoded package column to the results\r\n",
"poly_results <- poly_results %>% \r\n",
" bind_cols(package_encode %>% \r\n",
" rename(package_integer = package)) %>% \r\n",
" relocate(package_integer, .after = package)\r\n",
"\r\n",
"\r\n",
"# Print new results data frame\r\n",
"poly_results %>% \r\n",
" slice_head(n = 5)\r\n",
"\r\n",
"\r\n",
"# Make a scatter plot\r\n",
"poly_results %>% \r\n",
" ggplot(mapping = aes(x = package_integer, y = price)) +\r\n",
" geom_point(size = 1.6) +\r\n",
" # Overlay a line of best fit\r\n",
" geom_line(aes(y = .pred), color = \"midnightblue\", size = 1.2) +\r\n",
" xlab(\"package\")\r\n"
],
"outputs": [],
"metadata": {
"id": "A83U16frxdF1"
}
},
{
"cell_type": "markdown",
"source": [
"Можете видети закривљену линију која боље одговара вашим подацима! 🤩\n",
"\n",
"Можете је учинити још глаткијом тако што ћете проследити полиномску формулу функцији `geom_smooth` на следећи начин:\n"
],
"metadata": {
"id": "4U-7aHOVxlGU"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make a scatter plot\r\n",
"poly_results %>% \r\n",
" ggplot(mapping = aes(x = package_integer, y = price)) +\r\n",
" geom_point(size = 1.6) +\r\n",
" # Overlay a line of best fit\r\n",
" geom_smooth(method = lm, formula = y ~ poly(x, degree = 4), color = \"midnightblue\", size = 1.2, se = FALSE) +\r\n",
" xlab(\"package\")"
],
"outputs": [],
"metadata": {
"id": "5vzNT0Uexm-w"
}
},
{
"cell_type": "markdown",
"source": [
"Баш као глатка крива!🤩\n",
"\n",
"Ево како можете направити нову прогнозу:\n"
],
"metadata": {
"id": "v9u-wwyLxq4G"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make a hypothetical data frame\r\n",
"hypo_tibble <- tibble(package = \"bushel baskets\")\r\n",
"\r\n",
"# Make predictions using linear model\r\n",
"lm_pred <- lm_wf_fit %>% predict(new_data = hypo_tibble)\r\n",
"\r\n",
"# Make predictions using polynomial model\r\n",
"poly_pred <- poly_wf_fit %>% predict(new_data = hypo_tibble)\r\n",
"\r\n",
"# Return predictions in a list\r\n",
"list(\"linear model prediction\" = lm_pred, \r\n",
" \"polynomial model prediction\" = poly_pred)\r\n"
],
"outputs": [],
"metadata": {
"id": "jRPSyfQGxuQv"
}
},
{
"cell_type": "markdown",
"source": [
"Предвиђање помоћу `полиномског модела` има смисла, с обзиром на распршене графике `цена` и `пакета`! И, ако је ово бољи модел од претходног, гледајући исте податке, потребно је да планирате буџет за ове скупље тикве!\n",
"\n",
"🏆 Браво! Направили сте два модела регресије у једном часу. У завршном делу о регресији, научићете о логистичкој регресији за одређивање категорија.\n",
"\n",
"## **🚀Изазов**\n",
"\n",
"Тестирајте неколико различитих променљивих у овом нотебуку да видите како корелација утиче на тачност модела.\n",
"\n",
"## [**Квиз након предавања**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/14/)\n",
"\n",
"## **Преглед и Самостално учење**\n",
"\n",
"У овом часу смо научили о Линеарној регресији. Постоје и други важни типови регресије. Прочитајте о техникама Stepwise, Ridge, Lasso и Elasticnet. Добар курс за даље учење је [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning).\n",
"\n",
"Ако желите да научите више о коришћењу невероватног Tidymodels оквира, погледајте следеће ресурсе:\n",
"\n",
"- Веб-сајт Tidymodels: [Почните са Tidymodels](https://www.tidymodels.org/start/)\n",
"\n",
"- Мак Кун и Џулија Силџ, [*Tidy Modeling with R*](https://www.tmwr.org/)*.*\n",
"\n",
"###### **ХВАЛА:**\n",
"\n",
"[Елисон Хорст](https://twitter.com/allison_horst?lang=en) за креирање невероватних илустрација које чине R приступачнијим и занимљивијим. Пронађите више илустрација у њеној [галерији](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n"
],
"metadata": {
"id": "8zOLOWqMxzk5"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Одрицање од одговорности**: \nОвај документ је преведен коришћењем услуге за превођење помоћу вештачке интелигенције [Co-op Translator](https://github.com/Azure/co-op-translator). Иако тежимо тачности, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на изворном језику треба сматрати ауторитативним извором. За критичне информације препоручује се професионални превод од стране људи. Не сносимо одговорност за било каква погрешна тумачења или неспоразуме који могу произаћи из коришћења овог превода.\n"
]
}
]
}