This repository has been archived on 2026-06-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cas-pml/SL/aufgaben/template/2_Code/4.4 Validierung und mehr - Performance Metriken.ipynb
T
2026-05-21 14:16:30 +02:00

196 KiB

Feature Engineering

Klassifikation

Regression

Validierung und mehr

Sampling und Resampling

Validierungstechniken

Performancemetriken

Klassifikation

Einführung und Vorbereitung

In [1]:
import sys
sys.path.append('./')
In [2]:
## import libraries
import pandas as pd
import seaborn as sns
import matplotlib
import numpy as np
import matplotlib.pyplot as plt; sns.set()
%matplotlib inline

## load data
datapath = '../3_data'
from os import chdir; chdir(datapath)
from bfh_cas_pml import prep_data
X_train, X_test, y_train, y_test = prep_data('bank_data_prep.csv', 'y', seed = 1234)
In [3]:
## create different types of predictions
from sklearn.ensemble import RandomForestClassifier 
model = RandomForestClassifier(random_state=1234)
model.fit(X_train, y_train) 

## predictions: using .predict() and .predict_proba()
y_pred_c = model.predict(X_test)
y_pred_n = np.where(y_pred_c == 'yes', 1, 0)
y_pred_p = model.predict_proba(X_test)
Cell:
[Cell type raw - unsupported, skipped]
In [4]:
## comparison of y_pred_c, y_pred_n and y_pred_p
pred_df = pd.DataFrame({
    'y_pred_c': y_pred_c,
    'y_pred_n' : y_pred_n,
    'y_pred_p_0': y_pred_p[:,0],
    'y_pred_p_1': y_pred_p[:,1]
})
print(pred_df.head())
  y_pred_c  y_pred_n  y_pred_p_0  y_pred_p_1
0      yes         1        0.09        0.91
1      yes         1        0.24        0.76
2      yes         1        0.39        0.61
3       no         0        0.99        0.01
4       no         0        0.99        0.01
In [5]:
## for later use: the same with y_test
y_test_n = np.where(y_test == 'yes', 1, 0)
In [6]:
## check
print(pd.DataFrame({
    'y_test': y_test,
    'y_test_n': y_test_n
}).head())
     y_test  y_test_n
2809    yes         1
4052    yes         1
658     yes         1
786      no         0
6675     no         0

Metriken für nicht numerische Klassen

In [7]:
## example of a multi class classification
iris_data = sns.load_dataset('iris')
print(iris_data.info())
iris_X = iris_data.drop('species', axis=1)
iris_y = iris_data['species']
#print(iris_X)
#print(iris_y)

## test - train - split
from sklearn.model_selection import train_test_split
iris_X_train, iris_X_test, iris_y_train, iris_y_test, = train_test_split(
    iris_X,
    iris_y,
    train_size=2/3,
    random_state=1234)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   sepal_length  150 non-null    float64
 1   sepal_width   150 non-null    float64
 2   petal_length  150 non-null    float64
 3   petal_width   150 non-null    float64
 4   species       150 non-null    object 
dtypes: float64(4), object(1)
memory usage: 6.0+ KB
None
In [8]:
from sklearn.tree import DecisionTreeClassifier
iris_model = DecisionTreeClassifier(random_state=1234)
iris_model.fit(iris_X_train, iris_y_train)
iris_y_pred = iris_model.predict(iris_X_test)
In [9]:
## confusion matrix
#print(pd.crosstab(iris_y_pred, iris_y_test))
pd.crosstab(iris_y_pred, iris_y_test).style.background_gradient(axis=None) ## for all cells
Out [9]:
species setosa versicolor virginica
row_0      
setosa 17 0 0
versicolor 0 16 0
virginica 0 1 16
In [10]:
## accuracy aus confusion matrix
print(np.diag(pd.crosstab(iris_y_test, iris_y_pred)).sum() / iris_y_test.size)

## accuracy_score from sklearn.metrics
from sklearn.metrics import accuracy_score
print(accuracy_score(iris_y_pred, iris_y_test))

