library(tidyverse)
library(tidymodels)
diamonds-tidymodels01
ds1
tidymodels
statlearning
string
Aufgabe
Finden Sie ein möglichst “gutes” prädiktives Modell zur Vorhersage des Diamantenpreises im Datensatz diamonds
!
Gegenstand dieser Aufgabe ist die Modellierung; Datenvorverarbeitug (wie explorative Datenanalyse) steht nicht im Fokus.
Hinweise:
- Verwenden Sie die Methoden aus
tidymodels
. - Hohe Modellgüte (“gutes Modell”) sei definiert über \(R^2\), RMSE und MAE
- Verwenden Sie verschiedene Algorithmen (lineare Modell, kNN, …) und verschiedene Rezepte.
- Resampling und Tuning ist hier noch nicht nötig.s
Der Datensatz ist hier zu beziehen. Außerdem ist er Teil von ggplot2 bzw. des Tidyverse und daher mit data()
zu laden, wenn das entsprechende Paket vorhanden ist.
Lösung
Setup
Daten laden:
data(diamonds, package = "ggplot2")
Oder so:
<- read_csv("https://vincentarelbundock.github.io/Rdatasets/csv/ggplot2/diamonds.csv") diamonds
Rows: 53940 Columns: 11
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): cut, color, clarity
dbl (8): rownames, carat, depth, table, price, x, y, z
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Train- vs. Testdaten:
<- initial_split(diamonds, strata = price)
d_split
<- training(d_split)
d_train <- testing(d_split) d_test
Modelle:
<-
lin_mod linear_reg()
<-
knn_mod nearest_neighbor(mode = "regression")
Hilfe zu kNN findet sich z.B. hier.
Rezepte:
<-
rec1 recipe(price ~ ., data = d_train) %>%
update_role(1, new_role = "id") %>%
step_naomit() %>%
step_log(all_outcomes())
Rezept prüfen (preppen und backen)
<-
rec1_prepped %>%
rec1 prep()
rec1_prepped
── Recipe ──────────────────────────────────────────────────────────────────────
── Inputs
Number of variables by role
outcome: 1
predictor: 9
id: 1
── Training information
Training data contained 40453 data points and no incomplete rows.
── Operations
• Removing rows with NA values in: <none> | Trained
• Log transformation on: price | Trained
<-
d_train_baked bake(rec1_prepped, new_data = d_train)
Einen Überblick zu steps
findet sich z.B. hier.
Rollen-Definitionen in Tidymodels-Rezepten kann man hier nachlesen.
<-
rec2 recipe(price ~ ., data = d_train) %>%
update_role(1, new_role = "id") %>%
step_impute_knn() %>%
step_log(all_outcomes())
Workflows:
<-
wf1 workflow() %>%
add_recipe(rec1) %>%
add_model(lin_mod)
<-
wf2 %>%
wf1 update_model(knn_mod)
Fitting
<-
fit1 %>%
wf1 fit(d_train)
fit1
══ Workflow [trained] ══════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: linear_reg()
── Preprocessor ────────────────────────────────────────────────────────────────
2 Recipe Steps
• step_naomit()
• step_log()
── Model ───────────────────────────────────────────────────────────────────────
Call:
stats::lm(formula = ..y ~ ., data = data)
Coefficients:
(Intercept) carat cutGood cutIdeal cutPremium
-2.913222 -0.540689 0.091189 0.155213 0.108878
cutVery Good colorE colorF colorG colorH
0.124711 -0.061150 -0.091230 -0.157784 -0.259018
colorI colorJ clarityIF claritySI1 claritySI2
-0.386879 -0.528595 1.093164 0.607816 0.440536
clarityVS1 clarityVS2 clarityVVS1 clarityVVS2 depth
0.817124 0.751466 1.000923 0.935170 0.050243
table x y z
0.009026 1.156195 0.012648 0.040728
Fitten des Test-Samples
<-
fit1_test %>%
wf1 last_fit(d_split)
fit1_test
# Resampling results
# Manual resampling
# A tibble: 1 × 6
splits id .metrics .notes .predictions .workflow
<list> <chr> <list> <list> <list> <list>
1 <split [40453/13487]> train/test sp… <tibble> <tibble> <tibble> <workflow>
Modellgüte
collect_metrics(fit1_test)
# A tibble: 2 × 4
.metric .estimator .estimate .config
<chr> <chr> <dbl> <chr>
1 rmse standard 0.159 Preprocessor1_Model1
2 rsq standard 0.976 Preprocessor1_Model1
De-logarithmieren, wenn man Vorhersagen in den Rohwerten haben möchte:
collect_predictions(fit1_test) %>%
head()
# A tibble: 6 × 5
id .pred .row price .config
<chr> <dbl> <int> <dbl> <chr>
1 train/test split 5.81 5 5.81 Preprocessor1_Model1
2 train/test split 5.86 6 5.82 Preprocessor1_Model1
3 train/test split 5.89 8 5.82 Preprocessor1_Model1
4 train/test split 6.10 9 5.82 Preprocessor1_Model1
5 train/test split 5.85 21 5.86 Preprocessor1_Model1
6 train/test split 5.90 25 5.87 Preprocessor1_Model1
<-
d_test_w_preds collect_predictions(fit1_test) %>%
mutate(pred_raw = exp(.pred))
head(d_test_w_preds)
# A tibble: 6 × 6
id .pred .row price .config pred_raw
<chr> <dbl> <int> <dbl> <chr> <dbl>
1 train/test split 5.81 5 5.81 Preprocessor1_Model1 334.
2 train/test split 5.86 6 5.82 Preprocessor1_Model1 352.
3 train/test split 5.89 8 5.82 Preprocessor1_Model1 360.
4 train/test split 6.10 9 5.82 Preprocessor1_Model1 447.
5 train/test split 5.85 21 5.86 Preprocessor1_Model1 346.
6 train/test split 5.90 25 5.87 Preprocessor1_Model1 364.
Categories:
- ds1
- tidymodels
- statlearning
- string