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

1086 lines
42 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-04T06:26:17+00:00",
"source_file": "2-Regression/3-Linear/solution/R/lesson_3-R.ipynb",
"language_code": "cs"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "EgQw8osnsUV-"
}
},
{
"cell_type": "markdown",
"source": [
"## Lineární a polynomiální regrese pro stanovení cen dýní - Lekce 3\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Infografika od Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![Infografika od Dasani Madipalli](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n",
"\n",
"#### Úvod\n",
"\n",
"Doposud jste prozkoumali, co je regrese, pomocí vzorových dat získaných z datasetu cen dýní, který budeme používat v průběhu této lekce. Také jste ji vizualizovali pomocí `ggplot2`.💪\n",
"\n",
"Nyní jste připraveni ponořit se hlouběji do regrese pro strojové učení. V této lekci se dozvíte více o dvou typech regrese: *základní lineární regrese* a *polynomiální regrese*, spolu s některými matematickými základy těchto technik.\n",
"\n",
"> V celém tomto kurzu předpokládáme minimální znalosti matematiky a snažíme se ji zpřístupnit studentům z jiných oborů, takže sledujte poznámky, 🧮 upozornění, diagramy a další učební nástroje, které vám pomohou s pochopením.\n",
"\n",
"#### Příprava\n",
"\n",
"Připomeňme si, že tato data načítáte, abyste si mohli klást otázky.\n",
"\n",
"- Kdy je nejlepší čas na nákup dýní?\n",
"\n",
"- Jakou cenu mohu očekávat za bednu mini dýní?\n",
"\n",
"- Mám je koupit v půlkoších nebo v krabici o velikosti 1 1/9 bušlu? Pojďme se do těchto dat ponořit hlouběji.\n",
"\n",
"V předchozí lekci jste vytvořili `tibble` (moderní přepracování datového rámce) a naplnili jej částí původního datasetu, standardizovali ceny podle bušlu. Tímto způsobem jste však byli schopni shromáždit pouze asi 400 datových bodů a pouze pro podzimní měsíce. Možná můžeme získat trochu více detailů o povaze dat jejich důkladnějším vyčištěním? Uvidíme... 🕵️‍♀️\n",
"\n",
"Pro tento úkol budeme potřebovat následující balíčky:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) je [kolekce balíčků pro R](https://www.tidyverse.org/packages), která je navržena tak, aby byla datová věda rychlejší, jednodušší a zábavnější!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) je [rámec balíčků](https://www.tidymodels.org/packages/) pro modelování a strojové učení.\n",
"\n",
"- `janitor`: [balíček janitor](https://github.com/sfirke/janitor) poskytuje jednoduché nástroje pro zkoumání a čištění špinavých dat.\n",
"\n",
"- `corrplot`: [balíček corrplot](https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html) poskytuje vizuální nástroj pro zkoumání korelační matice, který podporuje automatické přeskupování proměnných, aby pomohl odhalit skryté vzory mezi proměnnými.\n",
"\n",
"Můžete je nainstalovat pomocí:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"corrplot\"))`\n",
"\n",
"Níže uvedený skript zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a v případě jejich absence je pro vás nainstaluje.\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": [
"Později načteme tyto skvělé balíčky a zpřístupníme je v naší aktuální R relaci. (Toto je pouze pro ilustraci, `pacman::p_load()` to už za vás udělal)\n",
"\n",
"## 1. Přímka lineární regrese\n",
"\n",
"Jak jste se naučili v Lekci 1, cílem cvičení lineární regrese je být schopen vykreslit *přímku* *nejlepšího* *přizpůsobení*, která:\n",
"\n",
"- **Ukazuje vztahy mezi proměnnými**. Zobrazuje vztah mezi proměnnými.\n",
"\n",
"- **Umožňuje predikce**. Poskytuje přesné předpovědi, kam by nový datový bod spadal ve vztahu k této přímce.\n",
"\n",
"K vykreslení tohoto typu přímky používáme statistickou techniku nazvanou **Regrese nejmenších čtverců**. Termín `nejmenší čtverce` znamená, že všechny datové body obklopující regresní přímku jsou umocněny na druhou a poté sečteny. Ideálně je tento konečný součet co nejmenší, protože chceme mít nízký počet chyb, tedy `nejmenší čtverce`. Přímka nejlepšího přizpůsobení je tedy ta, která nám dává nejnižší hodnotu součtu čtverců chyb odtud název *regrese nejmenších čtverců*.\n",
"\n",
"Děláme to proto, že chceme modelovat přímku, která má nejmenší kumulativní vzdálenost od všech našich datových bodů. Termíny také umocňujeme na druhou před jejich sečtením, protože nás zajímá jejich velikost, nikoli směr.\n",
"\n",
"> **🧮 Ukažte mi matematiku**\n",
">\n",
"> Tato přímka, nazývaná *přímka nejlepšího přizpůsobení*, může být vyjádřena [rovnicí](https://en.wikipedia.org/wiki/Simple_linear_regression):\n",
">\n",
"> Y = a + bX\n",
">\n",
"> `X` je '`vysvětlující proměnná` nebo `prediktor`'. `Y` je '`závislá proměnná` nebo `výsledek`'. Sklon přímky je `b` a `a` je průsečík s osou y, což označuje hodnotu `Y`, když `X = 0`.\n",
">\n",
"\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/slope.png \"sklon = $y/x$\")\n",
" Infografika od Jen Looper\n",
">\n",
"> Nejprve vypočítejte sklon `b`.\n",
">\n",
"> Jinými slovy, a s odkazem na původní otázku o datech dýní: \"předpovězte cenu dýně za bušl podle měsíce\", `X` by označovalo cenu a `Y` by označovalo měsíc prodeje.\n",
">\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/calculation.png)\n",
" Infografika od Jen Looper\n",
"> \n",
"> Vypočítejte hodnotu Y. Pokud platíte kolem 4 $, musí být duben!\n",
">\n",
"> Matematika, která vypočítává přímku, musí ukázat sklon přímky, který také závisí na průsečíku, tedy na tom, kde se `Y` nachází, když `X = 0`.\n",
">\n",
"> Metodu výpočtu těchto hodnot si můžete prohlédnout na webu [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html). Navštivte také [tento kalkulátor nejmenších čtverců](https://www.mathsisfun.com/data/least-squares-calculator.html), abyste viděli, jak hodnoty čísel ovlivňují přímku.\n",
"\n",
"Není to tak děsivé, že? 🤓\n",
"\n",
"#### Korelace\n",
"\n",
"Ještě jeden termín, který je třeba pochopit, je **koeficient korelace** mezi danými proměnnými X a Y. Pomocí bodového grafu můžete tento koeficient rychle vizualizovat. Graf s body uspořádanými do úhledné přímky má vysokou korelaci, ale graf s body rozptýlenými všude mezi X a Y má nízkou korelaci.\n",
"\n",
"Dobrý model lineární regrese bude takový, který má vysoký (blíže k 1 než k 0) koeficient korelace při použití metody regrese nejmenších čtverců s regresní přímkou.\n"
],
"metadata": {
"id": "cdX5FRpvsoP5"
}
},
{
"cell_type": "markdown",
"source": [
"## **2. Tanec s daty: vytvoření datového rámce pro modelování**\n",
"\n",
"<p >\n",
" <img src=\"../../images/janitor.jpg\"\n",
" width=\"700\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Ilustrace od \\@allison_horst](../../../../../../2-Regression/3-Linear/images/janitor.jpg){width=\"700\"}-->\n"
],
"metadata": {
"id": "WdUKXk7Bs8-V"
}
},
{
"cell_type": "markdown",
"source": [
"Načtěte potřebné knihovny a dataset. Převést data na datový rámec obsahující podmnožinu dat:\n",
"\n",
"- Získat pouze dýně oceněné podle bušlu\n",
"\n",
"- Převést datum na měsíc\n",
"\n",
"- Vypočítat cenu jako průměr vysokých a nízkých cen\n",
"\n",
"- Převést cenu tak, aby odrážela ocenění podle množství v bušlech\n",
"\n",
"> Tyto kroky jsme pokryli v [předchozí lekci](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": [
"Ve duchu čistého dobrodružství pojďme prozkoumat [`balíček janitor`](../../../../../../2-Regression/3-Linear/solution/R/github.com/sfirke/janitor), který poskytuje jednoduché funkce pro zkoumání a čištění nepořádných dat. Například se podívejme na názvy sloupců našich dat:\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": [
"🤔 Můžeme to udělat lépe. Pojďme tyto názvy sloupců `friendR` převést na konvenci [snake_case](https://en.wikipedia.org/wiki/Snake_case) pomocí `janitor::clean_names`. Chcete-li se o této funkci dozvědět více: `?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": [
"Mnoho tidyR 🧹! Teď tanec s daty pomocí `dplyr`, stejně jako v předchozí lekci! 💃\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": [
"Dobrá práce!👌 Nyní máte čistou a upravenou datovou sadu, na které můžete postavit svůj nový regresní model!\n",
"\n",
"Co takhle bodový graf?\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": [
"Bodový graf nám připomíná, že máme data pouze za měsíce od srpna do prosince. Pravděpodobně budeme potřebovat více dat, abychom mohli vyvozovat závěry lineárním způsobem.\n",
"\n",
"Podívejme se znovu na naše modelovací data:\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": [
"Co kdybychom chtěli předpovědět `cenu` dýně na základě sloupců `město` nebo `balení`, které jsou typu znak? Nebo ještě jednodušeji, jak bychom mohli najít korelaci (která vyžaduje, aby oba její vstupy byly číselné) například mezi `balení` a `cenou`? 🤷🤷\n",
"\n",
"Modely strojového učení fungují nejlépe s číselnými vlastnostmi než s textovými hodnotami, takže je obvykle potřeba převést kategorické vlastnosti na číselné reprezentace.\n",
"\n",
"To znamená, že musíme najít způsob, jak přeformátovat naše prediktory, aby je model mohl efektivně využít, což je proces známý jako `feature engineering`.\n"
],
"metadata": {
"id": "7hsHoxsStyjJ"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Předzpracování dat pro modelování s balíčkem recipes 👩‍🍳👨‍🍳\n",
"\n",
"Aktivity, které upravují hodnoty prediktorů tak, aby je model mohl efektivněji využít, se označují jako `feature engineering`.\n",
"\n",
"Různé modely mají různé požadavky na předzpracování. Například metoda nejmenších čtverců vyžaduje `kódování kategoriálních proměnných`, jako jsou měsíc, odrůda a city_name. To jednoduše zahrnuje `převod` sloupce s `kategoriálními hodnotami` na jeden nebo více `numerických sloupců`, které nahradí původní.\n",
"\n",
"Například, pokud vaše data obsahují následující kategoriální proměnnou:\n",
"\n",
"| město |\n",
"|:--------:|\n",
"| Denver |\n",
"| Nairobi |\n",
"| Tokio |\n",
"\n",
"Můžete použít *ordinální kódování*, které nahradí každou kategorii unikátní celočíselnou hodnotou, například takto:\n",
"\n",
"| město |\n",
"|:-----:|\n",
"| 0 |\n",
"| 1 |\n",
"| 2 |\n",
"\n",
"A přesně to uděláme s našimi daty!\n",
"\n",
"V této části prozkoumáme další úžasný balíček z Tidymodels: [recipes](https://tidymodels.github.io/recipes/) - který je navržen tak, aby vám pomohl předzpracovat data **před** trénováním modelu. Základem balíčku je objekt zvaný recept, který definuje, jaké kroky by měly být aplikovány na datovou sadu, aby byla připravena pro modelování.\n",
"\n",
"Teď si vytvoříme recept, který připraví naše data pro modelování tím, že nahradí unikátní celočíselnou hodnotu za všechny pozorování ve sloupcích prediktorů:\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": [
"Skvělé! 👏 Právě jsme vytvořili náš první recept, který určuje výsledek (cenu) a jeho odpovídající prediktory, přičemž všechny sloupce prediktorů by měly být zakódovány jako sada celých čísel 🙌! Pojďme si to rychle rozebrat:\n",
"\n",
"- Volání `recipe()` s formulí říká receptu *role* proměnných, přičemž jako referenční data používá `new_pumpkins`. Například sloupec `price` byl přiřazen roli `outcome`, zatímco ostatní sloupce byly přiřazeny roli `predictor`.\n",
"\n",
"- `step_integer(all_predictors(), zero_based = TRUE)` určuje, že všechny prediktory by měly být převedeny na sadu celých čísel, přičemž číslování začíná od 0.\n",
"\n",
"Jsme si jistí, že vás možná napadá něco jako: \"To je tak skvělé!! Ale co když budu potřebovat potvrdit, že recepty dělají přesně to, co od nich očekávám? 🤔\"\n",
"\n",
"To je skvělá myšlenka! Vidíte, jakmile je váš recept definován, můžete odhadnout parametry potřebné k předzpracování dat a poté extrahovat zpracovaná data. Obvykle to nemusíte dělat, když používáte Tidymodels (za chvíli uvidíme běžnou konvenci -\\> `workflows`), ale může se to hodit, když chcete provést nějakou kontrolu správnosti a potvrdit, že recepty dělají to, co očekáváte.\n",
"\n",
"K tomu budete potřebovat dvě další funkce: `prep()` a `bake()`, a jako vždy vám naši malí R kamarádi od [`Allison Horst`](https://github.com/allisonhorst/stats-illustrations) pomohou lépe pochopit tento proces!\n",
"\n",
"<p >\n",
" <img src=\"../../images/recipes.png\"\n",
" width=\"550\"/>\n",
" <figcaption>Ilustrace od @allison_horst</figcaption>\n"
],
"metadata": {
"id": "KEiO0v7kuC9O"
}
},
{
"cell_type": "markdown",
"source": [
"[`prep()`](https://recipes.tidymodels.org/reference/prep.html): odhaduje potřebné parametry z trénovací sady, které mohou být později aplikovány na jiné datové sady. Například, pro daný sloupec prediktoru, která pozorování budou přiřazena jako celé číslo 0, 1, 2 atd.\n",
"\n",
"[`bake()`](https://recipes.tidymodels.org/reference/bake.html): vezme připravený recept a aplikuje operace na jakoukoli datovou sadu.\n",
"\n",
"To znamená, pojďme připravit a upéct naše recepty, abychom si skutečně ověřili, že v zákulisí budou sloupce prediktorů nejprve zakódovány, než bude model natrénová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": [
"Hurá! 🥳 Zpracovaná data `baked_pumpkins` mají všechny své prediktory zakódované, což potvrzuje, že kroky předzpracování definované jako náš recept budou fungovat podle očekávání. To sice ztěžuje čtení, ale pro Tidymodels je to mnohem srozumitelnější! Udělejte si chvíli na to, abyste zjistili, která pozorování byla namapována na odpovídající celé číslo.\n",
"\n",
"Za zmínku také stojí, že `baked_pumpkins` je datový rámec, na kterém můžeme provádět výpočty.\n",
"\n",
"Například se pokusme najít dobrou korelaci mezi dvěma body vašich dat, abychom potenciálně vytvořili dobrý prediktivní model. K tomu použijeme funkci `cor()`. Zadejte `?cor()`, abyste se dozvěděli více o této funkci.\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": [
"Jak se ukazuje, mezi městem a cenou existuje pouze slabá korelace. Nicméně mezi balením a jeho cenou je o něco lepší korelace. To dává smysl, že? Obvykle platí, že čím větší je krabice s produkty, tím vyšší je cena.\n",
"\n",
"Když už jsme u toho, pojďme také zkusit vizualizovat korelační matici všech sloupců pomocí balíčku `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": [
"🤩🤩 Mnohem lepší.\n",
"\n",
"Dobrá otázka, kterou si teď můžeme položit, je: '`Jakou cenu mohu očekávat za daný balíček dýní?`' Pojďme se na to podívat!\n",
"\n",
"> Poznámka: Když **`bake()`** připravený recept **`pumpkins_prep`** s **`new_data = NULL`**, získáte zpracovaná (tj. zakódovaná) tréninková data. Pokud byste měli jinou datovou sadu, například testovací sadu, a chtěli byste vidět, jak by ji recept předzpracoval, jednoduše byste použili **`bake`** na **`pumpkins_prep`** s **`new_data = test_set`**.\n",
"\n",
"## 4. Vytvořte lineární regresní model\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Infografika od Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![Infografika od Dasani Madipalli](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n"
],
"metadata": {
"id": "YqXjLuWavNxW"
}
},
{
"cell_type": "markdown",
"source": [
"Nyní, když jsme vytvořili recept a skutečně potvrdili, že data budou správně předzpracována, pojďme vytvořit regresní model, který odpoví na otázku: `Jakou cenu mohu očekávat u daného balení dýní?`\n",
"\n",
"#### Natrénujte lineární regresní model pomocí trénovací sady\n",
"\n",
"Jak jste si už možná všimli, sloupec *price* je proměnná `výsledek`, zatímco sloupec *package* je proměnná `prediktor`.\n",
"\n",
"K tomu nejprve rozdělíme data tak, že 80 % půjde do trénovací sady a 20 % do testovací sady, poté definujeme recept, který zakóduje sloupec prediktoru do sady celých čísel, a následně vytvoříme specifikaci modelu. Recept nebudeme připravovat ani péct, protože už víme, že data předzpracuje podle očekávání.\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": [
"Skvělá práce! Teď, když máme recept a specifikaci modelu, musíme najít způsob, jak je spojit do jednoho objektu, který nejprve předzpracuje data (prep+bake na pozadí), přizpůsobí model na předzpracovaná data a také umožní případné aktivity po zpracování. Jak se vám to líbí pro klid duše!🤩\n",
"\n",
"V Tidymodels se tento praktický objekt nazývá [`workflow`](https://workflows.tidymodels.org/) a pohodlně uchovává vaše modelovací komponenty! To je to, co bychom v *Pythonu* nazvali *pipelines*.\n",
"\n",
"Tak pojďme všechno spojit do 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": [
"👌 Navíc lze pracovní postup přizpůsobit/vytrénovat podobně jako model.\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": [
"Z výstupu modelu můžeme vidět koeficienty naučené během trénování. Tyto koeficienty představují parametry přímky nejlepšího přizpůsobení, která nám poskytuje nejnižší celkovou chybu mezi skutečnou a předpovězenou proměnnou.\n",
"\n",
"#### Vyhodnocení výkonu modelu pomocí testovací sady\n",
"\n",
"Je čas zjistit, jak si model vedl 📏! Jak na to?\n",
"\n",
"Teď, když jsme model natrénovali, můžeme ho použít k předpovědím pro testovací_sadu pomocí `parsnip::predict()`. Poté můžeme tyto předpovědi porovnat se skutečnými hodnotami štítků, abychom vyhodnotili, jak dobře (nebo ne!) model funguje.\n",
"\n",
"Začněme tím, že vytvoříme předpovědi pro testovací sadu a poté připojíme sloupce k testovací sadě.\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": [
"Ano, právě jste natrénovali model a použili ho k provádění predikcí! 🔮 Je to dobré? Pojďme zhodnotit výkon modelu!\n",
"\n",
"V Tidymodels to děláme pomocí `yardstick::metrics()`! Pro lineární regresi se zaměříme na následující metriky:\n",
"\n",
"- `Root Mean Square Error (RMSE)`: Druhá odmocnina [MSE](https://en.wikipedia.org/wiki/Mean_squared_error). Poskytuje absolutní metriku ve stejné jednotce jako cílová proměnná (v tomto případě cena dýně). Čím menší hodnota, tím lepší model (zjednodušeně řečeno, představuje průměrnou cenu, o kterou se predikce mýlí!).\n",
"\n",
"- `Coefficient of Determination (obvykle známý jako R-squared nebo R2)`: Relativní metrika, u které platí, že čím vyšší hodnota, tím lepší přizpůsobení modelu. V podstatě tato metrika ukazuje, kolik rozptylu mezi predikovanými a skutečnými hodnotami cílové proměnné je model schopen vysvětlit.\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": [
"Tam jde výkon modelu. Podívejme se, zda můžeme získat lepší představu vizualizací bodového grafu balíčku a ceny, a poté použijeme předpovědi k překrytí čáry nejlepšího přizpůsobení.\n",
"\n",
"To znamená, že budeme muset připravit a zpracovat testovací sadu, abychom zakódovali sloupec balíčku a následně jej spojili s předpověďmi vytvořenými naším modelem.\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": [
"Skvělé! Jak můžete vidět, lineární regresní model příliš dobře negeneralizuje vztah mezi balíčkem a jeho odpovídající cenou.\n",
"\n",
"🎃 Gratulace, právě jste vytvořili model, který může pomoci předpovědět cenu několika druhů dýní. Vaše sváteční dýňové pole bude nádherné. Ale pravděpodobně můžete vytvořit ještě lepší model!\n",
"\n",
"## 5. Vytvořte model polynomiální regrese\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Infografika od Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![Infografika od Dasani Madipalli](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n"
],
"metadata": {
"id": "HOCqJXLTwtWI"
}
},
{
"cell_type": "markdown",
"source": [
"Někdy naše data nemusí mít lineární vztah, ale přesto chceme předpovědět výsledek. Polynomická regrese nám může pomoci provádět předpovědi pro složitější nelineární vztahy.\n",
"\n",
"Vezměme si například vztah mezi balením a cenou v našem datovém souboru s dýněmi. Zatímco někdy existuje lineární vztah mezi proměnnými - čím větší je dýně podle objemu, tím vyšší je cena - někdy tyto vztahy nelze vykreslit jako rovinu nebo přímku.\n",
"\n",
"> ✅ Zde jsou [další příklady](https://online.stat.psu.edu/stat501/lesson/9/9.8) dat, která by mohla využít polynomickou regresi\n",
">\n",
"> Podívejte se znovu na vztah mezi odrůdou a cenou v předchozím grafu. Zdá se, že tento bodový graf by měl být nutně analyzován pomocí přímky? Možná ne. V tomto případě můžete zkusit polynomickou regresi.\n",
">\n",
"> ✅ Polynomy jsou matematické výrazy, které mohou obsahovat jednu nebo více proměnných a koeficientů.\n",
"\n",
"#### Natrénujte model polynomické regrese pomocí trénovací sady\n",
"\n",
"Polynomická regrese vytváří *zakřivenou čáru*, která lépe odpovídá nelineárním datům.\n",
"\n",
"Podívejme se, zda polynomický model bude lépe fungovat při předpovědích. Budeme postupovat podobným způsobem jako dříve:\n",
"\n",
"- Vytvořte recept, který určuje kroky předzpracování, jež by měly být provedeny na našich datech, aby byla připravena pro modelování, tj. kódování prediktorů a výpočet polynomů stupně *n*\n",
"\n",
"- Vytvořte specifikaci modelu\n",
"\n",
"- Spojte recept a specifikaci modelu do pracovního postupu\n",
"\n",
"- Vytvořte model přizpůsobením pracovního postupu\n",
"\n",
"- Vyhodnoťte, jak dobře model funguje na testovacích datech\n",
"\n",
"Pojďme se do toho pustit!\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": [
"#### Vyhodnocení výkonu modelu\n",
"\n",
"👏👏 Vytvořili jste polynomiální model, pojďme udělat předpovědi na testovací sadě!\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": [
"Hurá, pojďme vyhodnotit, jak si model vedl na testovací sadě pomocí `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": [
"🤩🤩 Mnohem lepší výkon.\n",
"\n",
"`rmse` kleslo z přibližně 7 na přibližně 3, což naznačuje snížení chyby mezi skutečnou cenou a předpovězenou cenou. Můžete to *volně* interpretovat tak, že průměrně jsou nesprávné předpovědi chybné o zhruba 3 $. `rsq` vzrostlo z přibližně 0,4 na 0,8.\n",
"\n",
"Všechny tyto metriky ukazují, že polynomiální model funguje mnohem lépe než lineární model. Skvělá práce!\n",
"\n",
"Podívejme se, jestli to můžeme vizualizovat!\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": [
"Můžete vidět zakřivenou čáru, která lépe odpovídá vašim datům! 🤩\n",
"\n",
"Můžete ji udělat ještě hladší tím, že předáte polynomiální formuli funkci `geom_smooth` takto:\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": [
"Podobně jako hladká křivka!🤩\n",
"\n",
"Takto byste mohli vytvořit novou předpověď:\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": [
"Predpověď pomocí `polynomial model` dává smysl, vzhledem k bodovým grafům `price` a `package`! A pokud je tento model lepší než ten předchozí, při pohledu na stejná data budete muset počítat s rozpočtem na tyto dražší dýně!\n",
"\n",
"🏆 Skvělá práce! Vytvořili jste dva regresní modely během jedné lekce. V závěrečné části o regresi se naučíte o logistické regresi pro určení kategorií.\n",
"\n",
"## **🚀Výzva**\n",
"\n",
"Vyzkoušejte několik různých proměnných v tomto notebooku a zjistěte, jak korelace odpovídá přesnosti modelu.\n",
"\n",
"## [**Kvíz po přednášce**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/14/)\n",
"\n",
"## **Přehled & Samostudium**\n",
"\n",
"V této lekci jsme se naučili o lineární regresi. Existují i další důležité typy regrese. Přečtěte si o technikách Stepwise, Ridge, Lasso a Elasticnet. Skvělý kurz pro další studium je [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning).\n",
"\n",
"Pokud se chcete dozvědět více o používání úžasného frameworku Tidymodels, podívejte se na následující zdroje:\n",
"\n",
"- Web Tidymodels: [Začněte s Tidymodels](https://www.tidymodels.org/start/)\n",
"\n",
"- Max Kuhn a Julia Silge, [*Tidy Modeling with R*](https://www.tmwr.org/)*.*\n",
"\n",
"###### **DĚKUJEME:**\n",
"\n",
"[Allison Horst](https://twitter.com/allison_horst?lang=en) za vytvoření úžasných ilustrací, které činí R přívětivějším a poutavějším. Další ilustrace najdete v její [galerii](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**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o přesnost, mějte na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro kritické informace se doporučuje profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n"
]
}
]
}