{ "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:51:24+00:00", "source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb", "language_code": "nl" } }, "cells": [ { "cell_type": "markdown", "source": [], "metadata": { "id": "YJUHCXqK57yz" } }, { "cell_type": "markdown", "source": [ "## Introductie tot Regressie - Les 1\n", "\n", "#### In perspectief plaatsen\n", "\n", "✅ Er zijn veel soorten regressiemethoden, en welke je kiest hangt af van het antwoord dat je zoekt. Als je de waarschijnlijke lengte van een persoon van een bepaalde leeftijd wilt voorspellen, gebruik je `lineaire regressie`, omdat je op zoek bent naar een **numerieke waarde**. Als je wilt ontdekken of een type keuken als veganistisch moet worden beschouwd of niet, zoek je naar een **categorie-indeling**, dus zou je `logistische regressie` gebruiken. Je leert later meer over logistische regressie. Denk eens na over enkele vragen die je aan data kunt stellen, en welke van deze methoden het meest geschikt zou zijn.\n", "\n", "In deze sectie werk je met een [kleine dataset over diabetes](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html). Stel je voor dat je een behandeling voor diabetespatiënten wilde testen. Machine Learning-modellen kunnen je helpen bepalen welke patiënten beter op de behandeling zouden reageren, gebaseerd op combinaties van variabelen. Zelfs een heel eenvoudig regressiemodel, wanneer gevisualiseerd, kan informatie tonen over variabelen die je zouden helpen je theoretische klinische proeven te organiseren.\n", "\n", "Dat gezegd hebbende, laten we aan deze taak beginnen!\n", "\n", "

\n", " \n", "

Kunstwerk door @allison_horst
\n", "\n", "\n" ], "metadata": { "id": "LWNNzfqd6feZ" } }, { "cell_type": "markdown", "source": [ "## 1. Onze gereedschapsset laden\n", "\n", "Voor deze taak hebben we de volgende pakketten nodig:\n", "\n", "- `tidyverse`: Het [tidyverse](https://www.tidyverse.org/) is een [verzameling van R-pakketten](https://www.tidyverse.org/packages) ontworpen om datawetenschap sneller, eenvoudiger en leuker te maken!\n", "\n", "- `tidymodels`: Het [tidymodels](https://www.tidymodels.org/) framework is een [verzameling van pakketten](https://www.tidymodels.org/packages/) voor modellering en machine learning.\n", "\n", "Je kunt ze installeren met:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\"))`\n", "\n", "Het onderstaande script controleert of je de benodigde pakketten hebt om deze module te voltooien en installeert ze voor je als er pakketten ontbreken.\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": [ "Laten we nu deze geweldige pakketten laden en beschikbaar maken in onze huidige R-sessie. (Dit is slechts ter illustratie, `pacman::p_load()` heeft dat al voor je gedaan)\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. De diabetes dataset\n", "\n", "In deze oefening gaan we onze regressievaardigheden demonstreren door voorspellingen te maken op een diabetes dataset. De [diabetes dataset](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt) bevat `442 voorbeelden` van gegevens over diabetes, met 10 voorspellende variabelen: `leeftijd`, `geslacht`, `body mass index`, `gemiddelde bloeddruk`, en `zes bloedserummetingen`, evenals een uitkomstvariabele `y`: een kwantitatieve maat voor ziekteprogressie één jaar na de basislijn.\n", "\n", "|Aantal observaties|442|\n", "|------------------|:---|\n", "|Aantal voorspellers|De eerste 10 kolommen zijn numerieke voorspellers|\n", "|Uitkomst/Doel|Kolom 11 is een kwantitatieve maat voor ziekteprogressie één jaar na de basislijn|\n", "|Informatie over voorspellers|- leeftijd in jaren\n", "||- geslacht\n", "||- bmi body mass index\n", "||- bp gemiddelde bloeddruk\n", "||- s1 tc, totaal serumcholesterol\n", "||- s2 ldl, low-density lipoproteïnen\n", "||- s3 hdl, high-density lipoproteïnen\n", "||- s4 tch, totaal cholesterol / HDL\n", "||- s5 ltg, mogelijk logaritme van serumtriglyceridenniveau\n", "||- s6 glu, bloedsuikerniveau|\n", "\n", "> 🎓 Onthoud, dit is supervised learning, en we hebben een benoemde 'y'-doelvariabele nodig.\n", "\n", "Voordat je gegevens kunt manipuleren met R, moet je de gegevens importeren in het geheugen van R, of een verbinding maken met de gegevens zodat R deze op afstand kan benaderen.\n", "\n", "> Het [readr](https://readr.tidyverse.org/) pakket, dat deel uitmaakt van de Tidyverse, biedt een snelle en gebruiksvriendelijke manier om rechthoekige gegevens in R te laden.\n", "\n", "Laten we nu de diabetes dataset laden via deze bron-URL: \n", "\n", "Daarnaast voeren we een controle uit op onze gegevens met behulp van `glimpse()` en tonen we de eerste 5 rijen met `slice()`.\n", "\n", "Voordat we verder gaan, introduceren we ook iets dat je vaak zult tegenkomen in R-code 🥁🥁: de pipe-operator `%>%`\n", "\n", "De pipe-operator (`%>%`) voert bewerkingen uit in logische volgorde door een object door te geven aan een functie of expressie. Je kunt de pipe-operator zien als \"en dan\" in je code.\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()` laat ons zien dat deze data 442 rijen en 11 kolommen bevat, waarbij alle kolommen van het datatype `double` zijn.\n", "\n", "
\n", "\n", "> glimpse() en slice() zijn functies in [`dplyr`](https://dplyr.tidyverse.org/). Dplyr, onderdeel van de Tidyverse, is een grammatica voor datamanipulatie die een consistente set werkwoorden biedt om de meest voorkomende uitdagingen bij datamanipulatie op te lossen.\n", "\n", "
\n", "\n", "Nu we de data hebben, gaan we ons richten op één kenmerk (`bmi`) als doel voor deze oefening. Hiervoor moeten we de gewenste kolommen selecteren. Hoe doen we dat?\n", "\n", "[`dplyr::select()`](https://dplyr.tidyverse.org/reference/select.html) stelt ons in staat om kolommen in een data frame te *selecteren* (en eventueel te hernoemen).\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. Train- en testgegevens\n", "\n", "Het is gebruikelijk in supervised learning om de gegevens op te *splitsen* in twee subsets: een (meestal grotere) set om het model mee te trainen, en een kleinere \"achtergehouden\" set om te zien hoe het model presteert.\n", "\n", "Nu we de gegevens klaar hebben, kunnen we kijken of een machine kan helpen om een logische splitsing te maken tussen de getallen in deze dataset. We kunnen het [rsample](https://tidymodels.github.io/rsample/) pakket gebruiken, dat deel uitmaakt van het Tidymodels-framework, om een object te maken dat de informatie bevat over *hoe* de gegevens gesplitst moeten worden, en vervolgens twee andere rsample-functies gebruiken om de gemaakte train- en testsets te extraheren:\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. Train een lineair regressiemodel met Tidymodels\n", "\n", "Nu zijn we klaar om ons model te trainen!\n", "\n", "In Tidymodels specificeer je modellen met `parsnip()` door drie concepten te definiëren:\n", "\n", "- Het **type** model onderscheidt modellen zoals lineaire regressie, logistische regressie, beslissingsboommodellen, enzovoort.\n", "\n", "- De **modus** van het model omvat veelvoorkomende opties zoals regressie en classificatie; sommige modeltypes ondersteunen beide, terwijl andere slechts één modus hebben.\n", "\n", "- De **engine** van het model is het computationele hulpmiddel dat wordt gebruikt om het model te fitten. Vaak zijn dit R-pakketten, zoals **`\"lm\"`** of **`\"ranger\"`**\n", "\n", "Deze modelinformatie wordt vastgelegd in een modelspecificatie, dus laten we er een maken!\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": [ "Nadat een model is *gespecificeerd*, kan het model worden `geschat` of `getraind` met behulp van de [`fit()`](https://parsnip.tidymodels.org/reference/fit.html)-functie, meestal met een formule en wat gegevens.\n", "\n", "`y ~ .` betekent dat we `y` zullen modelleren als de voorspelde waarde/doel, verklaard door alle voorspellers/kenmerken, oftewel `.` (in dit geval hebben we slechts één voorspeller: `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": [ "Uit de modeloutput kunnen we de tijdens de training geleerde coëfficiënten zien. Deze vertegenwoordigen de coëfficiënten van de lijn van beste fit die ons de laagste totale fout geeft tussen de werkelijke en voorspelde variabele.\n", "
\n", "\n", "## 5. Voorspellingen maken op de testset\n", "\n", "Nu we een model hebben getraind, kunnen we het gebruiken om de ziekteprogressie y te voorspellen voor de testdataset met behulp van [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Dit zal worden gebruikt om de lijn tussen datagroepen te tekenen.\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! 💃🕺 We hebben net een model getraind en gebruikt om voorspellingen te maken!\n", "\n", "Bij het maken van voorspellingen is het volgens de tidymodels-conventie altijd de bedoeling om een tibble/dataframe met resultaten en gestandaardiseerde kolomnamen te produceren. Dit maakt het eenvoudig om de originele data en de voorspellingen te combineren in een bruikbaar formaat voor verdere bewerkingen, zoals het maken van grafieken.\n", "\n", "`dplyr::bind_cols()` voegt efficiënt meerdere dataframes samen per kolom.\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. Resultaten van de modellering plotten\n", "\n", "Nu is het tijd om dit visueel te bekijken 📈. We maken een spreidingsdiagram van alle `y`- en `bmi`-waarden van de testset en gebruiken vervolgens de voorspellingen om een lijn te tekenen op de meest geschikte plek, tussen de datagroeperingen van het model.\n", "\n", "R heeft verschillende systemen om grafieken te maken, maar `ggplot2` is een van de meest elegante en veelzijdige. Hiermee kun je grafieken samenstellen door **onafhankelijke componenten te combineren**.\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": [ "✅ Denk eens na over wat hier gebeurt. Een rechte lijn loopt door veel kleine datapunten, maar wat doet die precies? Kun je zien hoe je deze lijn zou moeten kunnen gebruiken om te voorspellen waar een nieuw, onbekend datapunt zou moeten passen in relatie tot de y-as van de plot? Probeer in woorden uit te leggen wat het praktische nut van dit model is.\n", "\n", "Gefeliciteerd, je hebt je eerste lineaire regressiemodel gebouwd, er een voorspelling mee gemaakt en deze weergegeven in een plot!\n" ], "metadata": { "id": "zrPtHIxx_tNI" } }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Disclaimer**: \nDit document is vertaald met behulp van de AI-vertalingsservice [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel we streven naar nauwkeurigheid, willen we u erop wijzen dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor kritieke informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.\n" ] } ] }