Einleitung

Klassifizierungsmodelle machen auf Grund historischer Daten Vorhersagen darüber, ob ein zukünftiger Fall zu einer bestimmten Gruppe gehören wird oder nicht. Ein Beispiel dafür wäre angesichts der Erfahrungen aus der Vergangenheit Vorhersagen zu treffen, ob ein bestimmtes Ereignis eintreten wird oder nicht. Es gibt dafür vielfältige Anwendungsbeispiele, etwa Vorhersagen ob

2019 erschien mit mlr3 eine Gruppe von Machine-Learning-Bibliotheken, die es einfacher machen, verschiedene Klassifizierungsalgorithmen in der statistischen Programmierumgebung R einzusetzen. Die folgende Einführung folgt größtenteils diesem Tutorial

Der ursprüngliche Datensatz ist auf dem UCI Machine Learning Repository verfügbar, wo sich auch eine kurze Beschreibung der Daten befindet. Er besteht aus Daten eines deutschen Kreditinstituts aus dem Jahr 1994, das für 1000 Kredite eine Einstufung (gut oder schlecht) enthält sowie demographische und andere Informationen zum Kreditnehmer und Informationen zum Kredit selber. Das Ziel ist die Klassifizierung eines Kredits als gut oder schlecht auf Grund der anderen Variablen vorherzusagen. Wir arbeiten im Folgenden mit einer überarbeiteten Version des Datensatzes, die in der Bibliothek rchallenge enthalten ist.

Wir benötigen neben mlr3 noch einige weitere Bibliotheken. Folgende Bibliotheken müssen installiert und geladen sein:

Daten

Wir laden zunächst den Datensatz “german” aus der Bibliothekt rchallenge und lassen uns seine Struktur mit str() anzeigen.

## Datensatz laden
data("german", package = "rchallenge")
str(german)
## 'data.frame':    1000 obs. of  21 variables:
##  $ status                 : Factor w/ 4 levels "no checking account",..: 1 2 4 1 1 4 4 2 4 2 ...
##  $ duration               : int  6 48 12 42 24 36 24 36 12 30 ...
##  $ credit_history         : Factor w/ 5 levels "delay in paying off in the past",..: 5 3 5 3 4 3 3 3 3 5 ...
##  $ purpose                : Factor w/ 11 levels "others","car (new)",..: 4 4 7 3 1 7 3 2 4 1 ...
##  $ amount                 : int  1169 5951 2096 7882 4870 9055 2835 6948 3059 5234 ...
##  $ savings                : Factor w/ 5 levels "unknown/no savings account",..: 5 1 1 1 1 5 3 1 4 1 ...
##  $ employment_duration    : Factor w/ 5 levels "unemployed","< 1 yr",..: 5 3 4 4 3 3 5 3 4 1 ...
##  $ installment_rate       : Ord.factor w/ 4 levels ">= 35"<"25 <= ... < 35"<..: 4 2 2 2 3 2 3 2 2 4 ...
##  $ personal_status_sex    : Factor w/ 4 levels "male : divorced/separated",..: 3 2 3 3 3 3 3 3 1 4 ...
##  $ other_debtors          : Factor w/ 3 levels "none","co-applicant",..: 1 1 1 3 1 1 1 1 1 1 ...
##  $ present_residence      : Ord.factor w/ 4 levels "< 1 yr"<"1 <= ... < 4 yrs"<..: 4 2 3 4 4 4 4 2 4 2 ...
##  $ property               : Factor w/ 4 levels "unknown / no property",..: 1 1 1 2 4 4 2 3 1 3 ...
##  $ age                    : int  67 22 49 45 53 35 53 35 61 28 ...
##  $ other_installment_plans: Factor w/ 3 levels "bank","stores",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ housing                : Factor w/ 3 levels "for free","rent",..: 2 2 2 3 3 3 2 1 2 2 ...
##  $ number_credits         : Ord.factor w/ 4 levels "1"<"2-3"<"4-5"<..: 2 1 1 1 2 1 1 1 1 2 ...
##  $ job                    : Factor w/ 4 levels "unemployed/unskilled - non-resident",..: 3 3 2 3 3 2 3 4 2 4 ...
##  $ people_liable          : Factor w/ 2 levels "0 to 2","3 or more": 1 1 2 2 2 2 1 1 1 1 ...
##  $ telephone              : Factor w/ 2 levels "no","yes (under customer name)": 2 1 1 1 1 2 1 2 1 1 ...
##  $ foreign_worker         : Factor w/ 2 levels "no","yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ credit_risk            : Factor w/ 2 levels "good","bad": 1 2 1 1 2 1 1 1 1 2 ...

