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

1084 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-06T11:38:43+00:00",
"source_file": "2-Regression/3-Linear/solution/R/lesson_3-R.ipynb",
"language_code": "no"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "EgQw8osnsUV-"
}
},
{
"cell_type": "markdown",
"source": [
"## Lineær og Polynomisk Regresjon for Prissetting av Gresskar - Leksjon 3\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Infografikk av Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"#### Introduksjon\n",
"\n",
"Så langt har du utforsket hva regresjon er ved hjelp av eksempeldata hentet fra gresskarprissettingsdatasettet som vi vil bruke gjennom denne leksjonen. Du har også visualisert det ved hjelp av `ggplot2`.💪\n",
"\n",
"Nå er du klar til å dykke dypere inn i regresjon for maskinlæring. I denne leksjonen vil du lære mer om to typer regresjon: *grunnleggende lineær regresjon* og *polynomisk regresjon*, sammen med noe av matematikken som ligger til grunn for disse teknikkene.\n",
"\n",
"> Gjennom hele dette kurset antar vi minimal kunnskap om matematikk, og vi søker å gjøre det tilgjengelig for studenter fra andre felt, så se etter notater, 🧮 utrop, diagrammer og andre læringsverktøy som kan hjelpe med forståelsen.\n",
"\n",
"#### Forberedelse\n",
"\n",
"Som en påminnelse, du laster inn disse dataene for å stille spørsmål til dem.\n",
"\n",
"- Når er det beste tidspunktet å kjøpe gresskar?\n",
"\n",
"- Hva kan jeg forvente å betale for en kasse med miniatyrgresskar?\n",
"\n",
"- Bør jeg kjøpe dem i halv-bushel kurver eller i 1 1/9 bushel bokser? La oss fortsette å grave i disse dataene.\n",
"\n",
"I forrige leksjon opprettet du en `tibble` (en moderne nytenkning av dataframes) og fylte den med en del av det opprinnelige datasettet, standardiserte prissettingen etter bushel. Ved å gjøre det, var du imidlertid bare i stand til å samle rundt 400 datapunkter og kun for høstmånedene. Kanskje vi kan få litt mer detaljert informasjon om naturen til dataene ved å rense dem mer? Vi får se... 🕵️‍♀️\n",
"\n",
"For denne oppgaven trenger vi følgende pakker:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) er en [samling av R-pakker](https://www.tidyverse.org/packages) designet for å gjøre dataanalyse raskere, enklere og morsommere!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) rammeverket er en [samling av pakker](https://www.tidymodels.org/packages/) for modellering og maskinlæring.\n",
"\n",
"- `janitor`: [janitor-pakken](https://github.com/sfirke/janitor) gir enkle verktøy for å undersøke og rense skitne data.\n",
"\n",
"- `corrplot`: [corrplot-pakken](https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html) gir et visuelt utforskingsverktøy for korrelasjonsmatriser som støtter automatisk variabelreorganisering for å hjelpe med å oppdage skjulte mønstre blant variabler.\n",
"\n",
"Du kan installere dem slik:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"corrplot\"))`\n",
"\n",
"Skriptet nedenfor sjekker om du har de nødvendige pakkene for å fullføre dette modulen og installerer dem for deg 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 laste inn disse fantastiske pakkene og gjøre dem tilgjengelige i vår nåværende R-sesjon. (Dette er kun for illustrasjon, `pacman::p_load()` har allerede gjort dette for deg)\n",
"\n",
"## 1. En lineær regresjonslinje\n",
"\n",
"Som du lærte i leksjon 1, er målet med en lineær regresjonsøvelse å kunne tegne en *linje* *for* *beste tilpasning* for å:\n",
"\n",
"- **Vise variabelsammenhenger**. Vise sammenhengen mellom variabler.\n",
"\n",
"- **Gjøre prediksjoner**. Gjøre nøyaktige prediksjoner om hvor et nytt datapunkt vil falle i forhold til den linjen.\n",
"\n",
"For å tegne denne typen linje bruker vi en statistisk teknikk kalt **Minste kvadraters regresjon**. Begrepet `minste kvadrater` betyr at alle datapunktene rundt regresjonslinjen kvadreres og deretter summeres. Ideelt sett er den endelige summen så liten som mulig, fordi vi ønsker et lavt antall feil, eller `minste kvadrater`. Som sådan er linjen for beste tilpasning den linjen som gir oss den laveste verdien for summen av de kvadrerte feilene - derav navnet *minste kvadraters regresjon*.\n",
"\n",
"Vi gjør dette fordi vi ønsker å modellere en linje som har den minste kumulative avstanden fra alle våre datapunkter. Vi kvadrerer også termene før vi summerer dem, siden vi er opptatt av størrelsen snarere enn retningen.\n",
"\n",
"> **🧮 Vis meg matematikken**\n",
">\n",
"> Denne linjen, kalt *linjen for beste tilpasning*, kan uttrykkes med [en ligning](https://en.wikipedia.org/wiki/Simple_linear_regression):\n",
">\n",
"> Y = a + bX\n",
">\n",
"> `X` er '`forklaringsvariabelen` eller `prediktoren`'. `Y` er '`avhengig variabel` eller `utfallet`'. Stigningen på linjen er `b`, og `a` er skjæringspunktet med y-aksen, som refererer til verdien av `Y` når `X = 0`.\n",
">\n",
"\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/slope.png \"stigning = $y/x$\")\n",
" Infografikk av Jen Looper\n",
">\n",
"> Først, beregn stigningen `b`.\n",
">\n",
"> Med andre ord, og med henvisning til vårt opprinnelige spørsmål om gresskar-data: \"forutsi prisen på et gresskar per skjeppe etter måned\", vil `X` referere til prisen og `Y` referere til salgsdatoen.\n",
">\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/calculation.png)\n",
" Infografikk av Jen Looper\n",
"> \n",
"> Beregn verdien av Y. Hvis du betaler rundt \\$4, må det være april!\n",
">\n",
"> Matematikk som beregner linjen må demonstrere stigningen på linjen, som også avhenger av skjæringspunktet, eller hvor `Y` befinner seg når `X = 0`.\n",
">\n",
"> Du kan se metoden for beregning av disse verdiene på nettstedet [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html). Besøk også [denne kalkulatoren for minste kvadrater](https://www.mathsisfun.com/data/least-squares-calculator.html) for å se hvordan verdiene påvirker linjen.\n",
"\n",
"Ikke så skummelt, sant? 🤓\n",
"\n",
"#### Korrelasjon\n",
"\n",
"Et annet begrep å forstå er **Korrelasjonskoeffisienten** mellom gitte X- og Y-variabler. Ved hjelp av et spredningsdiagram kan du raskt visualisere denne koeffisienten. Et diagram med datapunkter som er pent spredt i en linje har høy korrelasjon, mens et diagram med datapunkter spredt overalt mellom X og Y har lav korrelasjon.\n",
"\n",
"En god lineær regresjonsmodell vil være en som har en høy (nærmere 1 enn 0) korrelasjonskoeffisient ved bruk av metoden for minste kvadraters regresjon med en regresjonslinje.\n"
],
"metadata": {
"id": "cdX5FRpvsoP5"
}
},
{
"cell_type": "markdown",
"source": [
"## **2. En dans med data: opprette en data frame som skal brukes til modellering**\n",
"\n",
"<p >\n",
" <img src=\"../../images/janitor.jpg\"\n",
" width=\"700\"/>\n",
" <figcaption>Kunstverk av @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![Kunstverk av \\@allison_horst](../../../../../../2-Regression/3-Linear/images/janitor.jpg){width=\"700\"}-->\n"
],
"metadata": {
"id": "WdUKXk7Bs8-V"
}
},
{
"cell_type": "markdown",
"source": [
"Last inn nødvendige biblioteker og datasett. Konverter dataene til en data frame som inneholder et utvalg av dataene:\n",
"\n",
"- Ta kun med gresskar som er priset per skjeppe\n",
"\n",
"- Konverter datoen til en måned\n",
"\n",
"- Beregn prisen som et gjennomsnitt av høy og lav pris\n",
"\n",
"- Konverter prisen slik at den reflekterer prisingen per skjeppekvantitet\n",
"\n",
"> Vi dekket disse stegene i [forrige leksjon](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, la oss utforske [`janitor-pakken`](../../../../../../2-Regression/3-Linear/solution/R/github.com/sfirke/janitor) som tilbyr enkle funksjoner for å undersøke og rense uryddige data. For eksempel, la oss se på kolonnenavnene for dataene våre:\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 gjøre det bedre. La oss gjøre disse kolonnenavnene `friendR` ved å konvertere dem til [snake_case](https://en.wikipedia.org/wiki/Snake_case)-konvensjonen ved hjelp av `janitor::clean_names`. For å finne ut mer om denne funksjonen: `?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": [
"Mye ryddigere 🧹! Nå, en dans med dataene ved hjelp av `dplyr`, som i forrige leksjon! 💃\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": [
"Bra jobba!👌 Du har nå et rent og ryddig datasett som du kan bruke til å bygge din nye regresjonsmodell!\n",
"\n",
"Hva med et spredningsdiagram?\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 minner oss om at vi kun har månedsdata fra august til desember. Vi trenger sannsynligvis mer data for å kunne trekke konklusjoner på en lineær måte.\n",
"\n",
"La oss ta en titt på modelldataene våre igjen:\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": [
"Hva om vi ønsket å forutsi `price` på et gresskar basert på kolonnene `city` eller `package`, som er av typen karakter? Eller enda enklere, hvordan kunne vi finne korrelasjonen (som krever at begge inputene er numeriske) mellom for eksempel `package` og `price`? 🤷🤷\n",
"\n",
"Maskinlæringsmodeller fungerer best med numeriske egenskaper i stedet for tekstverdier, så du må vanligvis konvertere kategoriske egenskaper til numeriske representasjoner.\n",
"\n",
"Dette betyr at vi må finne en måte å omforme våre prediktorer på for å gjøre dem enklere for en modell å bruke effektivt, en prosess kjent som `feature engineering`.\n"
],
"metadata": {
"id": "7hsHoxsStyjJ"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Forbehandling av data for modellering med oppskrifter 👩‍🍳👨‍🍳\n",
"\n",
"Aktiviteter som omformaterer prediktorverdier for å gjøre dem enklere for en modell å bruke effektivt, har blitt kalt `feature engineering`.\n",
"\n",
"Ulike modeller har ulike krav til forbehandling. For eksempel krever minste kvadraters metode `koding av kategoriske variabler` som måned, sort og bynavn. Dette innebærer ganske enkelt å `oversette` en kolonne med `kategoriske verdier` til en eller flere `numeriske kolonner` som erstatter den opprinnelige.\n",
"\n",
"For eksempel, anta at dataene dine inkluderer følgende kategoriske variabel:\n",
"\n",
"| by |\n",
"|:-------:|\n",
"| Denver |\n",
"| Nairobi |\n",
"| Tokyo |\n",
"\n",
"Du kan bruke *ordinal koding* for å erstatte hver kategori med en unik heltallsverdi, slik som dette:\n",
"\n",
"| by |\n",
"|:---:|\n",
"| 0 |\n",
"| 1 |\n",
"| 2 |\n",
"\n",
"Og det er akkurat det vi skal gjøre med dataene våre!\n",
"\n",
"I denne delen skal vi utforske et annet fantastisk Tidymodels-pakke: [recipes](https://tidymodels.github.io/recipes/) - som er designet for å hjelpe deg med å forbehandle dataene dine **før** du trener modellen din. I kjernen er en oppskrift et objekt som definerer hvilke steg som skal brukes på et datasett for å gjøre det klart for modellering.\n",
"\n",
"La oss nå lage en oppskrift som forbereder dataene våre for modellering ved å erstatte en unik heltallsverdi for alle observasjonene i prediktorkolonnene:\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 nettopp laget vår første oppskrift som spesifiserer et utfall (pris) og tilhørende prediktorer, og som sørger for at alle prediktorkolonnene blir kodet som et sett med heltall 🙌! La oss raskt bryte det ned:\n",
"\n",
"- Kallet til `recipe()` med en formel forteller oppskriften *rollene* til variablene ved å bruke `new_pumpkins`-dataene som referanse. For eksempel har `price`-kolonnen blitt tildelt rollen som `outcome`, mens resten av kolonnene har blitt tildelt rollen som `predictor`.\n",
"\n",
"- `step_integer(all_predictors(), zero_based = TRUE)` spesifiserer at alle prediktorene skal konverteres til et sett med heltall, der nummereringen starter på 0.\n",
"\n",
"Vi er sikre på at du kanskje tenker noe sånt som: \"Dette er så kult!! Men hva om jeg trenger å bekrefte at oppskriftene gjør akkurat det jeg forventer? 🤔\"\n",
"\n",
"Det er en fantastisk tanke! Du skjønner, når oppskriften din er definert, kan du estimere parameterne som kreves for faktisk å forhåndsbehandle dataene, og deretter trekke ut de bearbeidede dataene. Du trenger vanligvis ikke å gjøre dette når du bruker Tidymodels (vi skal snart se den normale konvensjonen -\\> `workflows`), men det kan være nyttig når du vil gjøre en slags kontroll for å bekrefte at oppskriftene gjør det du forventer.\n",
"\n",
"For dette trenger du to flere verb: `prep()` og `bake()`, og som alltid hjelper våre små R-venner fra [`Allison Horst`](https://github.com/allisonhorst/stats-illustrations) deg med å forstå dette bedre!\n",
"\n",
"<p >\n",
" <img src=\"../../images/recipes.png\"\n",
" width=\"550\"/>\n",
" <figcaption>Kunstverk av @allison_horst</figcaption>\n"
],
"metadata": {
"id": "KEiO0v7kuC9O"
}
},
{
"cell_type": "markdown",
"source": [
"[`prep()`](https://recipes.tidymodels.org/reference/prep.html): estimerer de nødvendige parameterne fra et treningssett som senere kan brukes på andre datasett. For eksempel, for en gitt prediktorkolonne, hvilken observasjon vil bli tildelt heltall 0, 1, 2 osv.\n",
"\n",
"[`bake()`](https://recipes.tidymodels.org/reference/bake.html): tar en ferdigbehandlet oppskrift og utfører operasjonene på et hvilket som helst datasett.\n",
"\n",
"Med det sagt, la oss forberede og bruke oppskriftene våre for virkelig å bekrefte at prediktorkolonnene under panseret først vil bli kodet før en modell 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 bearbeidede dataene `baked_pumpkins` har alle sine prediktorer kodet, noe som bekrefter at forhåndsprosesseringsstegene definert som vår oppskrift fungerer som forventet. Dette gjør det vanskeligere for deg å lese, men mye mer forståelig for Tidymodels! Ta deg tid til å finne ut hvilken observasjon som har blitt tilordnet et tilsvarende heltall.\n",
"\n",
"Det er også verdt å nevne at `baked_pumpkins` er en data frame som vi kan utføre beregninger på.\n",
"\n",
"For eksempel, la oss prøve å finne en god korrelasjon mellom to punkter i dataene dine for potensielt å bygge en god prediktiv modell. Vi bruker funksjonen `cor()` for å gjøre dette. Skriv `?cor()` for å finne ut mer om funksjonen.\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 seg, er det bare en svak korrelasjon mellom By og Pris. Men det er en litt bedre korrelasjon mellom Pakke og dens Pris. Det gir mening, ikke sant? Vanligvis, jo større produktboksen er, desto høyere er prisen.\n",
"\n",
"Mens vi er i gang, la oss også prøve å visualisere en korrelasjonsmatrise for alle kolonnene ved hjelp av `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": [
"🤩🤩 Mye bedre.\n",
"\n",
"Et godt spørsmål å stille nå vil være: '`Hvilken pris kan jeg forvente for en gitt gresskarpakke?`' La oss sette i gang!\n",
"\n",
"> Merk: Når du **`bake()`** den forberedte oppskriften **`pumpkins_prep`** med **`new_data = NULL`**, henter du ut de bearbeidede (dvs. kodede) treningsdataene. Hvis du hadde et annet datasett, for eksempel et testsett, og ønsket å se hvordan en oppskrift ville forhåndsbehandle det, ville du ganske enkelt bake **`pumpkins_prep`** med **`new_data = test_set`**\n",
"\n",
"## 4. Bygg en lineær regresjonsmodell\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Infografikk av Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![Infografikk av Dasani Madipalli](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n"
],
"metadata": {
"id": "YqXjLuWavNxW"
}
},
{
"cell_type": "markdown",
"source": [
"Nå som vi har laget en oppskrift og faktisk bekreftet at dataene vil bli forhåndsbehandlet riktig, la oss nå bygge en regresjonsmodell for å svare på spørsmålet: `Hvilken pris kan jeg forvente for en gitt gresskarpakke?`\n",
"\n",
"#### Tren en lineær regresjonsmodell ved hjelp av treningssettet\n",
"\n",
"Som du kanskje allerede har forstått, er kolonnen *price* den `avhengige` variabelen, mens kolonnen *package* er den `uavhengige` variabelen.\n",
"\n",
"For å gjøre dette, vil vi først dele opp dataene slik at 80% går til treningssettet og 20% til testsettet, deretter definere en oppskrift som vil kode den uavhengige variabelen til et sett med heltall, og deretter bygge en modellspesifikasjon. Vi vil ikke forberede og bake oppskriften vår siden vi allerede vet at den vil forhåndsbehandle 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": [
"Bra jobbet! Nå som vi har en oppskrift og en modellspesifikasjon, må vi finne en måte å samle dem sammen i et objekt som først vil forhåndsbehandle dataene (prep+bake i bakgrunnen), tilpasse modellen til de forhåndsbehandlede dataene, og også tillate mulige etterbehandlingsaktiviteter. Hvordan er det for din sinnsro!🤩\n",
"\n",
"I Tidymodels kalles dette praktiske objektet en [`workflow`](https://workflows.tidymodels.org/) og holder praktisk dine modelleringskomponenter! Dette er det vi ville kalt *pipelines* i *Python*.\n",
"\n",
"Så la oss samle alt 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": [
"I tillegg kan en arbeidsflyt tilpasses/trenes på samme måte som en modell 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 modellens output kan vi se koeffisientene som ble lært under treningen. De representerer koeffisientene for den beste tilpassede linjen som gir oss den laveste totale feilen mellom den faktiske og den predikerte variabelen.\n",
"\n",
"#### Evaluere modellens ytelse ved bruk av testsettet\n",
"\n",
"Det er på tide å se hvordan modellen presterte 📏! Hvordan gjør vi dette?\n",
"\n",
"Nå som vi har trent modellen, kan vi bruke den til å lage prediksjoner for test_set ved hjelp av `parsnip::predict()`. Deretter kan vi sammenligne disse prediksjonene med de faktiske verdiene for å evaluere hvor godt (eller dårlig!) modellen fungerer.\n",
"\n",
"La oss starte med å lage prediksjoner for testsettet og deretter binde kolonnene til testsettet.\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 nettopp trent en modell og brukt den til å gjøre prediksjoner! 🔮 Er den noe bra? La oss evaluere modellens ytelse!\n",
"\n",
"I Tidymodels gjør vi dette ved hjelp av `yardstick::metrics()`! For lineær regresjon, la oss fokusere på følgende metrikker:\n",
"\n",
"- `Root Mean Square Error (RMSE)`: Kvadratroten av [MSE](https://en.wikipedia.org/wiki/Mean_squared_error). Dette gir en absolutt metrikk i samme enhet som målet (i dette tilfellet prisen på et gresskar). Jo mindre verdien er, desto bedre er modellen (enkelt sagt representerer det gjennomsnittsprisen modellen tar feil med!).\n",
"\n",
"- `Coefficient of Determination (vanligvis kjent som R-squared eller R2)`: En relativ metrikk der høyere verdi betyr bedre tilpasning av modellen. I hovedsak representerer denne metrikken hvor mye av variasjonen mellom de predikerte og faktiske måleverdiene modellen klarer å 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 modellens ytelse. La oss se om vi kan få en bedre indikasjon ved å visualisere et spredningsdiagram av pakken og prisen, og deretter bruke de prediksjonene som er gjort til å legge over en linje for beste tilpasning.\n",
"\n",
"Dette betyr at vi må forberede og bearbeide testsettet for å kode pakke-kolonnen, og deretter binde dette til prediksjonene som er gjort av modellen vår.\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": [
"Flott! Som du kan se, generaliserer ikke lineær regresjonsmodellen særlig godt forholdet mellom en pakke og dens tilsvarende pris.\n",
"\n",
"🎃 Gratulerer, du har nettopp laget en modell som kan hjelpe med å forutsi prisen på noen varianter av gresskar. Din gresskarhage til høytiden kommer til å bli fantastisk. Men du kan sannsynligvis lage en bedre modell!\n",
"\n",
"## 5. Bygg en polynomisk regresjonsmodell\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>Infografikk av Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![Infografikk av Dasani Madipalli](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n"
],
"metadata": {
"id": "HOCqJXLTwtWI"
}
},
{
"cell_type": "markdown",
"source": [
"Noen ganger har ikke dataene våre en lineær sammenheng, men vi ønsker likevel å forutsi et utfall. Polynomisk regresjon kan hjelpe oss med å lage prediksjoner for mer komplekse ikke-lineære sammenhenger.\n",
"\n",
"Ta for eksempel forholdet mellom pakke og pris i vårt gresskar-datasett. Selv om det noen ganger er en lineær sammenheng mellom variabler jo større gresskaret er i volum, desto høyere pris kan det hende at disse sammenhengene ikke kan plottes som et plan eller en rett linje.\n",
"\n",
"> ✅ Her er [noen flere eksempler](https://online.stat.psu.edu/stat501/lesson/9/9.8) på data som kan bruke polynomisk regresjon\n",
">\n",
"> Ta en ny titt på forholdet mellom Sort til Pris i det forrige plottet. Virker det som om dette spredningsdiagrammet nødvendigvis bør analyseres med en rett linje? Kanskje ikke. I dette tilfellet kan du prøve polynomisk regresjon.\n",
">\n",
"> ✅ Polynom er matematiske uttrykk som kan bestå av én eller flere variabler og koeffisienter\n",
"\n",
"#### Tren en polynomisk regresjonsmodell ved hjelp av treningssettet\n",
"\n",
"Polynomisk regresjon lager en *kurvet linje* for bedre å tilpasse ikke-lineære data.\n",
"\n",
"La oss se om en polynomisk modell vil prestere bedre i å lage prediksjoner. Vi følger en prosedyre som ligner på den vi brukte tidligere:\n",
"\n",
"- Lag en oppskrift som spesifiserer forbehandlingsstegene som skal utføres på dataene våre for å gjøre dem klare for modellering, dvs.: koding av prediktorer og beregning av polynomer av grad *n*\n",
"\n",
"- Bygg en modellspecifikasjon\n",
"\n",
"- Kombiner oppskriften og modellspecifikasjonen i en arbeidsflyt\n",
"\n",
"- Lag en modell ved å tilpasse arbeidsflyten\n",
"\n",
"- Evaluer hvor godt modellen presterer på testdataene\n",
"\n",
"La oss sette 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": [
"#### Evaluere modellens ytelse\n",
"\n",
"👏👏Du har laget en polynommodell, la oss gjøre spådommer på testsettet!\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, la oss evaluere hvordan modellen presterte på test_set ved å bruke `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": [
"🤩🤩 Mye bedre ytelse.\n",
"\n",
"`rmse` gikk ned fra omtrent 7 til omtrent 3, noe som indikerer en redusert feil mellom den faktiske prisen og den predikerte prisen. Du kan *løst* tolke dette som at feilaktige prediksjoner i gjennomsnitt er feil med rundt 3 dollar. `rsq` økte fra omtrent 0,4 til 0,8.\n",
"\n",
"Alle disse målene viser at den polynomiske modellen fungerer mye bedre enn den lineære modellen. Bra jobbet!\n",
"\n",
"La oss 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 som passer bedre til dataene dine! 🤩\n",
"\n",
"Du kan gjøre dette enda jevnere ved å sende en polynomformel til `geom_smooth` slik som dette:\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": [
"Akkurat som en jevn kurve!🤩\n",
"\n",
"Slik kan du lage en ny prediksjon:\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": [
"Prediksjonen fra `polynomial model` gir mening, gitt spredningsdiagrammene for `price` og `package`! Og hvis dette er en bedre modell enn den forrige, basert på de samme dataene, må du planlegge for disse dyrere gresskarene!\n",
"\n",
"🏆 Bra jobbet! Du har laget to regresjonsmodeller i én leksjon. I den siste delen om regresjon vil du lære om logistisk regresjon for å bestemme kategorier.\n",
"\n",
"## **🚀Utfordring**\n",
"\n",
"Test flere forskjellige variabler i denne notatboken for å se hvordan korrelasjon samsvarer med modellens nøyaktighet.\n",
"\n",
"## [**Quiz etter leksjonen**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/14/)\n",
"\n",
"## **Gjennomgang & Selvstudium**\n",
"\n",
"I denne leksjonen lærte vi om Lineær Regresjon. Det finnes andre viktige typer regresjon. Les om Stepwise, Ridge, Lasso og Elasticnet-teknikker. Et godt kurs for å lære mer er [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning).\n",
"\n",
"Hvis du vil lære mer om hvordan du bruker det fantastiske Tidymodels-rammeverket, kan du sjekke ut følgende ressurser:\n",
"\n",
"- Tidymodels nettsted: [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",
"###### **TAKK TIL:**\n",
"\n",
"[Allison Horst](https://twitter.com/allison_horst?lang=en) for å lage de fantastiske illustrasjonene som gjør R mer innbydende og engasjerende. Finn flere illustrasjoner i hennes [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 dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi tilstreber nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.\n"
]
}
]
}