## model internal scorer
print(iris_model.score(iris_X_test, iris_y_test))
0.98
0.98
0.98
In [11]:
## classification error, calculated as 1 - accuracy_score)
print(1 - accuracy_score(iris_y_pred, iris_y_test))
0.020000000000000018
In [12]:
## other multiclass scorer: balanced_accuracy_score
from sklearn.metrics import balanced_accuracy_score
print(balanced_accuracy_score(iris_y_test, iris_y_pred))
0.9803921568627452
In [13]:
## other multiclass scorer: cohen_kappa_score
from sklearn.metrics import cohen_kappa_score
print(cohen_kappa_score(iris_y_test, iris_y_pred))
0.97000599880024

Metriken für binär numerische Klassen

In [14]:
## confusion matrix of numerical targets
print(pd.crosstab(y_pred_n, y_test_n)) ## confusion matrix
print()
print(pd.crosstab(y_pred_n, y_test_n).\
      reindex(columns=[1, 0], index=[1, 0])) ## reindexed
col_0     0     1
row_0            
0      1461   142
1       274  1410

col_0     1     0
row_0            
1      1410   274
0       142  1461
In [15]:
## extract confusion matrix cells
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test_n, y_pred_n).ravel() ## .ravel() in order to flatten array
print('tp =', tp)
print('fn =', fn)
print('fp =', fp)
print('tn =', tn)
tp = 1410
fn = 142
fp = 274
tn = 1461
In [16]:
## precision - positive predictive value - PPV
ppv = tp / (tp + fp)
print(ppv)
from sklearn.metrics import precision_score
print(precision_score(y_test_n, y_pred_n))
0.83729216152019
0.83729216152019
In [17]:
## recall, hit rate, sensitivity, or true positive rate (TPR)
tpr = tp / (tp + fn)
print(tpr)
from sklearn.metrics import recall_score
print(recall_score(y_test_n, y_pred_n))
0.9085051546391752
0.9085051546391752
In [18]:
## F1
f1 = 2 * (ppv * tpr) / (ppv + tpr)
print(f1)
from sklearn.metrics import f1_score
print(f1_score(y_test_n, y_pred_n))
0.8714462299134734
0.8714462299134734
In [19]:
## classification_report
from sklearn.metrics import classification_report
print(classification_report(y_test_n, y_pred_n))
              precision    recall  f1-score   support

           0       0.91      0.84      0.88      1735
           1       0.84      0.91      0.87      1552

    accuracy                           0.87      3287
   macro avg       0.87      0.88      0.87      3287
weighted avg       0.88      0.87      0.87      3287

In [20]:
## with not numerical labels
print(classification_report(y_test, y_pred_c))
              precision    recall  f1-score   support

          no       0.91      0.84      0.88      1735
         yes       0.84      0.91      0.87      1552

    accuracy                           0.87      3287
   macro avg       0.87      0.88      0.87      3287
weighted avg       0.88      0.87      0.87      3287

In [21]:
## a multiclass classification, data prepared in 4.4.1.2
print(classification_report(iris_y_test, iris_y_pred))
              precision    recall  f1-score   support

      setosa       1.00      1.00      1.00        17
  versicolor       1.00      0.94      0.97        17
   virginica       0.94      1.00      0.97        16

    accuracy                           0.98        50
   macro avg       0.98      0.98      0.98        50
weighted avg       0.98      0.98      0.98        50

In [22]:
## apply precision_score and recall_score for multiclass models
from sklearn.metrics import precision_score, recall_score, f1_score
print('precision_score:', precision_score(iris_y_test, iris_y_pred, average = 'weighted'))
print('recall_score:   ', recall_score(iris_y_test, iris_y_pred, average = 'weighted'))
print('f1_score:       ', f1_score(iris_y_test, iris_y_pred, average = 'weighted'))
precision_score: 0.9811764705882353
recall_score:    0.98
f1_score:        0.98
In [23]:
## recall, sensitivity, TPR
tpr = tp / (tp + fn)
print(tpr)
from sklearn.metrics import recall_score
print(recall_score(y_test_n, y_pred_n))
0.9085051546391752
0.9085051546391752
In [24]:
## specificity, TNR (no sklearn function)
tnr = tn / (tn + fp)
print(tnr)
0.8420749279538905
In [25]:
## false positive rate, FPR: 1 - TNR (no sklearn function)
fpr = 1 - tnr 
print(fpr)
0.1579250720461095
In [26]:
## ROC AUC - part I (binary)
plt.figure(figsize=(5,4.5))
sns.lineplot(x=[0, fpr, 1], y=[0, tpr, 1])
plt.xlabel('fpr (1 - specificity)')
plt.ylabel('tpr (recall, sensitivity)')
ls = np.linspace(0, 1, 100)
plt.plot(ls, ls, color='r', linestyle='--')
plt.annotate('O', (fpr, tpr), ha='center', va='center')
plt.annotate('O 1', (-0.01, 1), ha='left', va='center', size=10)
plt.annotate('O 2', (0.3, 0.5), ha='left', va='center', size=10)
plt.annotate('O 3', (0.6, 0.1), ha='left', va='center', size=10);
In [27]:
## calculate the area under the curve
plt.figure(figsize=(5,4.5))
sns.lineplot(x=[0, fpr, 1], y=[0, tpr, 1])
plt.xlabel('fpr (1 - specificity)')
plt.ylabel('tpr (recall, sensitivity)')
ls = np.linspace(0, 1, 100)
plt.plot(ls, ls, color='r', linestyle='--')
plt.annotate('O', (fpr, tpr), ha='center', va='center')