Das Ergebnis von str() zeigt uns, dass der Datensatz aus 1000 Beobachtungen besteht und 21 Variablen beinhaltet, die im Folgenden mit ihrem Namen (z.B. credit_history), dem Datentyp (Factor, int) und ein paar Beispielen beschrieben sind. Factor bezieht sich auf kategoriale Variablen mit einer bestimmten Anzahl an Ausprägungen (levels). int steht für integer - also eine numerische Variable bestehend aus ganzen Zahlen. Die Variable age gibt etwa das Alter des Kreditnehmers in Jahren an.

Mit skim() können wir uns einen genaueren Eindruck der Daten verschaffen.

skim(german)
Data summary
Name german
Number of rows 1000
Number of columns 21
_______________________
Column type frequency:
factor 18
numeric 3
________________________
Group variables None

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
status 0 1 FALSE 4 …: 394, no : 274, …: 269, 0<=: 63
credit_history 0 1 FALSE 5 no : 530, all: 293, exi: 88, cri: 49
purpose 0 1 FALSE 10 fur: 280, oth: 234, car: 181, car: 103
savings 0 1 FALSE 5 unk: 603, …: 183, …: 103, 100: 63
employment_duration 0 1 FALSE 5 1 <: 339, >= : 253, 4 <: 174, < 1: 172
installment_rate 0 1 TRUE 4 < 2: 476, 25 : 231, 20 : 157, >= : 136
personal_status_sex 0 1 FALSE 4 mal: 548, fem: 310, fem: 92, mal: 50
other_debtors 0 1 FALSE 3 non: 907, gua: 52, co-: 41
present_residence 0 1 TRUE 4 >= : 413, 1 <: 308, 4 <: 149, < 1: 130
property 0 1 FALSE 4 bui: 332, unk: 282, car: 232, rea: 154
other_installment_plans 0 1 FALSE 3 non: 814, ban: 139, sto: 47
housing 0 1 FALSE 3 ren: 713, for: 179, own: 108
number_credits 0 1 TRUE 4 1: 633, 2-3: 333, 4-5: 28, >= : 6
job 0 1 FALSE 4 ski: 630, uns: 200, man: 148, une: 22
people_liable 0 1 FALSE 2 0 t: 845, 3 o: 155
telephone 0 1 FALSE 2 no: 596, yes: 404
foreign_worker 0 1 FALSE 2 no: 963, yes: 37
credit_risk 0 1 FALSE 2 goo: 700, bad: 300

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
duration 0 1 20.90 12.06 4 12.0 18.0 24.00 72 ▇▇▂▁▁
amount 0 1 3271.26 2822.74 250 1365.5 2319.5 3972.25 18424 ▇▂▁▁▁
age 0 1 35.55 11.38 19 27.0 33.0 42.00 75 ▇▆▃▁▁

Der Datensatz enthält 18 kategoriale und drei numerische Variablen. Keine der Variablen enhält fehlende Werte. Für die kategorialen Daten wird die Anzahl der Ausprägungen (also die levels) sowie die häufigsten Werte angegeben. Für die numerischen Variablen gibt skim() eine Zusammenfassung (inkl. arithmetisches Mittel, Median, Standardabweichung) sowie ein kleines Histogramm aus. Das durchschnittliche Alter der Kreditnehmer beträgt etwa 35,5 Jahre mit einer Standardabweichgun von 11,4. Die Altersverteilung ist rechts-schief, es gibt mehr jüngere als ältere Kreditnehmer. Der Betrag liegt zwischen 250 und 18 424, mit einem Median von 2 320. 75% der Kredite liegen unter einem Betrag von 3 972.

Vorbereitung der Klassifizierung

Um mit mlr3 maschinelles Lernen - in diesem Fall für ein Klassifizierungsproblem - durchzuführen, müssen wir zunächst das Problem genau definieren. Dazu benötigen wir verschiedene Komponenten:

Zunächst definieren wir die Aufgabe mit der Methode new, die wir dann einem neuen Objekt namens task zuweisen: wir möchten die Variable credit_risk mit dem Datensatz german vorhersagen, dabei handelt es sich um ein Klassifizierungsproblem (TaskClassif). Dem Ganzen geben wir den Namen “GermanCredit” und lassen uns dann die Zusammenfassung unseres neu angelegten Objektes task ausgeben.

task <- TaskClassif$new("GermanCredit", german, target = "credit_risk")
task
## <TaskClassif:GermanCredit> (1000 x 21)
## * Target: credit_risk
## * Properties: twoclass
## * Features (20):
##   - fct (14): credit_history, employment_duration, foreign_worker,
##     housing, job, other_debtors, other_installment_plans,
##     people_liable, personal_status_sex, property, purpose, savings,
##     status, telephone
##   - int (3): age, amount, duration
##   - ord (3): installment_rate, number_credits, present_residence

Als nächstes bestimmen wir den Algorithmus, den wir nutzen wollen. Eine Liste der aktuell via mlr3 verfügbaren Algorithmen ist in mlr_learners enthalten.

mlr_learners
## <DictionaryLearner> with 29 stored values
## Keys: classif.cv_glmnet, classif.debug, classif.featureless,
##   classif.glmnet, classif.kknn, classif.lda, classif.log_reg,
##   classif.multinom, classif.naive_bayes, classif.nnet, classif.qda,
##   classif.ranger, classif.rpart, classif.svm, classif.xgboost,
##   regr.cv_glmnet, regr.featureless, regr.glmnet, regr.kknn, regr.km,
##   regr.lm, regr.ranger, regr.rpart, regr.svm, regr.xgboost,
##   surv.cv_glmnet, surv.glmnet, surv.ranger, surv.xgboost

Da wir ein Klassifikationsproblem lösen möchten, kommen prinzipiell alle classif-Algorithmen in Frage.

Wir benutzen zunächst eine logistische Regression. Bevor der Algorithmus zum Einsatz kommt, muss er mit lrn() initialisiert werden. Danach lassen wir uns die Eigenschaften unseres neu initialisierten Algorithmus anzeigen.

## Initialisierung
learner_logreg <- lrn("classif.log_reg")
print(learner_logreg)
## <LearnerClassifLogReg:classif.log_reg>
## * Model: -
## * Parameters: list()
## * Packages: stats
## * Predict Type: response
## * Feature types: logical, integer, numeric, character, factor, ordered
## * Properties: twoclass, weights

Da der Algorithmus noch nicht trainiert wurde, gibt es noch kein Modell. mlr3 greift auf andere Bibliotheken (packages) zurück, die die eigentlichen Algorithmen beinhalten. In diesem Fall kommt der Algorithmus aus der Bibliothek stats. Er ist (standardmäßig) so eingestellt, dass die Vorhersage eine Klasse/Gruppe ist (und nicht etwa die Wahrscheinlichkeit für eine Klasse). Die Prädiktorvariablen (features) können verschiedene Datentypen umfassen, u.a. auch integer, factor und ordered - also die Datentypen in unserem Datensatz. Der Algorithmus ist geeignet für binäre Zielvariablen (twoclass) und kann auch mit gewichteten Datensätzen arbeiten (weights).

Modelltraining

Ein Standardverfahren im maschinellen Lernen ist es, den ursprünglichen Datensatz zufällig in zwei Teile aufzuteilen. Anhand des Trainingsdatensatzes (häufig 80% der ursprünglichen Daten) lernt der Algorithmus und anhand des Testdatensatzes (häufig die restlichen 20%) wird die Prognosegüte geschätzt. Den vollständigen Datensatz für das Modelltraining und die Modellevaluation zu benutzen würde zu irreführenden Ergebnissen führen, da wir ja wissen wollen, wie gut der Algorithmus Vorhersagen für neue Daten macht, nicht für Daten, die er bereits kennt.

