germeval03-sent-wordvec-rf-tune

textmining
datawrangling
germeval
prediction
tidymodels
sentiment
string
random-forest
tune
Published

December 4, 2023

Aufgabe

Erstellen Sie ein prädiktives Modell für Textdaten. Nutzen Sie Sentiments und TextFeatures im Rahmen von Feature-Engineering. Nutzen Sie außerdem deutsche Word-Vektoren für das Feature-Engineering.

Als Lernalgorithmus verwenden Sie Random Forest (Ranger). Tunen Sie mtry und min_n.

Daten

Verwenden Sie die GermEval-2018-Daten.

Die Daten sind unter CC-BY-4.0 lizensiert. Author: Wiegand, Michael (Spoken Language Systems, Saarland University (2010-2018), Leibniz Institute for the German Language (since 2019)),

Die Daten sind auch über das R-Paket PradaData zu beziehen.

library(tidyverse)
data("germeval_train", package = "pradadata")
data("germeval_test", package = "pradadata")

AV und UV

Die AV lautet c1. Die (einzige) UV lautet: text.

Hinweise

  • Orientieren Sie sich im Übrigen an den allgemeinen Hinweisen des Datenwerks.
  • Nutzen Sie Tidymodels.
  • Nutzen Sie das sentiws Lexikon.
  • ❗ Achten Sie darauf, die Variable c2 zu entfernen bzw. nicht zu verwenden.











Lösung

Setup

d_train <-
  germeval_train |> 
  select(id, c1, text)
library(tictoc)
library(tidymodels)
#library(syuzhet)
library(beepr)
library(finetune)  # anova race
library(lobstr)  # object size
library(visdat)  # footprint of csv
#data("sentiws", package = "pradadata")

Eine Vorlage für ein Tidymodels-Pipeline findet sich hier.

Learner/Modell

mod <-
  rand_forest(mode = "classification",
             mtry =  tune(), 
             min_n = tune()
             )

Gebackenen Datensatz als neue Grundlage

Wir importieren den schon an anderer Stelle aufbereiteten Datensatz. Das hat den Vorteil (hoffentlich), das die Datenvolumina viel kleiner sind. Die Arbeit des Feature Engineering wurde uns schon abgenommen.

d_train <-
  read_csv("https://raw.githubusercontent.com/sebastiansauer/Datenwerk2/main/data/germeval/germeval_train_recipe_wordvec_senti.csv")
Rows: 5009 Columns: 121
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr   (1): c1
dbl (120): id, emo_count, schimpf_count, emoji_count, textfeature_text_copy_...

ℹ 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.
vis_dat(d_train) +
  # remove axis labels:
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank() 
        )

d_test_baked <- read_csv("https://raw.githubusercontent.com/sebastiansauer/Datenwerk2/main/data/germeval/germeval_test_recipe_wordvec_senti.csv")
Rows: 3532 Columns: 121
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr   (1): c1
dbl (120): id, emo_count, schimpf_count, emoji_count, textfeature_text_copy_...

ℹ 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.

Plain-Rezept

rec <- 
  recipe(c1 ~ ., data = d_train)

Neuer Workflow mit plainem Rezept

wf <-
  workflow() |> 
  add_recipe(rec) |> 
  add_model(mod)

Parallelisierung über mehrere Kerne

library(parallel)
all_cores <- detectCores(logical = FALSE)

library(doFuture)
registerDoFuture()
cl <- makeCluster(3)
plan(cluster, workers = cl)

Achtung: Viele Kerne brauchen auch viel Speicher.

Tune/Resample/Fit

tic()
fit_wordvec_senti_rf <-
  tune_race_anova(
    wf,
    grid = 50,
    resamples = vfold_cv(d_train, v = 5),
    control = control_race(verbose_elim = TRUE))
i Creating pre-processing data to finalize unknown parameter: mtry
ℹ Racing will maximize the roc_auc metric.
ℹ Resamples are analyzed in a random order.
ℹ Fold5: 47 eliminated; 3 candidates remain.

ℹ Fold2: 0 eliminated; 3 candidates remain.
toc()
3554.225 sec elapsed
beep()

Objekt-Größe:

lobstr::obj_size(fit_wordvec_senti_rf)
5.06 MB

Beste Performance

autoplot(fit_wordvec_senti_rf)

show_best(fit_wordvec_senti_rf)
Warning: No value of `metric` was given; metric 'roc_auc' will be used.
# A tibble: 3 × 8
   mtry min_n .metric .estimator  mean     n std_err .config              
  <int> <int> <chr>   <chr>      <dbl> <int>   <dbl> <chr>                
1     3    33 roc_auc binary     0.796     5 0.00659 Preprocessor1_Model01
2     4    24 roc_auc binary     0.796     5 0.00716 Preprocessor1_Model09
3     8    14 roc_auc binary     0.793     5 0.00722 Preprocessor1_Model43
best_params <- select_best(fit_wordvec_senti_rf)
Warning: No value of `metric` was given; metric 'roc_auc' will be used.

Finalisieren

best_params <- select_best(fit_wordvec_senti_rf)
Warning: No value of `metric` was given; metric 'roc_auc' will be used.
tic()
wf_finalized <- finalize_workflow(wf, best_params)
lastfit_rf <- fit(wf_finalized, data = d_train)
toc()
5.687 sec elapsed

Test-Set-Güte

tic()
preds <-
  predict(lastfit_rf, new_data = d_test_baked)
toc()
0.342 sec elapsed
d_test <-
  d_test_baked |> 
  bind_cols(preds) |> 
  mutate(c1 = as.factor(c1))
my_metrics <- metric_set(accuracy, f_meas)
my_metrics(d_test,
           truth = c1,
           estimate = .pred_class)
# A tibble: 2 × 3
  .metric  .estimator .estimate
  <chr>    <chr>          <dbl>
1 accuracy binary         0.686
2 f_meas   binary         0.177