## add polygons
x1 = [0, fpr, fpr, 0]
y1 = [0, tpr, 0, 0]
plt.fill(x1, y1, color='lightblue')
x2 = [fpr, fpr, 1, 1, fpr]
y2 = [0, tpr, 1, 0, 0]
plt.fill(x2, y2, color='palegreen');
In [28]:
## calculated from the values of the confusion matrix
print((fpr * tpr / 2) + ((1 - fpr) * ((tpr + 1) / 2)))
print((tpr - fpr + 1) / 2)
print(((tp / (tp + fn)) - (fp / (tn + fp)) + 1) / 2)
0.8752900412965329
0.8752900412965329
0.8752900412965329
In [29]:
## with functions from sklearn.metrics
from sklearn.metrics import roc_curve, auc
fpr_arr, tpr_arr, thresholds = roc_curve(y_test_n, y_pred_n)
print(auc(fpr_arr, tpr_arr))
0.8752900412965329

Metriken für Wahrscheinlichkeitswerte von Klassen

In [30]:
## a graphic comparision of the values from .predict() and .predict_proba()
f, axes = plt.subplots(nrows=1, ncols=2, figsize=(8, 3.5), sharex=False)
ax = sns.histplot(y_pred_n, bins=20, ax=axes[0])
ax = sns.histplot(y_pred_p[:,1], bins=20, ax=axes[1]);
In [31]:
## ROC AUC - Part 2 (cont)
print(pd.DataFrame({
    'y_pred_n': y_pred_n,
    'y_pred_p_1': y_pred_p[:, 1]
}).head())
   y_pred_n  y_pred_p_1
0         1        0.91
1         1        0.76
2         1        0.61
3         0        0.01
4         0        0.01
In [32]:
from sklearn.metrics import roc_curve
fpr_arr, tpr_arr, thresholds = roc_curve(y_test_n, y_pred_p[:, 1])
#auc_arr = (tpr_arr - fpr_arr + 1) / 2

results = pd.DataFrame({
    'thresholds' : thresholds,
    'tpr_arr': tpr_arr,
    'fpr_arr': fpr_arr #,
#    'auc_arr': auc_arr
})
print(results.head())
#print(results.tail())
   thresholds   tpr_arr   fpr_arr
0         inf  0.000000  0.000000
1        1.00  0.030928  0.000000
2        0.99  0.063144  0.000576
3        0.98  0.103093  0.001729
4        0.97  0.136598  0.005764
In [33]:
plt.figure(figsize=(5,4.5))
sns.lineplot(x=fpr_arr, y=tpr_arr)
plt.xlabel('fpr')
plt.ylabel('tpr');
In [34]:
from sklearn.metrics import auc
print('auc :', auc(fpr_arr, tpr_arr))
auc : 0.9363025119581688
Cell:
[Cell type raw - unsupported, skipped]
In [35]:
## a function from sklearn.metrics which draws an calculates roc auc directly
from sklearn.metrics import RocCurveDisplay
RocCurveDisplay.from_predictions(y_test_n, y_pred_p[:,1]);
In [36]:
## calc best_fpr and best_tpr
auc_arr = (tpr_arr - fpr_arr + 1) / 2
max_auc = max(auc_arr)
best_tpr = tpr_arr[auc_arr == max(auc_arr)][0]
best_fpr = fpr_arr[auc_arr == max(auc_arr)][0]
best_th = thresholds[auc_arr == max(auc_arr)][0]