Dazu ziehen wir mit sample() eine Zufallsstichprobe der Zeilennummern (row_ids) unseres Datensatzes, der in task enthalten ist. Die Stichprobe soll aus 80% der Beobachtungen, also der Zeilen des Datensatzes (nrow), bestehen. Das Resultat train_set besteht aus den Zeilennummern der Beobachtungen des Ursprungsdatensatzes, die für das Modelltraining genutzt werden sollen. Als Testdatensatz wollen wir die verbleibenden Zeilennummern nehmen, also die Zeilennummern (row_ids) aus task, die nicht in train_set enthalten sind. Dazu nutzen wir die Funktion setdiff().

## Aufteilung Training/Test
train_set <- sample(task$row_ids, 0.8 * task$nrow)
test_set <- setdiff(task$row_ids, train_set)
head(train_set)
## [1] 125 292 312 577  39 951
length(train_set)
## [1] 800

Mit head() können wir uns die ersten Zeilennummern als Beispiele ausgeben lassen und mit Hilfe von length() sehen wir, dass train_set aus 800 Zahlen besteht.

Das Modelltraining erfolgt mit Hilfe der Methode train. Neben der Aufgabe task geben wir auch train_set als Parameter für row_ids ein, um nur die Beobachtungen zu benutzen, die unseren Trainingsdatensatz bilden. Das trainierte Modell ist anschließend in learner_logreg$model verfügbar. Da es sich um ein Modell aus der stats-Bibliothek handelt, können wir es uns mit Hilfe der Funktion summary anzeigen lassen.

