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.
1086 lines
42 KiB
1086 lines
42 KiB
{
|
|
"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:28:04+00:00",
|
|
"source_file": "2-Regression/3-Linear/solution/R/lesson_3-R.ipynb",
|
|
"language_code": "da"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [],
|
|
"metadata": {
|
|
"id": "EgQw8osnsUV-"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Lineær og Polynomisk Regression for Græskarpriser - Lektion 3\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/linear-polynomial.png\"\n",
|
|
" width=\"800\"/>\n",
|
|
" <figcaption>Infografik af Dasani Madipalli</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!--{width=\"800\"}-->\n",
|
|
"\n",
|
|
"#### Introduktion\n",
|
|
"\n",
|
|
"Indtil videre har du udforsket, hvad regression er, med eksempeldata indsamlet fra græskarpris-datasættet, som vi vil bruge gennem denne lektion. Du har også visualiseret det ved hjælp af `ggplot2`.💪\n",
|
|
"\n",
|
|
"Nu er du klar til at dykke dybere ned i regression for ML. I denne lektion vil du lære mere om to typer regression: *grundlæggende lineær regression* og *polynomisk regression*, sammen med noget af den matematik, der ligger til grund for disse teknikker.\n",
|
|
"\n",
|
|
"> Gennem hele dette pensum antager vi minimal viden om matematik og søger at gøre det tilgængeligt for studerende fra andre områder, så hold øje med noter, 🧮 fremhævelser, diagrammer og andre læringsværktøjer, der kan hjælpe med forståelsen.\n",
|
|
"\n",
|
|
"#### Forberedelse\n",
|
|
"\n",
|
|
"Som en påmindelse, du indlæser disse data for at kunne stille spørgsmål til dem.\n",
|
|
"\n",
|
|
"- Hvornår er det bedste tidspunkt at købe græskar?\n",
|
|
"\n",
|
|
"- Hvilken pris kan jeg forvente for en kasse med miniaturegræskar?\n",
|
|
"\n",
|
|
"- Skal jeg købe dem i halv-bushel kurve eller i 1 1/9 bushel kasser? Lad os fortsætte med at grave i disse data.\n",
|
|
"\n",
|
|
"I den forrige lektion oprettede du en `tibble` (en moderne genfortolkning af dataframes) og fyldte den med en del af det originale datasæt, hvor du standardiserede prisen pr. bushel. Ved at gøre det var du dog kun i stand til at samle omkring 400 datapunkter, og kun for efterårsmånederne. Måske kan vi få lidt mere detaljeret indsigt i dataene ved at rense dem yderligere? Det må vi se... 🕵️♀️\n",
|
|
"\n",
|
|
"Til denne opgave skal vi bruge følgende pakker:\n",
|
|
"\n",
|
|
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) er en [samling af R-pakker](https://www.tidyverse.org/packages), der er designet til at gøre datavidenskab hurtigere, lettere og sjovere!\n",
|
|
"\n",
|
|
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) er en [rammeværk af pakker](https://www.tidymodels.org/packages/) til modellering og maskinlæring.\n",
|
|
"\n",
|
|
"- `janitor`: [janitor-pakken](https://github.com/sfirke/janitor) tilbyder enkle værktøjer til at undersøge og rense beskidte data.\n",
|
|
"\n",
|
|
"- `corrplot`: [corrplot-pakken](https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html) giver et visuelt udforskningsværktøj til korrelationsmatricer, der understøtter automatisk variabelomorganisering for at hjælpe med at opdage skjulte mønstre blandt variabler.\n",
|
|
"\n",
|
|
"Du kan installere dem som:\n",
|
|
"\n",
|
|
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"corrplot\"))`\n",
|
|
"\n",
|
|
"Scriptet nedenfor tjekker, om du har de nødvendige pakker til at fuldføre dette modul og installerer dem for dig, hvis de mangler.\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": [
|
|
"Vi vil senere indlæse disse fantastiske pakker og gøre dem tilgængelige i vores nuværende R-session. (Dette er kun for illustration, `pacman::p_load()` har allerede gjort det for dig)\n",
|
|
"\n",
|
|
"## 1. En lineær regressionslinje\n",
|
|
"\n",
|
|
"Som du lærte i Lektion 1, er målet med en lineær regressionsøvelse at kunne tegne en *linje* *af* *bedste tilpasning* for at:\n",
|
|
"\n",
|
|
"- **Vis variableforhold**. Vise forholdet mellem variabler.\n",
|
|
"\n",
|
|
"- **Foretage forudsigelser**. Foretage præcise forudsigelser om, hvor et nyt datapunkt vil falde i forhold til den linje.\n",
|
|
"\n",
|
|
"For at tegne denne type linje bruger vi en statistisk teknik kaldet **Mindste Kvadraters Regression**. Udtrykket `mindste kvadrater` betyder, at alle datapunkterne omkring regressionslinjen kvadreres og derefter lægges sammen. Ideelt set er den endelige sum så lille som muligt, fordi vi ønsker et lavt antal fejl, eller `mindste kvadrater`. Som sådan er linjen med den bedste tilpasning den linje, der giver os den laveste værdi for summen af de kvadrerede fejl - deraf navnet *mindste kvadraters regression*.\n",
|
|
"\n",
|
|
"Vi gør dette, fordi vi ønsker at modellere en linje, der har den mindste kumulative afstand fra alle vores datapunkter. Vi kvadrerer også termerne, før vi lægger dem sammen, da vi er interesserede i deres størrelse snarere end deres retning.\n",
|
|
"\n",
|
|
"> **🧮 Vis mig matematikken**\n",
|
|
">\n",
|
|
"> Denne linje, kaldet *linjen med den bedste tilpasning*, kan udtrykkes ved [en ligning](https://en.wikipedia.org/wiki/Simple_linear_regression):\n",
|
|
">\n",
|
|
"> Y = a + bX\n",
|
|
">\n",
|
|
"> `X` er '`forklarende variabel` eller `prediktor`'. `Y` er '`afhængig variabel` eller `resultat`'. Hældningen af linjen er `b`, og `a` er skæringspunktet med y-aksen, som refererer til værdien af `Y`, når `X = 0`.\n",
|
|
">\n",
|
|
"\n",
|
|
"> \n",
|
|
" Infografik af Jen Looper\n",
|
|
">\n",
|
|
"> Først beregnes hældningen `b`.\n",
|
|
">\n",
|
|
"> Med andre ord, og med henvisning til vores græskardatas oprindelige spørgsmål: \"forudsige prisen på et græskar pr. tønde efter måned\", ville `X` referere til prisen, og `Y` ville referere til salgsdatoen.\n",
|
|
">\n",
|
|
"> \n",
|
|
" Infografik af Jen Looper\n",
|
|
"> \n",
|
|
"> Beregn værdien af Y. Hvis du betaler omkring \\$4, må det være april!\n",
|
|
">\n",
|
|
"> Matematikken, der beregner linjen, skal demonstrere hældningen af linjen, som også afhænger af skæringspunktet, eller hvor `Y` er placeret, når `X = 0`.\n",
|
|
">\n",
|
|
"> Du kan se metoden til beregning af disse værdier på webstedet [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html). Besøg også [denne Mindste Kvadraters beregner](https://www.mathsisfun.com/data/least-squares-calculator.html) for at se, hvordan tallenes værdier påvirker linjen.\n",
|
|
"\n",
|
|
"Ikke så skræmmende, vel? 🤓\n",
|
|
"\n",
|
|
"#### Korrelation\n",
|
|
"\n",
|
|
"Et andet begreb, du skal forstå, er **Korrelationskoefficienten** mellem givne X- og Y-variabler. Ved hjælp af et scatterplot kan du hurtigt visualisere denne koefficient. Et plot med datapunkter spredt i en pæn linje har høj korrelation, men et plot med datapunkter spredt overalt mellem X og Y har lav korrelation.\n",
|
|
"\n",
|
|
"En god lineær regressionsmodel vil være en, der har en høj (nærmere 1 end 0) korrelationskoefficient ved brug af Mindste Kvadraters Regression-metoden med en regressionslinje.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "cdX5FRpvsoP5"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## **2. En dans med data: oprettelse af en data frame til modellering**\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/janitor.jpg\"\n",
|
|
" width=\"700\"/>\n",
|
|
" <figcaption>Kunstværk af @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!--{width=\"700\"}-->\n"
|
|
],
|
|
"metadata": {
|
|
"id": "WdUKXk7Bs8-V"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Indlæs de nødvendige biblioteker og datasæt. Konverter dataene til en data frame, der indeholder et udsnit af dataene:\n",
|
|
"\n",
|
|
"- Kun få græskar, der er prissat pr. tønde\n",
|
|
"\n",
|
|
"- Konverter datoen til en måned\n",
|
|
"\n",
|
|
"- Beregn prisen som et gennemsnit af høj og lav pris\n",
|
|
"\n",
|
|
"- Konverter prisen, så den afspejler prissætningen pr. tønde\n",
|
|
"\n",
|
|
"> Vi dækkede disse trin i [den forrige lektion](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": [
|
|
"I eventyrets ånd, lad os udforske [`janitor-pakken`](../../../../../../2-Regression/3-Linear/solution/R/github.com/sfirke/janitor), der tilbyder simple funktioner til at undersøge og rense beskidte data. For eksempel, lad os tage et kig på kolonnenavnene for vores data:\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": [
|
|
"🤔 Vi kan gøre det bedre. Lad os gøre disse kolonnenavne `friendR` ved at konvertere dem til [snake_case](https://en.wikipedia.org/wiki/Snake_case)-konventionen ved hjælp af `janitor::clean_names`. For at finde ud af mere om denne funktion: `?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": [
|
|
"Meget tidyR 🧹! Nu, en dans med dataene ved hjælp af `dplyr` som i den tidligere lektion! 💃\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": [
|
|
"Godt klaret!👌 Du har nu et rent og ryddeligt datasæt, som du kan bruge til at bygge din nye regressionsmodel!\n",
|
|
"\n",
|
|
"Hvad siger du til et scatterplot?\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": [
|
|
"Et spredningsdiagram minder os om, at vi kun har månedsdata fra august til december. Vi har sandsynligvis brug for mere data for at kunne drage konklusioner på en lineær måde.\n",
|
|
"\n",
|
|
"Lad os tage et kig på vores modelleringsdata igen:\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": [
|
|
"Hvad hvis vi ville forudsige `price` på et græskar baseret på `city` eller `package` kolonnerne, som er af typen karakter? Eller endnu enklere, hvordan kunne vi finde korrelationen (som kræver, at begge input er numeriske) mellem for eksempel `package` og `price`? 🤷🤷\n",
|
|
"\n",
|
|
"Maskinlæringsmodeller fungerer bedst med numeriske egenskaber frem for tekstværdier, så det er generelt nødvendigt at konvertere kategoriske egenskaber til numeriske repræsentationer.\n",
|
|
"\n",
|
|
"Det betyder, at vi skal finde en måde at omformatere vores prediktorer på, så de bliver nemmere for en model at bruge effektivt, en proces kendt som `feature engineering`.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "7hsHoxsStyjJ"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## 3. Forbehandling af data til modellering med opskrifter 👩🍳👨🍳\n",
|
|
"\n",
|
|
"Aktiviteter, der omformaterer prædiktorværdier for at gøre dem lettere for en model at bruge effektivt, kaldes `feature engineering`.\n",
|
|
"\n",
|
|
"Forskellige modeller har forskellige krav til forbehandling. For eksempel kræver mindste kvadrater `kodning af kategoriske variabler` såsom måned, sort og bynavn. Dette indebærer simpelthen at `oversætte` en kolonne med `kategoriske værdier` til en eller flere `numeriske kolonner`, der erstatter den oprindelige.\n",
|
|
"\n",
|
|
"For eksempel, antag at dine data indeholder følgende kategoriske variabel:\n",
|
|
"\n",
|
|
"| by |\n",
|
|
"|:-------:|\n",
|
|
"| Denver |\n",
|
|
"| Nairobi |\n",
|
|
"| Tokyo |\n",
|
|
"\n",
|
|
"Du kan anvende *ordinal kodning* for at erstatte hver kategori med en unik heltalsværdi, som dette:\n",
|
|
"\n",
|
|
"| by |\n",
|
|
"|:---:|\n",
|
|
"| 0 |\n",
|
|
"| 1 |\n",
|
|
"| 2 |\n",
|
|
"\n",
|
|
"Og det er præcis, hvad vi vil gøre med vores data!\n",
|
|
"\n",
|
|
"I denne sektion vil vi udforske endnu en fantastisk Tidymodels-pakke: [recipes](https://tidymodels.github.io/recipes/) - som er designet til at hjælpe dig med at forbehandle dine data **før** du træner din model. I sin kerne er en opskrift et objekt, der definerer, hvilke trin der skal anvendes på et datasæt for at gøre det klar til modellering.\n",
|
|
"\n",
|
|
"Lad os nu oprette en opskrift, der forbereder vores data til modellering ved at erstatte en unik heltalsværdi for alle observationer i prædiktorkolonnerne:\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": [
|
|
"Fantastisk! 👏 Vi har lige oprettet vores første opskrift, der specificerer et resultat (pris) og de tilsvarende prediktorer, og som sørger for, at alle prediktorkolonner bliver kodet som et sæt heltal 🙌! Lad os hurtigt bryde det ned:\n",
|
|
"\n",
|
|
"- Kaldet til `recipe()` med en formel fortæller opskriften *rollerne* for variablerne ved at bruge `new_pumpkins`-dataene som reference. For eksempel er `price`-kolonnen blevet tildelt rollen som `outcome`, mens resten af kolonnerne er blevet tildelt rollen som `predictor`.\n",
|
|
"\n",
|
|
"- `step_integer(all_predictors(), zero_based = TRUE)` specificerer, at alle prediktorer skal konverteres til et sæt heltal, hvor nummereringen starter ved 0.\n",
|
|
"\n",
|
|
"Vi er sikre på, at du måske tænker: \"Det her er så fedt!! Men hvad nu hvis jeg havde brug for at bekræfte, at opskrifterne gør præcis det, jeg forventer? 🤔\"\n",
|
|
"\n",
|
|
"Det er en fantastisk tanke! Ser du, når din opskrift er defineret, kan du estimere de parametre, der kræves for faktisk at forbehandle dataene, og derefter udtrække de forarbejdede data. Normalt behøver du ikke gøre dette, når du bruger Tidymodels (vi ser den normale konvention om et øjeblik -> `workflows`), men det kan være nyttigt, hvis du vil lave en slags sanity check for at bekræfte, at opskrifterne gør, hvad du forventer.\n",
|
|
"\n",
|
|
"Til det skal du bruge to ekstra verber: `prep()` og `bake()`, og som altid hjælper vores små R-venner fra [`Allison Horst`](https://github.com/allisonhorst/stats-illustrations) dig med at forstå dette bedre!\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/recipes.png\"\n",
|
|
" width=\"550\"/>\n",
|
|
" <figcaption>Kunstværk af @allison_horst</figcaption>\n"
|
|
],
|
|
"metadata": {
|
|
"id": "KEiO0v7kuC9O"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"[`prep()`](https://recipes.tidymodels.org/reference/prep.html): estimerer de nødvendige parametre fra et træningssæt, som senere kan anvendes på andre datasæt. For eksempel, for en given predictor-kolonne, hvilken observation vil blive tildelt heltal 0, 1, 2 osv.\n",
|
|
"\n",
|
|
"[`bake()`](https://recipes.tidymodels.org/reference/bake.html): tager en forberedt opskrift og anvender operationerne på ethvert datasæt.\n",
|
|
"\n",
|
|
"Når det er sagt, lad os forberede og anvende vores opskrifter for virkelig at bekræfte, at under overfladen vil predictor-kolonnerne først blive kodet, før en model tilpasses.\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": [
|
|
"Woo-hoo!🥳 De behandlede data `baked_pumpkins` har alle sine prædiktorer kodet, hvilket bekræfter, at de foruddefinerede forbehandlingsskridt i vores opskrift fungerer som forventet. Dette gør det sværere for dig at læse, men meget mere forståeligt for Tidymodels! Tag dig tid til at finde ud af, hvilken observation der er blevet kortlagt til et tilsvarende heltal.\n",
|
|
"\n",
|
|
"Det er også værd at nævne, at `baked_pumpkins` er en data frame, som vi kan udføre beregninger på.\n",
|
|
"\n",
|
|
"For eksempel, lad os prøve at finde en god korrelation mellem to punkter i dine data for potentielt at bygge en god prædiktiv model. Vi bruger funktionen `cor()` til dette. Skriv `?cor()` for at finde ud af mere om funktionen.\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": [
|
|
"Som det viser sig, er der kun en svag sammenhæng mellem By og Pris. Derimod er der en lidt bedre sammenhæng mellem Pakke og dens Pris. Det giver mening, ikke? Normalt, jo større produktkassen er, desto højere er prisen.\n",
|
|
"\n",
|
|
"Mens vi er i gang, lad os også prøve at visualisere en korrelationsmatrix for alle kolonnerne ved hjælp af `corrplot`-pakken.\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": [
|
|
"🤩🤩 Meget bedre.\n",
|
|
"\n",
|
|
"Et godt spørgsmål at stille til disse data kunne være: '`Hvilken pris kan jeg forvente for en given græskarpakke?`' Lad os komme i gang!\n",
|
|
"\n",
|
|
"> Note: Når du **`bake()`** den forberedte opskrift **`pumpkins_prep`** med **`new_data = NULL`**, udtrækker du de behandlede (dvs. kodede) træningsdata. Hvis du havde et andet datasæt, for eksempel et testdatasæt, og gerne ville se, hvordan en opskrift ville forbehandle det, skulle du blot bage **`pumpkins_prep`** med **`new_data = test_set`**\n",
|
|
"\n",
|
|
"## 4. Byg en lineær regressionsmodel\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/linear-polynomial.png\"\n",
|
|
" width=\"800\"/>\n",
|
|
" <figcaption>Infografik af Dasani Madipalli</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!--{width=\"800\"}-->\n"
|
|
],
|
|
"metadata": {
|
|
"id": "YqXjLuWavNxW"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Nu hvor vi har opbygget en opskrift og faktisk bekræftet, at dataene vil blive forbehandlet korrekt, lad os nu opbygge en regressionsmodel for at besvare spørgsmålet: `Hvilken pris kan jeg forvente for en given græskarpakke?`\n",
|
|
"\n",
|
|
"#### Træn en lineær regressionsmodel ved hjælp af træningssættet\n",
|
|
"\n",
|
|
"Som du måske allerede har regnet ud, er kolonnen *price* den `afhængige` variabel, mens kolonnen *package* er den `uafhængige` variabel.\n",
|
|
"\n",
|
|
"For at gøre dette vil vi først opdele dataene, så 80% går til træningssættet og 20% til test-sættet, derefter definere en opskrift, der vil kode den uafhængige variabel som et sæt heltal, og derefter opbygge en modelspecifikation. Vi vil ikke forberede og bage vores opskrift, da vi allerede ved, at den vil forbehandle dataene som forventet.\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": [
|
|
"Godt klaret! Nu hvor vi har en opskrift og en modelspecifikation, skal vi finde en måde at samle dem i et objekt, der først forbehandler dataene (prep+bake bag kulisserne), tilpasser modellen til de forbehandlede data og også giver mulighed for potentielle efterbehandlingsaktiviteter. Hvordan lyder det for din ro i sindet!🤩\n",
|
|
"\n",
|
|
"I Tidymodels kaldes dette praktiske objekt en [`workflow`](https://workflows.tidymodels.org/) og indeholder bekvemt dine modelkomponenter! Det er det, vi ville kalde *pipelines* i *Python*.\n",
|
|
"\n",
|
|
"Så lad os samle det hele i en 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": [
|
|
"👌 Som en ekstra bonus kan en arbejdsproces tilpasses/trænes på næsten samme måde som en model kan.\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": [
|
|
"Fra modeloutputtet kan vi se de koefficienter, der blev lært under træningen. De repræsenterer koefficienterne for den bedste tilpasningslinje, som giver os den laveste samlede fejl mellem den faktiske og den forudsagte variabel.\n",
|
|
"\n",
|
|
"#### Evaluér modellens præstation ved hjælp af testdatasættet\n",
|
|
"\n",
|
|
"Det er tid til at se, hvordan modellen klarede sig 📏! Hvordan gør vi det?\n",
|
|
"\n",
|
|
"Nu hvor vi har trænet modellen, kan vi bruge den til at lave forudsigelser for test_sættet ved hjælp af `parsnip::predict()`. Derefter kan vi sammenligne disse forudsigelser med de faktiske mærkeværdier for at vurdere, hvor godt (eller dårligt!) modellen fungerer.\n",
|
|
"\n",
|
|
"Lad os starte med at lave forudsigelser for testdatasættet og derefter binde kolonnerne til testdatasættet.\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": [
|
|
"Ja, du har lige trænet en model og brugt den til at lave forudsigelser!🔮 Er den god? Lad os evaluere modellens præstation!\n",
|
|
"\n",
|
|
"I Tidymodels gør vi dette ved hjælp af `yardstick::metrics()`! For lineær regression fokuserer vi på følgende metrikker:\n",
|
|
"\n",
|
|
"- `Root Mean Square Error (RMSE)`: Kvadratroden af [MSE](https://en.wikipedia.org/wiki/Mean_squared_error). Dette giver en absolut metrik i samme enhed som labelen (i dette tilfælde prisen på et græskar). Jo mindre værdien er, desto bedre er modellen (forenklet sagt repræsenterer det den gennemsnitlige pris, som forudsigelserne er forkerte med!)\n",
|
|
"\n",
|
|
"- `Coefficient of Determination (normalt kendt som R-squared eller R2)`: En relativ metrik, hvor en højere værdi betyder en bedre modeltilpasning. Grundlæggende repræsenterer denne metrik, hvor meget af variansen mellem de forudsagte og faktiske labelværdier modellen er i stand til at forklare.\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": [
|
|
"Der går modelpræstationen. Lad os se, om vi kan få en bedre indikation ved at visualisere et spredningsdiagram af pakken og prisen og derefter bruge de forudsigelser, der er lavet, til at overlejre en linje med bedste tilpasning.\n",
|
|
"\n",
|
|
"Det betyder, at vi skal forberede og bearbejde testdatasættet for at kode pakke-kolonnen og derefter binde dette til de forudsigelser, som vores model har lavet.\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": [
|
|
"Som du kan se, generaliserer lineær regressionsmodellen ikke særlig godt forholdet mellem en pakke og dens tilsvarende pris.\n",
|
|
"\n",
|
|
"🎃 Tillykke, du har lige skabt en model, der kan hjælpe med at forudsige prisen på nogle få græskarsorter. Din græskarhave til højtiden bliver smuk. Men du kan sandsynligvis lave en bedre model!\n",
|
|
"\n",
|
|
"## 5. Byg en polynomisk regressionsmodel\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/linear-polynomial.png\"\n",
|
|
" width=\"800\"/>\n",
|
|
" <figcaption>Infografik af Dasani Madipalli</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!--{width=\"800\"}-->\n"
|
|
],
|
|
"metadata": {
|
|
"id": "HOCqJXLTwtWI"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Nogle gange har vores data måske ikke en lineær sammenhæng, men vi vil stadig gerne forudsige et resultat. Polynomisk regression kan hjælpe os med at lave forudsigelser for mere komplekse ikke-lineære sammenhænge.\n",
|
|
"\n",
|
|
"Tag for eksempel forholdet mellem pakke og pris i vores græskar-datasæt. Selvom der nogle gange er en lineær sammenhæng mellem variablerne - jo større græskar i volumen, jo højere pris - kan disse sammenhænge nogle gange ikke afbildes som et plan eller en lige linje.\n",
|
|
"\n",
|
|
"> ✅ Her er [nogle flere eksempler](https://online.stat.psu.edu/stat501/lesson/9/9.8) på data, der kunne bruge polynomisk regression\n",
|
|
">\n",
|
|
"> Tag et nyt kig på forholdet mellem Sort og Pris i det tidligere plot. Ser dette scatterplot ud som om det nødvendigvis skal analyseres med en lige linje? Måske ikke. I dette tilfælde kan du prøve polynomisk regression.\n",
|
|
">\n",
|
|
"> ✅ Polynomier er matematiske udtryk, der kan bestå af en eller flere variabler og koefficienter\n",
|
|
"\n",
|
|
"#### Træn en polynomisk regressionsmodel ved hjælp af træningssættet\n",
|
|
"\n",
|
|
"Polynomisk regression skaber en *kurvet linje* for bedre at tilpasse sig ikke-lineære data.\n",
|
|
"\n",
|
|
"Lad os se, om en polynomisk model vil klare sig bedre til at lave forudsigelser. Vi følger en nogenlunde lignende procedure som før:\n",
|
|
"\n",
|
|
"- Opret en opskrift, der angiver de forbehandlingsskridt, der skal udføres på vores data for at gøre dem klar til modellering, dvs.: kodning af prædiktorer og beregning af polynomier af grad *n*\n",
|
|
"\n",
|
|
"- Byg en modelspecifikation\n",
|
|
"\n",
|
|
"- Kombiner opskriften og modelspecifikationen i en arbejdsgang\n",
|
|
"\n",
|
|
"- Opret en model ved at tilpasse arbejdsgangen\n",
|
|
"\n",
|
|
"- Evaluer, hvor godt modellen klarer sig på testdataene\n",
|
|
"\n",
|
|
"Lad os komme i gang!\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": [
|
|
"#### Evaluér modellens ydeevne\n",
|
|
"\n",
|
|
"👏👏Du har bygget en polynomisk model, lad os lave forudsigelser på testdatasættet!\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": [
|
|
"Woo-hoo, lad os evaluere, hvordan modellen klarede sig på test_sættet ved hjælp af `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": [
|
|
"🤩🤩 Meget bedre ydeevne.\n",
|
|
"\n",
|
|
"`rmse` faldt fra omkring 7 til omkring 3, hvilket indikerer en reduceret fejl mellem den faktiske pris og den forudsagte pris. Du kan *løst* tolke dette som, at forkerte forudsigelser i gennemsnit er omkring \\$3 forkerte. `rsq` steg fra omkring 0,4 til 0,8.\n",
|
|
"\n",
|
|
"Alle disse målinger viser, at den polynomiske model klarer sig langt bedre end den lineære model. Godt arbejde!\n",
|
|
"\n",
|
|
"Lad os se, om vi kan visualisere dette!\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": [
|
|
"Du kan se en kurvet linje, der passer bedre til dine data! 🤩\n",
|
|
"\n",
|
|
"Du kan gøre dette endnu mere glidende ved at give en polynomisk formel til `geom_smooth` sådan her:\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": [
|
|
"Ligesom en glat kurve!🤩\n",
|
|
"\n",
|
|
"Sådan laver du en ny forudsigelse:\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": [
|
|
"Forudsigelsen med `polynomial model` giver mening, givet scatterplots af `price` og `package`! Og hvis dette er en bedre model end den tidligere, når man ser på de samme data, skal du budgettere for disse dyrere græskar!\n",
|
|
"\n",
|
|
"🏆 Godt klaret! Du har oprettet to regressionsmodeller i én lektion. I den sidste sektion om regression vil du lære om logistisk regression for at bestemme kategorier.\n",
|
|
"\n",
|
|
"## **🚀Udfordring**\n",
|
|
"\n",
|
|
"Test flere forskellige variabler i denne notebook for at se, hvordan korrelation svarer til modelnøjagtighed.\n",
|
|
"\n",
|
|
"## [**Quiz efter lektionen**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/14/)\n",
|
|
"\n",
|
|
"## **Gennemgang & Selvstudie**\n",
|
|
"\n",
|
|
"I denne lektion lærte vi om Lineær Regression. Der findes andre vigtige typer af Regression. Læs om Stepwise, Ridge, Lasso og Elasticnet teknikker. Et godt kursus at studere for at lære mere er [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning).\n",
|
|
"\n",
|
|
"Hvis du vil lære mere om, hvordan du bruger det fantastiske Tidymodels framework, kan du tjekke følgende ressourcer:\n",
|
|
"\n",
|
|
"- Tidymodels hjemmeside: [Kom i gang med Tidymodels](https://www.tidymodels.org/start/)\n",
|
|
"\n",
|
|
"- Max Kuhn og Julia Silge, [*Tidy Modeling with R*](https://www.tmwr.org/)*.*\n",
|
|
"\n",
|
|
"###### **TAK TIL:**\n",
|
|
"\n",
|
|
"[Allison Horst](https://twitter.com/allison_horst?lang=en) for at skabe de fantastiske illustrationer, der gør R mere indbydende og engagerende. Find flere illustrationer i hendes [galleri](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**Ansvarsfraskrivelse**: \nDette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.\n"
|
|
]
|
|
}
|
|
]
|
|
} |