plt.figure(figsize=(5,4.5))
sns.lineplot(x=fpr_arr, y=tpr_arr)
plt.xlabel('fpr')
plt.ylabel('tpr')
ls = np.linspace(0, 1, 100)
plt.plot(ls, ls, color='r', linestyle='--')
plt.plot([0, best_fpr], [0, best_tpr], color='black', lw=0.5)
plt.plot([best_fpr, 1], [best_tpr, 1], color='black', lw=0.5)
plt.annotate('O', (best_fpr, best_tpr), ha='center', va='center')
x1 = best_fpr - 0.15
x2 = best_fpr + 0.1
y1 = best_tpr - 0.15
y2 = best_tpr + 0.1
plt.plot([x1, x2], [y1, y2], color='r', linestyle='--');
In [37]:
print('best auc :', max(auc_arr))
print('best threshold :', thresholds[auc_arr == max(auc_arr)][0])
best auc : 0.881685619002347
best threshold : 0.41
In [38]:
## log_loss
from sklearn.metrics import log_loss
print(log_loss(y_test_n, y_pred_p))
0.30455787062978196
In [39]:
## also applicable to multiclass models
## see https://scikit-learn.org/stable/modules/model_evaluation.html#log-loss
## example of a multi class classification
iris_data = sns.load_dataset('iris')
iris_X = iris_data.drop('species', axis=1)
iris_y = iris_data['species']
from sklearn.model_selection import train_test_split
iris_X_train, iris_X_test, iris_y_train, iris_y_test, = train_test_split(
    iris_X,
    iris_y,
    train_size=2/3,
    random_state=1234)

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(random_state=1234)
model.fit(iris_X_train, iris_y_train)
iris_y_pred_p = model.predict_proba(iris_X_test)
print(iris_y_pred_p[0:5,:])

#iris_y_pred_p
from sklearn.metrics import log_loss
print(log_loss(iris_y_test, iris_y_pred_p))
[[0.   0.98 0.02]
 [0.   0.98 0.02]
 [0.   0.   1.  ]
 [1.   0.   0.  ]
 [0.   0.98 0.02]]
0.10952457826611424

Performancemetriken - Regression

Vorbereitung

In [40]:
## import libraries
import pandas as pd
import seaborn as sns
import matplotlib
import numpy as np
import matplotlib.pyplot as plt; sns.set()
%matplotlib inline

## load data
datapath = '../3_data'
from os import chdir; chdir(datapath)

from bfh_cas_pml import prep_data
X_train, X_test, y_train, y_test = prep_data('melb_data_prep.csv', 'Price', seed = 1234)

from sklearn.tree import DecisionTreeRegressor
model = DecisionTreeRegressor()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
In [41]:
print(pd.DataFrame({
    'y_test': y_test,
    'y_pred': y_pred
}).head())
          y_test     y_pred
18178  3400000.0   901000.0
16248  3625000.0  2100000.0
7472    565000.0   580000.0
11719  2525000.0  1680000.0
5228   1350000.0  1200000.0

Einige Scorer im Überblick

In [42]:
## mean_squared_error (mse)
from sklearn.metrics import mean_squared_error
print(mean_squared_error(y_test, y_pred))
169124790914.51215
In [43]:
## root_mean_squared_error (mse)
from sklearn.metrics import root_mean_squared_error
print(root_mean_squared_error(y_test, y_pred))
411247.8460910308
In [44]:
## mean_absolute_error (mae)
from sklearn.metrics import mean_absolute_error
print(mean_absolute_error(y_test, y_pred))
244061.39297558853
In [45]:
## mean_absolute_percentage_error (mape)
from sklearn.metrics import mean_absolute_percentage_error
print(mean_absolute_percentage_error(y_test, y_pred))
0.22599557388412617
In [46]:
## mean_squared_log_error (msle)
from sklearn.metrics import mean_squared_log_error
print(mean_squared_log_error(y_test, y_pred))
0.08469851350303957
In [47]:
## median_absolute_error (medae)
from sklearn.metrics import median_absolute_error
print(median_absolute_error(y_test, y_pred))
140000.0
In [48]:
## r2_score (r2)
from sklearn.metrics import r2_score
print(r2_score(y_test, y_pred))
0.5768009946090255