## Modelltraining
learner_logreg$train(task, row_ids = train_set)
summary(learner_logreg$model)
## 
## Call:
## stats::glm(formula = task$formula(), family = "binomial", data = task$data(), 
##     model = FALSE)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.2864  -0.6717  -0.3571   0.6581   2.8576  
## 
## Coefficients:
##                                                             Estimate Std. Error
## (Intercept)                                                2.684e+00  1.182e+00
## age                                                       -2.741e-02  1.097e-02
## amount                                                     9.895e-05  5.013e-05
## credit_historycritical account/other credits elsewhere     2.074e-02  6.362e-01
## credit_historyno credits taken/all credits paid back duly -5.185e-01  4.908e-01
## credit_historyexisting credits paid back duly till now    -5.317e-01  5.410e-01
## credit_historyall credits at this bank paid back duly     -1.356e+00  4.875e-01
## duration                                                   3.052e-02  1.057e-02
## employment_duration< 1 yr                                  4.259e-01  5.191e-01
## employment_duration1 <= ... < 4 yrs                        5.121e-02  4.912e-01
## employment_duration4 <= ... < 7 yrs                       -5.993e-01  5.358e-01
## employment_duration>= 7 yrs                               -5.580e-02  4.989e-01
## foreign_workeryes                                         -1.629e+00  6.927e-01
## housingrent                                               -4.657e-01  2.640e-01
## housingown                                                -4.606e-01  5.534e-01
## installment_rate.L                                         7.163e-01  2.442e-01
## installment_rate.Q                                         2.991e-03  2.218e-01
## installment_rate.C                                         7.187e-02  2.281e-01
## jobunskilled - resident                                    2.170e-01  8.282e-01
## jobskilled employee/official                               1.095e-01  8.008e-01
## jobmanager/self-empl/highly qualif. employee               1.650e-01  8.050e-01
## number_credits.L                                           1.515e-01  9.144e-01
## number_credits.Q                                          -3.518e-01  7.394e-01
## number_credits.C                                           1.801e-01  5.248e-01
## other_debtorsco-applicant                                  6.052e-01  4.688e-01
## other_debtorsguarantor                                    -7.270e-01  4.968e-01
## other_installment_plansstores                             -4.480e-01  4.873e-01
## other_installment_plansnone                               -6.326e-01  2.674e-01
## people_liable3 or more                                     1.983e-01  2.812e-01
## personal_status_sexfemale : non-single or male : single   -3.863e-01  4.452e-01
## personal_status_sexmale : married/widowed                 -8.643e-01  4.343e-01
## personal_status_sexfemale : single                        -3.519e-01  5.193e-01
## present_residence.L                                        2.103e-01  2.389e-01
## present_residence.Q                                       -4.834e-01  2.251e-01
## present_residence.C                                        2.552e-01  2.262e-01
## propertycar or other                                       9.285e-02  2.925e-01
## propertybuilding soc. savings agr. / life insurance        1.082e-01  2.730e-01
## propertyreal estate                                        7.737e-01  4.829e-01
## purposecar (new)                                          -1.931e+00  4.342e-01
## purposecar (used)                                         -7.855e-01  2.934e-01
## purposefurniture/equipment                                -9.432e-01  2.869e-01
## purposeradio/television                                   -7.918e-01  8.837e-01
## purposedomestic appliances                                -5.089e-01  6.674e-01
## purposerepairs                                             2.043e-01  4.636e-01
## purposevacation                                           -1.558e+01  5.794e+02
## purposeretraining                                         -9.052e-01  3.775e-01
## purposebusiness                                           -2.524e+00  9.378e-01
## savings... < 100 DM                                       -4.051e-01  3.296e-01
## savings100 <= ... < 500 DM                                -2.823e-01  4.155e-01
## savings500 <= ... < 1000 DM                               -1.472e+00  6.035e-01
## savings... >= 1000 DM                                     -1.064e+00  3.157e-01
## status... < 0 DM                                          -3.796e-01  2.492e-01
## status0<= ... < 200 DM                                    -8.881e-01  4.171e-01
## status... >= 200 DM / salary for at least 1 year          -1.872e+00  2.658e-01
## telephoneyes (under customer name)                        -1.286e-01  2.323e-01
##                                                           z value Pr(>|z|)    
## (Intercept)                                                 2.270 0.023198 *  
## age                                                        -2.499 0.012460 *  
## amount                                                      1.974 0.048390 *  
## credit_historycritical account/other credits elsewhere      0.033 0.973995    
## credit_historyno credits taken/all credits paid back duly  -1.056 0.290809    
## credit_historyexisting credits paid back duly till now     -0.983 0.325700    
## credit_historyall credits at this bank paid back duly      -2.781 0.005423 ** 
## duration                                                    2.887 0.003891 ** 
## employment_duration< 1 yr                                   0.820 0.411982    
## employment_duration1 <= ... < 4 yrs                         0.104 0.916968    
## employment_duration4 <= ... < 7 yrs                        -1.118 0.263365    
## employment_duration>= 7 yrs                                -0.112 0.910942    
## foreign_workeryes                                          -2.351 0.018713 *  
## housingrent                                                -1.764 0.077718 .  
## housingown                                                 -0.832 0.405236    
## installment_rate.L                                          2.933 0.003354 ** 
## installment_rate.Q                                          0.013 0.989241    
## installment_rate.C                                          0.315 0.752700    
## jobunskilled - resident                                     0.262 0.793275    
## jobskilled employee/official                                0.137 0.891237    
## jobmanager/self-empl/highly qualif. employee                0.205 0.837595    
## number_credits.L                                            0.166 0.868404    
## number_credits.Q                                           -0.476 0.634231    
## number_credits.C                                            0.343 0.731462    
## other_debtorsco-applicant                                   1.291 0.196770    
## other_debtorsguarantor                                     -1.463 0.143371    
## other_installment_plansstores                              -0.919 0.357904    
## other_installment_plansnone                                -2.366 0.017999 *  
## people_liable3 or more                                      0.705 0.480715    
## personal_status_sexfemale : non-single or male : single    -0.868 0.385524    
## personal_status_sexmale : married/widowed                  -1.990 0.046562 *  
## personal_status_sexfemale : single                         -0.677 0.498091    
## present_residence.L                                         0.880 0.378801    
## present_residence.Q                                        -2.148 0.031748 *  
## present_residence.C                                         1.128 0.259267    
## propertycar or other                                        0.317 0.750917    
## propertybuilding soc. savings agr. / life insurance         0.397 0.691731    
## propertyreal estate                                         1.602 0.109136    
## purposecar (new)                                           -4.448 8.68e-06 ***
## purposecar (used)                                          -2.677 0.007427 ** 
## purposefurniture/equipment                                 -3.288 0.001010 ** 
## purposeradio/television                                    -0.896 0.370277    
## purposedomestic appliances                                 -0.763 0.445748    
## purposerepairs                                              0.441 0.659392    
## purposevacation                                            -0.027 0.978541    
## purposeretraining                                          -2.398 0.016499 *  
## purposebusiness                                            -2.691 0.007117 ** 
## savings... < 100 DM                                        -1.229 0.218951    
## savings100 <= ... < 500 DM                                 -0.679 0.496887    
## savings500 <= ... < 1000 DM                                -2.439 0.014722 *  
## savings... >= 1000 DM                                      -3.371 0.000749 ***
## status... < 0 DM                                           -1.523 0.127718    
## status0<= ... < 200 DM                                     -2.129 0.033241 *  
## status... >= 200 DM / salary for at least 1 year           -7.042 1.89e-12 ***
## telephoneyes (under customer name)                         -0.553 0.579996    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 982.41  on 799  degrees of freedom
## Residual deviance: 700.34  on 745  degrees of freedom
## AIC: 810.34
## 
## Number of Fisher Scoring iterations: 14

