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.
447 lines
16 KiB
447 lines
16 KiB
{
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2,
|
|
"metadata": {
|
|
"colab": {
|
|
"name": "lesson_1-R.ipynb",
|
|
"provenance": [],
|
|
"collapsed_sections": [],
|
|
"toc_visible": true
|
|
},
|
|
"kernelspec": {
|
|
"name": "ir",
|
|
"display_name": "R"
|
|
},
|
|
"language_info": {
|
|
"name": "R"
|
|
},
|
|
"coopTranslator": {
|
|
"original_hash": "c18d3bd0bd8ae3878597e89dcd1fa5c1",
|
|
"translation_date": "2025-09-06T11:52:06+00:00",
|
|
"source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb",
|
|
"language_code": "no"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [],
|
|
"metadata": {
|
|
"id": "YJUHCXqK57yz"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Introduksjon til regresjon - Leksjon 1\n",
|
|
"\n",
|
|
"#### Sett det i perspektiv\n",
|
|
"\n",
|
|
"✅ Det finnes mange typer regresjonsmetoder, og hvilken du velger avhenger av svaret du leter etter. Hvis du vil forutsi sannsynlig høyde for en person med en gitt alder, vil du bruke `lineær regresjon`, siden du søker en **numerisk verdi**. Hvis du er interessert i å finne ut om en type mat bør anses som vegansk eller ikke, ser du etter en **kategoriinndeling**, og da vil du bruke `logistisk regresjon`. Du vil lære mer om logistisk regresjon senere. Tenk litt på noen spørsmål du kan stille til data, og hvilken av disse metodene som ville være mest passende.\n",
|
|
"\n",
|
|
"I denne delen skal du jobbe med et [lite datasett om diabetes](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html). Tenk deg at du ønsket å teste en behandling for diabetikere. Maskinlæringsmodeller kan hjelpe deg med å avgjøre hvilke pasienter som vil respondere bedre på behandlingen, basert på kombinasjoner av variabler. Selv en veldig enkel regresjonsmodell, når den visualiseres, kan vise informasjon om variabler som kan hjelpe deg med å organisere dine teoretiske kliniske studier.\n",
|
|
"\n",
|
|
"Med det sagt, la oss komme i gang med denne oppgaven!\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/encouRage.jpg\"\n",
|
|
" width=\"630\"/>\n",
|
|
" <figcaption>Kunstverk av @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"<!--<br>Kunstverk av @allison_horst-->\n"
|
|
],
|
|
"metadata": {
|
|
"id": "LWNNzfqd6feZ"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## 1. Laste inn verktøysettet vårt\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) som er laget for å gjøre datavitenskap raskere, enklere og morsommere!\n",
|
|
"\n",
|
|
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) er et [rammeverk med pakker](https://www.tidymodels.org/packages/) for modellering og maskinlæring.\n",
|
|
"\n",
|
|
"Du kan installere dem slik:\n",
|
|
"\n",
|
|
"`install.packages(c(\"tidyverse\", \"tidymodels\"))`\n",
|
|
"\n",
|
|
"Skriptet nedenfor sjekker om du har de nødvendige pakkene for å fullføre denne modulen og installerer dem for deg dersom noen mangler.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "FIo2YhO26wI9"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"source": [
|
|
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
|
|
"pacman::p_load(tidyverse, tidymodels)"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"output_type": "stream",
|
|
"name": "stderr",
|
|
"text": [
|
|
"Loading required package: pacman\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"id": "cIA9fz9v7Dss",
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"outputId": "2df7073b-86b2-4b32-cb86-0da605a0dc11"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"La oss nå laste inn disse fantastiske pakkene og gjøre dem tilgjengelige i vår nåværende R-økt. (Dette er kun for illustrasjon, `pacman::p_load()` har allerede gjort det for deg)\n"
|
|
],
|
|
"metadata": {
|
|
"id": "gpO_P_6f9WUG"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# load the core Tidyverse packages\r\n",
|
|
"library(tidyverse)\r\n",
|
|
"\r\n",
|
|
"# load the core Tidymodels packages\r\n",
|
|
"library(tidymodels)\r\n"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "NLMycgG-9ezO"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## 2. Diabetes-datasettet\n",
|
|
"\n",
|
|
"I denne øvelsen skal vi vise våre regresjonsferdigheter ved å lage prediksjoner på et diabetes-datasett. [Diabetes-datasettet](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt) inkluderer `442 prøver` med data om diabetes, med 10 prediktorvariabler: `alder`, `kjønn`, `kroppsmasseindeks`, `gjennomsnittlig blodtrykk` og `seks blodserummålinger`, samt en utfallsvariabel `y`: et kvantitativt mål på sykdomsutvikling ett år etter baseline.\n",
|
|
"\n",
|
|
"|Antall observasjoner|442|\n",
|
|
"|--------------------|:---|\n",
|
|
"|Antall prediktorer|De første 10 kolonnene er numeriske prediktorer|\n",
|
|
"|Utfall/Mål|Kolonne 11 er et kvantitativt mål på sykdomsutvikling ett år etter baseline|\n",
|
|
"|Informasjon om prediktorer|- alder i år\n",
|
|
"||- kjønn\n",
|
|
"||- bmi kroppsmasseindeks\n",
|
|
"||- bp gjennomsnittlig blodtrykk\n",
|
|
"||- s1 tc, total serumkolesterol\n",
|
|
"||- s2 ldl, lavdensitetslipoproteiner\n",
|
|
"||- s3 hdl, høydensitetslipoproteiner\n",
|
|
"||- s4 tch, total kolesterol / HDL\n",
|
|
"||- s5 ltg, muligens logaritmen av serumtriglyseridnivå\n",
|
|
"||- s6 glu, blodsukkernivå|\n",
|
|
"\n",
|
|
"> 🎓 Husk, dette er veiledet læring, og vi trenger et navngitt mål 'y'.\n",
|
|
"\n",
|
|
"Før du kan manipulere data med R, må du importere dataene til R's minne, eller opprette en forbindelse til dataene som R kan bruke for å få tilgang til dem eksternt.\n",
|
|
"\n",
|
|
"> [readr](https://readr.tidyverse.org/)-pakken, som er en del av Tidyverse, gir en rask og brukervennlig måte å lese rektangulære data inn i R.\n",
|
|
"\n",
|
|
"La oss nå laste inn diabetes-datasettet fra denne kilde-URL-en: <https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html>\n",
|
|
"\n",
|
|
"Vi skal også utføre en enkel sjekk av dataene våre ved å bruke `glimpse()` og vise de første 5 radene med `slice()`.\n",
|
|
"\n",
|
|
"Før vi går videre, la oss også introdusere noe du ofte vil støte på i R-kode 🥁🥁: pipe-operatøren `%>%`\n",
|
|
"\n",
|
|
"Pipe-operatøren (`%>%`) utfører operasjoner i logisk rekkefølge ved å sende et objekt videre inn i en funksjon eller kalluttrykk. Du kan tenke på pipe-operatøren som å si \"og deretter\" i koden din.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "KM6iXLH996Cl"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Import the data set\r\n",
|
|
"diabetes <- read_table2(file = \"https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt\")\r\n",
|
|
"\r\n",
|
|
"\r\n",
|
|
"# Get a glimpse and dimensions of the data\r\n",
|
|
"glimpse(diabetes)\r\n",
|
|
"\r\n",
|
|
"\r\n",
|
|
"# Select the first 5 rows of the data\r\n",
|
|
"diabetes %>% \r\n",
|
|
" slice(1:5)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "Z1geAMhM-bSP"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"`glimpse()` viser oss at disse dataene har 442 rader og 11 kolonner, hvor alle kolonnene er av datatypen `double`.\n",
|
|
"\n",
|
|
"<br>\n",
|
|
"\n",
|
|
"> glimpse() og slice() er funksjoner i [`dplyr`](https://dplyr.tidyverse.org/). Dplyr, som er en del av Tidyverse, er et rammeverk for datamanipulering som gir et konsistent sett med verktøy for å løse de vanligste utfordringene innen datamanipulering.\n",
|
|
"\n",
|
|
"<br>\n",
|
|
"\n",
|
|
"Nå som vi har dataene, la oss fokusere på én variabel (`bmi`) som mål for denne øvelsen. Dette krever at vi velger de ønskede kolonnene. Så, hvordan gjør vi dette?\n",
|
|
"\n",
|
|
"[`dplyr::select()`](https://dplyr.tidyverse.org/reference/select.html) lar oss *velge* (og eventuelt gi nytt navn til) kolonner i en dataramme.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "UwjVT1Hz-c3Z"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Select predictor feature `bmi` and outcome `y`\r\n",
|
|
"diabetes_select <- diabetes %>% \r\n",
|
|
" select(c(bmi, y))\r\n",
|
|
"\r\n",
|
|
"# Print the first 5 rows\r\n",
|
|
"diabetes_select %>% \r\n",
|
|
" slice(1:10)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "RDY1oAKI-m80"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## 3. Trenings- og testdata\n",
|
|
"\n",
|
|
"Det er vanlig praksis i overvåket læring å *dele* dataene i to undergrupper; et (typisk større) sett for å trene modellen, og et mindre \"tilbakeholdt\" sett for å se hvordan modellen presterte.\n",
|
|
"\n",
|
|
"Nå som vi har dataene klare, kan vi se om en maskin kan hjelpe med å bestemme en logisk deling mellom tallene i dette datasettet. Vi kan bruke [rsample](https://tidymodels.github.io/rsample/)-pakken, som er en del av Tidymodels-rammeverket, for å opprette et objekt som inneholder informasjon om *hvordan* dataene skal deles, og deretter to flere rsample-funksjoner for å hente ut de opprettede trenings- og testsettene:\n"
|
|
],
|
|
"metadata": {
|
|
"id": "SDk668xK-tc3"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"set.seed(2056)\r\n",
|
|
"# Split 67% of the data for training and the rest for tesing\r\n",
|
|
"diabetes_split <- diabetes_select %>% \r\n",
|
|
" initial_split(prop = 0.67)\r\n",
|
|
"\r\n",
|
|
"# Extract the resulting train and test sets\r\n",
|
|
"diabetes_train <- training(diabetes_split)\r\n",
|
|
"diabetes_test <- testing(diabetes_split)\r\n",
|
|
"\r\n",
|
|
"# Print the first 3 rows of the training set\r\n",
|
|
"diabetes_train %>% \r\n",
|
|
" slice(1:10)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "EqtHx129-1h-"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## 4. Tren en lineær regresjonsmodell med Tidymodels\n",
|
|
"\n",
|
|
"Nå er vi klare til å trene modellen vår!\n",
|
|
"\n",
|
|
"I Tidymodels spesifiserer du modeller ved hjelp av `parsnip()` ved å definere tre konsepter:\n",
|
|
"\n",
|
|
"- Modell **type** skiller mellom modeller som lineær regresjon, logistisk regresjon, beslutningstrær og lignende.\n",
|
|
"\n",
|
|
"- Modell **modus** inkluderer vanlige alternativer som regresjon og klassifisering; noen modelltyper støtter begge disse, mens andre kun har én modus.\n",
|
|
"\n",
|
|
"- Modell **motor** er det beregningsverktøyet som vil bli brukt til å tilpasse modellen. Ofte er disse R-pakker, som **`\"lm\"`** eller **`\"ranger\"`**\n",
|
|
"\n",
|
|
"Denne modellinformasjonen fanges opp i en modellspecifikasjon, så la oss lage en!\n"
|
|
],
|
|
"metadata": {
|
|
"id": "sBOS-XhB-6v7"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Build a linear model specification\r\n",
|
|
"lm_spec <- \r\n",
|
|
" # Type\r\n",
|
|
" linear_reg() %>% \r\n",
|
|
" # Engine\r\n",
|
|
" set_engine(\"lm\") %>% \r\n",
|
|
" # Mode\r\n",
|
|
" set_mode(\"regression\")\r\n",
|
|
"\r\n",
|
|
"\r\n",
|
|
"# Print the model specification\r\n",
|
|
"lm_spec"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "20OwEw20--t3"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Etter at en modell har blitt *spesifisert*, kan modellen `estimeres` eller `trenes` ved hjelp av funksjonen [`fit()`](https://parsnip.tidymodels.org/reference/fit.html), vanligvis ved bruk av en formel og noen data.\n",
|
|
"\n",
|
|
"`y ~ .` betyr at vi skal tilpasse `y` som den predikerte verdien/målet, forklart av alle prediktorene/egenskapene, altså `.` (i dette tilfellet har vi kun én prediktor: `bmi`).\n"
|
|
],
|
|
"metadata": {
|
|
"id": "_oDHs89k_CJj"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Build a linear model specification\r\n",
|
|
"lm_spec <- linear_reg() %>% \r\n",
|
|
" set_engine(\"lm\") %>%\r\n",
|
|
" set_mode(\"regression\")\r\n",
|
|
"\r\n",
|
|
"\r\n",
|
|
"# Train a linear regression model\r\n",
|
|
"lm_mod <- lm_spec %>% \r\n",
|
|
" fit(y ~ ., data = diabetes_train)\r\n",
|
|
"\r\n",
|
|
"# Print the model\r\n",
|
|
"lm_mod"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "YlsHqd-q_GJQ"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Fra modellens output kan vi se koeffisientene som ble lært under treningen. Disse representerer koeffisientene for den beste tilpasningslinjen som gir oss den laveste totale feilen mellom den faktiske og den predikerte variabelen.\n",
|
|
"<br>\n",
|
|
"\n",
|
|
"## 5. Gjør prediksjoner på testsettet\n",
|
|
"\n",
|
|
"Nå som vi har trent en modell, kan vi bruke den til å forutsi sykdomsutviklingen y for testdatasettet ved hjelp av [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Dette vil bli brukt til å tegne linjen mellom datagruppene.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "kGZ22RQj_Olu"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Make predictions for the test set\r\n",
|
|
"predictions <- lm_mod %>% \r\n",
|
|
" predict(new_data = diabetes_test)\r\n",
|
|
"\r\n",
|
|
"# Print out some of the predictions\r\n",
|
|
"predictions %>% \r\n",
|
|
" slice(1:5)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "nXHbY7M2_aao"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Woohoo! 💃🕺 Vi har nettopp trent en modell og brukt den til å lage prediksjoner!\n",
|
|
"\n",
|
|
"Når vi lager prediksjoner, er det en konvensjon i tidymodels å alltid produsere en tibble/data frame med resultater og standardiserte kolonnenavn. Dette gjør det enkelt å kombinere de originale dataene med prediksjonene i et brukervennlig format for videre operasjoner som visualisering.\n",
|
|
"\n",
|
|
"`dplyr::bind_cols()` binder effektivt flere data frames sammen kolonnevis.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "R_JstwUY_bIs"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Combine the predictions and the original test set\r\n",
|
|
"results <- diabetes_test %>% \r\n",
|
|
" bind_cols(predictions)\r\n",
|
|
"\r\n",
|
|
"\r\n",
|
|
"results %>% \r\n",
|
|
" slice(1:5)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "RybsMJR7_iI8"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## 6. Visualisering av modellresultater\n",
|
|
"\n",
|
|
"Nå er det på tide å se dette visuelt 📈. Vi skal lage et spredningsdiagram av alle `y`- og `bmi`-verdiene fra testsettet, og deretter bruke prediksjonene til å tegne en linje på det mest passende stedet, mellom modellens datagrupperinger.\n",
|
|
"\n",
|
|
"R har flere systemer for å lage grafer, men `ggplot2` er en av de mest elegante og allsidige. Dette lar deg komponere grafer ved **å kombinere uavhengige komponenter**.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "XJbYbMZW_n_s"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Set a theme for the plot\r\n",
|
|
"theme_set(theme_light())\r\n",
|
|
"# Create a scatter plot\r\n",
|
|
"results %>% \r\n",
|
|
" ggplot(aes(x = bmi)) +\r\n",
|
|
" # Add a scatter plot\r\n",
|
|
" geom_point(aes(y = y), size = 1.6) +\r\n",
|
|
" # Add a line plot\r\n",
|
|
" geom_line(aes(y = .pred), color = \"blue\", size = 1.5)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "R9tYp3VW_sTn"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"✅ Tenk litt over hva som skjer her. En rett linje går gjennom mange små datapunkter, men hva gjør den egentlig? Kan du se hvordan du burde kunne bruke denne linjen til å forutsi hvor et nytt, ukjent datapunkt burde passe i forhold til plottets y-akse? Prøv å sette ord på den praktiske bruken av denne modellen.\n",
|
|
"\n",
|
|
"Gratulerer, du har laget din første lineære regresjonsmodell, laget en prediksjon med den, og vist den i et plott!\n"
|
|
],
|
|
"metadata": {
|
|
"id": "zrPtHIxx_tNI"
|
|
}
|
|
},
|
|
{
|
|
"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"
|
|
]
|
|
}
|
|
]
|
|
} |