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.
1083 lines
42 KiB
1083 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-06T11:37:09+00:00",
|
|
"source_file": "2-Regression/3-Linear/solution/R/lesson_3-R.ipynb",
|
|
"language_code": "nl"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [],
|
|
"metadata": {
|
|
"id": "EgQw8osnsUV-"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Lineaire en Polynomiale Regressie voor Pompoenprijzen - Les 3\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/linear-polynomial.png\"\n",
|
|
" width=\"800\"/>\n",
|
|
" <figcaption>Infographic door Dasani Madipalli</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!--{width=\"800\"}-->\n",
|
|
"\n",
|
|
"#### Introductie\n",
|
|
"\n",
|
|
"Tot nu toe heb je onderzocht wat regressie is met voorbeeldgegevens verzameld uit de pompoenprijsdataset die we gedurende deze les zullen gebruiken. Je hebt het ook gevisualiseerd met behulp van `ggplot2`. 💪\n",
|
|
"\n",
|
|
"Nu ben je klaar om dieper in te gaan op regressie voor machine learning. In deze les leer je meer over twee soorten regressie: *basis lineaire regressie* en *polynomiale regressie*, samen met enkele wiskundige principes die aan deze technieken ten grondslag liggen.\n",
|
|
"\n",
|
|
"> Door deze hele cursus gaan we uit van minimale wiskundige kennis en proberen we het toegankelijk te maken voor studenten uit andere vakgebieden. Let daarom op notities, 🧮 wiskundige aanwijzingen, diagrammen en andere leermiddelen om het begrip te vergemakkelijken.\n",
|
|
"\n",
|
|
"#### Voorbereiding\n",
|
|
"\n",
|
|
"Ter herinnering: je laadt deze gegevens in om er vragen over te stellen.\n",
|
|
"\n",
|
|
"- Wanneer is de beste tijd om pompoenen te kopen?\n",
|
|
"\n",
|
|
"- Welke prijs kan ik verwachten voor een kist met miniatuurpompoenen?\n",
|
|
"\n",
|
|
"- Moet ik ze kopen in halve schepelmanden of in een 1 1/9 schepeldoos? Laten we verder graven in deze gegevens.\n",
|
|
"\n",
|
|
"In de vorige les heb je een `tibble` (een moderne herinterpretatie van het data frame) gemaakt en deze gevuld met een deel van de oorspronkelijke dataset, waarbij je de prijzen standaardiseerde per schepel. Door dat te doen, kon je echter slechts ongeveer 400 datapunten verzamelen en alleen voor de herfstmaanden. Misschien kunnen we wat meer details over de aard van de gegevens krijgen door ze verder op te schonen? We zullen zien... 🕵️♀️\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 data science 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 modelleren en machine learning.\n",
|
|
"\n",
|
|
"- `janitor`: Het [janitor-pakket](https://github.com/sfirke/janitor) biedt eenvoudige hulpmiddelen voor het onderzoeken en opschonen van rommelige gegevens.\n",
|
|
"\n",
|
|
"- `corrplot`: Het [corrplot-pakket](https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html) biedt een visueel exploratie-instrument voor correlatiematrices dat automatische variabelenherordening ondersteunt om verborgen patronen tussen variabelen te helpen detecteren.\n",
|
|
"\n",
|
|
"Je kunt ze installeren met:\n",
|
|
"\n",
|
|
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"corrplot\"))`\n",
|
|
"\n",
|
|
"Het onderstaande script controleert of je de pakketten hebt die nodig zijn om deze module te voltooien en installeert ze voor je als ze ontbreken.\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": [
|
|
"We zullen later 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",
|
|
"\n",
|
|
"## 1. Een lineaire regressielijn\n",
|
|
"\n",
|
|
"Zoals je hebt geleerd in Les 1, is het doel van een lineaire regressieoefening om een *lijn* *van* *beste* *fit* te kunnen plotten om:\n",
|
|
"\n",
|
|
"- **Variabele relaties te tonen**. De relatie tussen variabelen te laten zien.\n",
|
|
"\n",
|
|
"- **Voorspellingen te maken**. Nauwkeurige voorspellingen te maken over waar een nieuw datapunt zou vallen in relatie tot die lijn.\n",
|
|
"\n",
|
|
"Om dit type lijn te tekenen, gebruiken we een statistische techniek genaamd **Least-Squares Regression**. De term `least-squares` betekent dat alle datapunten rondom de regressielijn worden gekwadrateerd en vervolgens opgeteld. Idealiter is die uiteindelijke som zo klein mogelijk, omdat we een laag aantal fouten willen, oftewel `least-squares`. De lijn van beste fit is dus de lijn die ons de laagste waarde geeft voor de som van de gekwadrateerde fouten - vandaar de naam *least squares regression*.\n",
|
|
"\n",
|
|
"We doen dit omdat we een lijn willen modelleren die de kleinste cumulatieve afstand heeft tot al onze datapunten. We kwadrateren de termen voordat we ze optellen, omdat we ons bezighouden met de grootte ervan en niet met de richting.\n",
|
|
"\n",
|
|
"> **🧮 Laat me de wiskunde zien**\n",
|
|
">\n",
|
|
"> Deze lijn, genaamd de *lijn van beste fit*, kan worden uitgedrukt door [een vergelijking](https://en.wikipedia.org/wiki/Simple_linear_regression):\n",
|
|
">\n",
|
|
"> Y = a + bX\n",
|
|
">\n",
|
|
"> `X` is de '`verklarende variabele` of `voorspeller`'. `Y` is de '`afhankelijke variabele` of `uitkomst`'. De helling van de lijn is `b` en `a` is het snijpunt met de y-as, wat verwijst naar de waarde van `Y` wanneer `X = 0`.\n",
|
|
">\n",
|
|
"\n",
|
|
"> \n",
|
|
" Infographic door Jen Looper\n",
|
|
">\n",
|
|
"> Bereken eerst de helling `b`.\n",
|
|
">\n",
|
|
"> Met andere woorden, en verwijzend naar de oorspronkelijke vraag over onze pompoendata: \"voorspel de prijs van een pompoen per schepel per maand\", zou `X` verwijzen naar de prijs en `Y` naar de maand van verkoop.\n",
|
|
">\n",
|
|
"> \n",
|
|
" Infographic door Jen Looper\n",
|
|
"> \n",
|
|
"> Bereken de waarde van Y. Als je ongeveer \\$4 betaalt, moet het april zijn!\n",
|
|
">\n",
|
|
"> De wiskunde die de lijn berekent, moet de helling van de lijn aantonen, die ook afhankelijk is van het snijpunt, of waar `Y` zich bevindt wanneer `X = 0`.\n",
|
|
">\n",
|
|
"> Je kunt de methode van berekening voor deze waarden bekijken op de [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html) website. Bezoek ook [deze Least-squares calculator](https://www.mathsisfun.com/data/least-squares-calculator.html) om te zien hoe de waarden van de getallen de lijn beïnvloeden.\n",
|
|
"\n",
|
|
"Niet zo eng, toch? 🤓\n",
|
|
"\n",
|
|
"#### Correlatie\n",
|
|
"\n",
|
|
"Nog een term om te begrijpen is de **Correlatiecoëfficiënt** tussen gegeven X- en Y-variabelen. Met een spreidingsdiagram kun je deze coëfficiënt snel visualiseren. Een diagram met datapunten die netjes in een lijn liggen, heeft een hoge correlatie, maar een diagram met datapunten die overal tussen X en Y verspreid zijn, heeft een lage correlatie.\n",
|
|
"\n",
|
|
"Een goed lineair regressiemodel is er een die een hoge (dichter bij 1 dan bij 0) Correlatiecoëfficiënt heeft met behulp van de Least-Squares Regression-methode met een regressielijn.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "cdX5FRpvsoP5"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## **2. Een dans met data: een data frame maken voor modellering**\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/janitor.jpg\"\n",
|
|
" width=\"700\"/>\n",
|
|
" <figcaption>Kunstwerk door @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!--{width=\"700\"}-->\n"
|
|
],
|
|
"metadata": {
|
|
"id": "WdUKXk7Bs8-V"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Laad de benodigde bibliotheken en dataset. Zet de data om naar een data frame met een subset van de gegevens:\n",
|
|
"\n",
|
|
"- Selecteer alleen pompoenen die per schepel geprijsd zijn\n",
|
|
"\n",
|
|
"- Zet de datum om naar een maand\n",
|
|
"\n",
|
|
"- Bereken de prijs als een gemiddelde van de hoge en lage prijzen\n",
|
|
"\n",
|
|
"- Zet de prijs om zodat deze overeenkomt met de prijs per schepelhoeveelheid\n",
|
|
"\n",
|
|
"> We hebben deze stappen behandeld in de [vorige les](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": [
|
|
"In de geest van puur avontuur, laten we de [`janitor package`](../../../../../../2-Regression/3-Linear/solution/R/github.com/sfirke/janitor) verkennen die eenvoudige functies biedt voor het onderzoeken en opschonen van rommelige gegevens. Laten we bijvoorbeeld eens kijken naar de kolomnamen van onze gegevens:\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": [
|
|
"🤔 We kunnen beter. Laten we deze kolomnamen `friendR` maken door ze om te zetten naar de [snake_case](https://en.wikipedia.org/wiki/Snake_case)-conventie met behulp van `janitor::clean_names`. Om meer te weten te komen over deze functie: `?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": [
|
|
"Veel tidyR 🧹! Nu, een dansje met de data met behulp van `dplyr`, zoals in de vorige les! 💃\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": [
|
|
"Goed gedaan!👌 Je hebt nu een schoon en overzichtelijk gegevensbestand waarop je je nieuwe regressiemodel kunt bouwen!\n",
|
|
"\n",
|
|
"Zin in een spreidingsdiagram?\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": [
|
|
"Een spreidingsdiagram herinnert ons eraan dat we alleen maandgegevens hebben van augustus tot en met december. We hebben waarschijnlijk meer gegevens nodig om conclusies te kunnen trekken op een lineaire manier.\n",
|
|
"\n",
|
|
"Laten we onze modelleringsgegevens opnieuw bekijken:\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": [
|
|
"Wat als we de `prijs` van een pompoen wilden voorspellen op basis van de kolommen `stad` of `pakket`, die van het type karakter zijn? Of nog eenvoudiger, hoe zouden we de correlatie kunnen vinden (wat vereist dat beide invoerwaarden numeriek zijn) tussen bijvoorbeeld `pakket` en `prijs`? 🤷🤷\n",
|
|
"\n",
|
|
"Machine learning-modellen werken het beste met numerieke kenmerken in plaats van tekstwaarden, dus je moet categorische kenmerken meestal omzetten naar numerieke representaties.\n",
|
|
"\n",
|
|
"Dit betekent dat we een manier moeten vinden om onze voorspellers opnieuw te formatteren, zodat een model ze effectiever kan gebruiken. Dit proces staat bekend als `feature engineering`.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "7hsHoxsStyjJ"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## 3. Gegevens voorbereiden voor modellering met recepten 👩🍳👨🍳\n",
|
|
"\n",
|
|
"Activiteiten die voorspellerwaarden herformatteren om ze gemakkelijker door een model te laten gebruiken, worden `feature engineering` genoemd.\n",
|
|
"\n",
|
|
"Verschillende modellen hebben verschillende vereisten voor gegevensvoorbereiding. Bijvoorbeeld, least squares vereist `het coderen van categorische variabelen` zoals maand, variëteit en city_name. Dit houdt simpelweg in dat een kolom met `categorische waarden` wordt `vertaald` naar een of meer `numerieke kolommen` die de oorspronkelijke kolom vervangen.\n",
|
|
"\n",
|
|
"Stel bijvoorbeeld dat je gegevens de volgende categorische eigenschap bevatten:\n",
|
|
"\n",
|
|
"| stad |\n",
|
|
"|:-------:|\n",
|
|
"| Denver |\n",
|
|
"| Nairobi |\n",
|
|
"| Tokio |\n",
|
|
"\n",
|
|
"Je kunt *ordinale codering* toepassen om elke categorie te vervangen door een unieke integerwaarde, zoals dit:\n",
|
|
"\n",
|
|
"| stad |\n",
|
|
"|:----:|\n",
|
|
"| 0 |\n",
|
|
"| 1 |\n",
|
|
"| 2 |\n",
|
|
"\n",
|
|
"En dat is precies wat we met onze gegevens gaan doen!\n",
|
|
"\n",
|
|
"In deze sectie gaan we een ander geweldig Tidymodels-pakket verkennen: [recipes](https://tidymodels.github.io/recipes/) - dat is ontworpen om je te helpen je gegevens te verwerken **voordat** je je model traint. In de kern is een recept een object dat definieert welke stappen moeten worden toegepast op een dataset om deze klaar te maken voor modellering.\n",
|
|
"\n",
|
|
"Laten we nu een recept maken dat onze gegevens voorbereidt voor modellering door een unieke integer te vervangen voor alle observaties in de voorspellerkolommen:\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": [
|
|
"Geweldig! 👏 We hebben zojuist ons eerste recept gemaakt dat een uitkomst (prijs) specificeert en de bijbehorende voorspellers, waarbij alle voorspellerkolommen worden gecodeerd als een reeks gehele getallen 🙌! Laten we het snel opsplitsen:\n",
|
|
"\n",
|
|
"- De oproep naar `recipe()` met een formule vertelt het recept de *rollen* van de variabelen, waarbij gebruik wordt gemaakt van de gegevens uit `new_pumpkins` als referentie. Bijvoorbeeld, de kolom `price` is toegewezen aan de rol `outcome`, terwijl de rest van de kolommen de rol `predictor` hebben gekregen.\n",
|
|
"\n",
|
|
"- `step_integer(all_predictors(), zero_based = TRUE)` specificeert dat alle voorspellers moeten worden omgezet in een reeks gehele getallen, waarbij de nummering begint bij 0.\n",
|
|
"\n",
|
|
"We begrijpen dat je misschien denkt: \"Dit is zo gaaf!! Maar wat als ik wil bevestigen dat de recepten precies doen wat ik verwacht? 🤔\"\n",
|
|
"\n",
|
|
"Dat is een geweldige gedachte! Zie je, zodra je recept is gedefinieerd, kun je de parameters schatten die nodig zijn om de gegevens daadwerkelijk voor te verwerken, en vervolgens de verwerkte gegevens extraheren. Dit is meestal niet nodig wanneer je Tidymodels gebruikt (we zullen zo meteen de normale conventie zien -> `workflows`), maar het kan handig zijn als je een soort controle wilt uitvoeren om te bevestigen dat de recepten doen wat je verwacht.\n",
|
|
"\n",
|
|
"Hiervoor heb je twee extra werkwoorden nodig: `prep()` en `bake()`. En zoals altijd helpen onze kleine R-vrienden van [`Allison Horst`](https://github.com/allisonhorst/stats-illustrations) je om dit beter te begrijpen!\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/recipes.png\"\n",
|
|
" width=\"550\"/>\n",
|
|
" <figcaption>Illustratie door @allison_horst</figcaption>\n"
|
|
],
|
|
"metadata": {
|
|
"id": "KEiO0v7kuC9O"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"[`prep()`](https://recipes.tidymodels.org/reference/prep.html): schat de benodigde parameters op basis van een trainingsset, die later kunnen worden toegepast op andere datasets. Bijvoorbeeld, voor een bepaalde voorspellerkolom, welke observatie krijgt het gehele getal 0, 1, 2, enzovoort toegewezen.\n",
|
|
"\n",
|
|
"[`bake()`](https://recipes.tidymodels.org/reference/bake.html): neemt een voorbereide recipe en past de bewerkingen toe op elke dataset.\n",
|
|
"\n",
|
|
"Dat gezegd hebbende, laten we onze recepten voorbereiden en toepassen om echt te bevestigen dat, achter de schermen, de voorspellerkolommen eerst worden gecodeerd voordat een model wordt getraind.\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 verwerkte data `baked_pumpkins` heeft alle voorspellers gecodeerd, wat bevestigt dat de preprocessiestappen die we als ons recept hebben gedefinieerd, inderdaad werken zoals verwacht. Dit maakt het misschien moeilijker voor jou om te lezen, maar veel begrijpelijker voor Tidymodels! Neem even de tijd om uit te zoeken welke observatie is gekoppeld aan welk overeenkomstig geheel getal.\n",
|
|
"\n",
|
|
"Het is ook goed om te vermelden dat `baked_pumpkins` een data frame is waarop we berekeningen kunnen uitvoeren.\n",
|
|
"\n",
|
|
"Bijvoorbeeld, laten we proberen een goede correlatie te vinden tussen twee punten in je data om mogelijk een goed voorspellend model te bouwen. We gebruiken hiervoor de functie `cor()`. Typ `?cor()` om meer te weten te komen over deze functie.\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": [
|
|
"Zoals blijkt, is er slechts een zwakke correlatie tussen de Stad en de Prijs. Er is echter een iets betere correlatie tussen het Pakket en de Prijs. Dat is logisch, toch? Meestal geldt: hoe groter de productdoos, hoe hoger de prijs.\n",
|
|
"\n",
|
|
"Laten we, nu we toch bezig zijn, ook proberen een correlatiematrix van alle kolommen te visualiseren met behulp van het `corrplot`-pakket.\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": [
|
|
"🤩🤩 Veel beter.\n",
|
|
"\n",
|
|
"Een goede vraag om nu aan deze gegevens te stellen is: '`Welke prijs kan ik verwachten voor een bepaald pompoenpakket?`' Laten we meteen aan de slag gaan!\n",
|
|
"\n",
|
|
"> Opmerking: Wanneer je **`bake()`** toepast op het voorbereide recept **`pumpkins_prep`** met **`new_data = NULL`**, haal je de verwerkte (d.w.z. gecodeerde) trainingsgegevens op. Als je een andere dataset had, bijvoorbeeld een testset, en wilde zien hoe een recept deze zou voorbewerken, zou je simpelweg **`pumpkins_prep`** bakken met **`new_data = test_set`**.\n",
|
|
"\n",
|
|
"## 4. Bouw een lineair regressiemodel\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/linear-polynomial.png\"\n",
|
|
" width=\"800\"/>\n",
|
|
" <figcaption>Infographic door Dasani Madipalli</figcaption>\n"
|
|
],
|
|
"metadata": {
|
|
"id": "YqXjLuWavNxW"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Nu we een recept hebben gemaakt en daadwerkelijk hebben bevestigd dat de gegevens correct worden voorbewerkt, gaan we nu een regressiemodel bouwen om de volgende vraag te beantwoorden: `Welke prijs kan ik verwachten voor een bepaald pompoenpakket?`\n",
|
|
"\n",
|
|
"#### Train een lineair regressiemodel met behulp van de trainingsset\n",
|
|
"\n",
|
|
"Zoals je waarschijnlijk al hebt begrepen, is de kolom *price* de `uitkomst`-variabele, terwijl de kolom *package* de `voorspeller`-variabele is.\n",
|
|
"\n",
|
|
"Om dit te doen, splitsen we eerst de gegevens zodat 80% in de trainingsset terechtkomt en 20% in de testset. Vervolgens definiëren we een recept dat de voorspellerkolom omzet in een reeks gehele getallen, en daarna bouwen we een modelspecificatie. We zullen ons recept niet voorbereiden en bakken, omdat we al weten dat het de gegevens naar verwachting zal voorbewerken.\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": [
|
|
"Goed gedaan! Nu we een recept en een modelspecificatie hebben, moeten we een manier vinden om deze samen te voegen in een object dat eerst de gegevens zal voorbewerken (prep+bake achter de schermen), het model zal trainen op de voorbewerkte gegevens en ook ruimte biedt voor eventuele nabewerkingsactiviteiten. Klinkt dat niet geruststellend!🤩\n",
|
|
"\n",
|
|
"In Tidymodels wordt dit handige object een [`workflow`](https://workflows.tidymodels.org/) genoemd, en het bevat op een handige manier je modelcomponenten! Dit is wat we in *Python* *pipelines* zouden noemen.\n",
|
|
"\n",
|
|
"Laten we dus alles samenvoegen in een 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": [
|
|
"👌 Bovendien kan een workflow op vrijwel dezelfde manier worden aangepast/getraind als een model.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "zd1A5tgOwEPX"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Train the model\n",
|
|
"lm_wf_fit <- lm_wf %>% \n",
|
|
" fit(data = pumpkins_train)\n",
|
|
"\n",
|
|
"# Print the model coefficients learned \n",
|
|
"lm_wf_fit"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "NhJagFumwFHf"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Uit de modeloutput kunnen we de coëfficiënten zien die tijdens de training zijn geleerd. Ze 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",
|
|
"#### Modelprestaties evalueren met behulp van de testset\n",
|
|
"\n",
|
|
"Het is tijd om te zien hoe het model heeft gepresteerd 📏! Hoe doen we dit?\n",
|
|
"\n",
|
|
"Nu we het model hebben getraind, kunnen we het gebruiken om voorspellingen te maken voor de test_set met `parsnip::predict()`. Vervolgens kunnen we deze voorspellingen vergelijken met de werkelijke labelwaarden om te beoordelen hoe goed (of niet!) het model werkt.\n",
|
|
"\n",
|
|
"Laten we beginnen met het maken van voorspellingen voor de testset en vervolgens de kolommen aan de testset koppelen.\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, je hebt net een model getraind en gebruikt om voorspellingen te maken! 🔮 Is het goed? Laten we de prestaties van het model evalueren!\n",
|
|
"\n",
|
|
"In Tidymodels doen we dit met behulp van `yardstick::metrics()`! Voor lineaire regressie richten we ons op de volgende metrics:\n",
|
|
"\n",
|
|
"- `Root Mean Square Error (RMSE)`: De vierkantswortel van de [MSE](https://en.wikipedia.org/wiki/Mean_squared_error). Dit levert een absolute maatstaf op in dezelfde eenheid als het label (in dit geval de prijs van een pompoen). Hoe kleiner de waarde, hoe beter het model (simpel gezegd vertegenwoordigt het de gemiddelde prijs waarmee de voorspellingen fout zijn!).\n",
|
|
"\n",
|
|
"- `Coefficient of Determination (meestal bekend als R-squared of R2)`: Een relatieve maatstaf waarbij een hogere waarde betekent dat het model beter past. In essentie vertegenwoordigt deze metric hoeveel van de variatie tussen voorspelde en werkelijke labelwaarden het model kan verklaren.\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": [
|
|
"Daar gaat de modelprestaties. Laten we kijken of we een betere indicatie kunnen krijgen door een spreidingsdiagram van het pakket en de prijs te visualiseren en vervolgens de voorspellingen te gebruiken om een lijn van beste fit te overlayen.\n",
|
|
"\n",
|
|
"Dit betekent dat we de testset moeten voorbereiden en verwerken om de pakketkolom te coderen en deze vervolgens te koppelen aan de voorspellingen die door ons model zijn gemaakt.\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": [
|
|
"Geweldig! Zoals je kunt zien, generaliseert het lineaire regressiemodel de relatie tussen een pakket en de bijbehorende prijs niet echt goed.\n",
|
|
"\n",
|
|
"🎃 Gefeliciteerd, je hebt zojuist een model gemaakt dat kan helpen de prijs van een paar soorten pompoenen te voorspellen. Jouw pompoenveld voor de feestdagen zal prachtig zijn. Maar je kunt waarschijnlijk een beter model maken!\n",
|
|
"\n",
|
|
"## 5. Bouw een polynomiaal regressiemodel\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/linear-polynomial.png\"\n",
|
|
" width=\"800\"/>\n",
|
|
" <figcaption>Infographic door Dasani Madipalli</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!--{width=\"800\"}-->\n"
|
|
],
|
|
"metadata": {
|
|
"id": "HOCqJXLTwtWI"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Soms heeft onze data geen lineaire relatie, maar willen we toch een uitkomst voorspellen. Polynomiale regressie kan ons helpen voorspellingen te doen voor meer complexe niet-lineaire relaties.\n",
|
|
"\n",
|
|
"Neem bijvoorbeeld de relatie tussen het pakket en de prijs in onze pompoen-dataset. Hoewel er soms een lineaire relatie is tussen variabelen - hoe groter de pompoen qua volume, hoe hoger de prijs - kunnen deze relaties soms niet worden weergegeven als een vlak of rechte lijn.\n",
|
|
"\n",
|
|
"> ✅ Hier zijn [nog wat voorbeelden](https://online.stat.psu.edu/stat501/lesson/9/9.8) van data die polynomiale regressie kunnen gebruiken\n",
|
|
">\n",
|
|
"> Kijk nog eens naar de relatie tussen Variëteit en Prijs in de vorige grafiek. Lijkt deze spreidingsplot noodzakelijkerwijs geanalyseerd te moeten worden met een rechte lijn? Misschien niet. In dit geval kun je polynomiale regressie proberen.\n",
|
|
">\n",
|
|
"> ✅ Polynomen zijn wiskundige uitdrukkingen die kunnen bestaan uit één of meer variabelen en coëfficiënten\n",
|
|
"\n",
|
|
"#### Train een polynomiaal regressiemodel met behulp van de trainingsset\n",
|
|
"\n",
|
|
"Polynomiale regressie creëert een *gebogen lijn* om niet-lineaire data beter te modelleren.\n",
|
|
"\n",
|
|
"Laten we kijken of een polynomiaal model beter presteert bij het maken van voorspellingen. We volgen een procedure die enigszins lijkt op wat we eerder hebben gedaan:\n",
|
|
"\n",
|
|
"- Maak een recept dat de preprocessing-stappen specificeert die op onze data moeten worden uitgevoerd om deze klaar te maken voor modellering, zoals: het coderen van voorspellers en het berekenen van polynomen van graad *n*\n",
|
|
"\n",
|
|
"- Bouw een modelspecificatie\n",
|
|
"\n",
|
|
"- Bundel het recept en de modelspecificatie in een workflow\n",
|
|
"\n",
|
|
"- Maak een model door de workflow te fitten\n",
|
|
"\n",
|
|
"- Evalueer hoe goed het model presteert op de testdata\n",
|
|
"\n",
|
|
"Laten we aan de slag gaan!\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": [
|
|
"#### Evalueer de prestaties van het model\n",
|
|
"\n",
|
|
"👏👏Je hebt een polynomiaal model gebouwd, laten we voorspellingen maken op de testset!\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, laten we evalueren hoe het model presteerde op de test_set met behulp van `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": [
|
|
"🤩🤩 Veel betere prestaties.\n",
|
|
"\n",
|
|
"De `rmse` is gedaald van ongeveer 7 naar ongeveer 3, wat aangeeft dat de fout tussen de werkelijke prijs en de voorspelde prijs is verminderd. Je kunt dit *losjes* interpreteren als dat verkeerde voorspellingen gemiddeld ongeveer \\$3 fout zijn. De `rsq` is gestegen van ongeveer 0,4 naar 0,8.\n",
|
|
"\n",
|
|
"Al deze statistieken geven aan dat het polynomiale model veel beter presteert dan het lineaire model. Goed gedaan!\n",
|
|
"\n",
|
|
"Laten we kijken of we dit kunnen visualiseren!\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": [
|
|
"Je kunt een gebogen lijn zien die beter bij je gegevens past! 🤩\n",
|
|
"\n",
|
|
"Je kunt dit nog vloeiender maken door een polynomiale formule door te geven aan `geom_smooth`, zoals dit:\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": [
|
|
"Net zoals een vloeiende curve!🤩\n",
|
|
"\n",
|
|
"Hier is hoe je een nieuwe voorspelling zou maken:\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": [
|
|
"De voorspelling van het `polynomial model` is logisch, gezien de spreidingsdiagrammen van `price` en `package`! En als dit een beter model is dan het vorige, kijkend naar dezelfde gegevens, moet je rekening houden met deze duurdere pompoenen!\n",
|
|
"\n",
|
|
"🏆 Goed gedaan! Je hebt twee regressiemodellen gemaakt in één les. In het laatste deel over regressie leer je over logistische regressie om categorieën te bepalen.\n",
|
|
"\n",
|
|
"## **🚀Uitdaging**\n",
|
|
"\n",
|
|
"Test verschillende variabelen in dit notebook om te zien hoe correlatie overeenkomt met de nauwkeurigheid van het model.\n",
|
|
"\n",
|
|
"## [**Quiz na de les**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/14/)\n",
|
|
"\n",
|
|
"## **Review & Zelfstudie**\n",
|
|
"\n",
|
|
"In deze les hebben we geleerd over Lineaire Regressie. Er zijn andere belangrijke soorten regressie. Lees meer over Stepwise, Ridge, Lasso en Elasticnet technieken. Een goede cursus om meer te leren is de [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning).\n",
|
|
"\n",
|
|
"Als je meer wilt leren over het gebruik van het geweldige Tidymodels-framework, bekijk dan de volgende bronnen:\n",
|
|
"\n",
|
|
"- Tidymodels website: [Aan de slag met Tidymodels](https://www.tidymodels.org/start/)\n",
|
|
"\n",
|
|
"- Max Kuhn en Julia Silge, [*Tidy Modeling with R*](https://www.tmwr.org/)*.*\n",
|
|
"\n",
|
|
"###### **BEDANKT AAN:**\n",
|
|
"\n",
|
|
"[Allison Horst](https://twitter.com/allison_horst?lang=en) voor het maken van de geweldige illustraties die R toegankelijker en aantrekkelijker maken. Vind meer illustraties in haar [galerij](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**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, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in zijn oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor cruciale informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor eventuele misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.\n"
|
|
]
|
|
}
|
|
]
|
|
} |