Mit unserem trainierten Modell können wir nun Vorhersagen für den Testdatensatz machen. Da der Algorithmus diese Daten nicht für das Modelltraining benutzt hat, sind dies für ihn neue Daten und eine Vorhersage im landläufige Sinne, auch wenn es sich um historische Daten handelt und wir das Ergebnis kennen.

preds_logreg = learner_logreg$predict(task, row_ids = test_set)
preds_logreg
## <PredictionClassif> for 200 observations:
##     row_id truth response
##          6  good     good
##          8  good     good
##         10   bad      bad
## ---                      
##        990  good     good
##        993  good     good
##        999   bad      bad

Wenn die Vorhersagen (response) für eine Beobachtung (row_id) mit den bekannten Werten aus dem Datensatz (truth) übereinstimmen, dann war die Vorhersage korrekt.

Modellevaluation

Es gibt verschiedene Gütemaße für binäre Klassifikationsmodells, die eine von zwei möglichen Klassen vorhersagen. Viele davon bauen auf der Wahrheitsmatrix (confusion matrix) auf. Diese fasst zusammen, wieviele Vorhersagen mit der historischen Wahrheit übereinstimmen. Die beiden möglichen Klassen werden generisch als positiv (z.B. Zahlungsausfall) bzw. negativ (z.B. kein Zahlungsausfall) bezeichnet. In unserem Beispiel haben wir die Klassen “good” (gutes Kreditrisiko) und “bad” (schlechtes Kreditrisiko).

preds_logreg$confusion
##         truth
## response good bad
##     good  121  22
##     bad    22  35

Die 121 Fälle in der obersten Zeile links sind etwa Vorhersagen eines guten Kreditrisikos, die korrekt waren.

mlr3 enthält eine Reihe von Maßen für die Prognosegüte für Klassifikationsmodelle (classif).

mlr_measures
## <DictionaryMeasure> with 54 stored values
## Keys: classif.acc, classif.auc, classif.bacc, classif.bbrier,
##   classif.ce, classif.costs, classif.dor, classif.fbeta, classif.fdr,
##   classif.fn, classif.fnr, classif.fomr, classif.fp, classif.fpr,
##   classif.logloss, classif.mbrier, classif.mcc, classif.npv,
##   classif.ppv, classif.prauc, classif.precision, classif.recall,
##   classif.sensitivity, classif.specificity, classif.tn, classif.tnr,
##   classif.tp, classif.tpr, debug, oob_error, regr.bias, regr.ktau,
##   regr.mae, regr.mape, regr.maxae, regr.medae, regr.medse, regr.mse,
##   regr.msle, regr.pbias, regr.rae, regr.rmse, regr.rmsle, regr.rrse,
##   regr.rse, regr.rsq, regr.sae, regr.smape, regr.srho, regr.sse,
##   selected_features, time_both, time_predict, time_train

Ein einfaches Gütemaß ist die Treffergenauigkeit (accuracy): der Anteil der Vorhersagen, der korrekt war. Mit msr() können wir auf das Maß (measure) für die Treffergenauigkeit (classif.acc) zugreifen. Die Methode score des Objektes mit den Vorhersagen (preds_logreg) gibt das entsprechende Gütemaß für diese Vorhersagen aus.

msr_acc <- msr("classif.acc")
preds_logreg$score(msr_acc)
## classif.acc 
##        0.78

In diesem Fall erreichte die logistische Regression im Testdatensatz eine Treffergenauigkeit von 0.78.

Alternative Gütemaße sind