Nauč se Python > Kurzy > Datový kurz PyLadies > Strojové učení - úvod, regrese > Regrese - základní metriky

Regresní metriky

V úvodním příkladu s krajinou jsme si metriku vymýšleli sami. Existuje samozřejmě řada standardním metrik, které se k hodnocení modelů používají. Uvedeme si přehled nejnámějších z nich:

($y = y_1, \ldots, y_N$ jsou reálné hodnoty odezvy, $\hat{y} = \hat{y}_1, \ldots, \hat{y}_N$ jsou predikované hodnoty)

  • MAE (Mean absolute error) - průměr absolutních hodnot odchylek požadovaných výstupů od predikovaných výstupů

    $$ MAE(y, \hat{y}) = \frac{1}{N} \sum_{i=1}^N |y_i - \hat{y}_i| $$

  • MSE (Mean squared error) - průměr sumy čterců odchylek požadovaných výstupů od predikovaných výstupů

    $$ MSE(y, \hat{y}) = \frac{1}{N} \sum_{i=1}^N (y_i - \hat{y}_i)^2 $$

  • $R^2$ score (Koeficient determinace) - koeficient determinace vyjadřuje, jaký podíl variability závislé proměnné (odezvy) model vyjadřuje. Dá se interpretovat tak, že říká, jak moc je náš model lepší než konstantní baseline daná jako průměr. $$ R^2(y, \hat{y}) = 1 - \frac{MSE(model)}{MSE(baseline)} = 1 - \frac{MSE(y, \hat{y})}{MSE(y, \bar{y})}; \qquad \mbox{kde}\quad \bar{y} = \frac{1}{N} \sum_{i=1}^N y_i $$ $R^2$ skóre dosahuje maximálně hodnoty jedna, což znamená dokonalou predikci.

Pokud nemáš ráda vzorečky, nelam si s nimi hlavu. Podívej se na následující příklad:

Vytvoříme dataframe, který bude obsahovat odezvy (sloupec "správně") a predikované hodnoty (sloupec "predikováno"). Pro jednoduchost hodnoty odezvy vygenerujeme náhodně a jejich "predikce" vytvoříme tak, že k těmto odezvám přičteme náhodné číslo z intervalu (-10, 10).

In [1]:
import pandas as pd 
import random

df = pd.DataFrame({"správně": [random.randint(10, 90) for _ in range(10)]})
df["predikováno"] = df["správně"].apply(lambda predikovano: predikovano + random.randint(-10, 10))
df
Out[1]:
správně predikováno
0 24 23
1 61 51
2 26 22
3 86 95
4 78 85
5 10 19
6 40 44
7 84 92
8 25 28
9 83 92

Spočteme si MSE, MAE a $R^2$ skóre. Napišme si na to funkci:

In [2]:
def spocti_metriky(skutecna_odezva, predikovano):
    chyby = pd.DataFrame()
    chyby["absolutní_chyba"] = abs(skutecna_odezva - predikovano)
    chyby["chyba_na_druhou"] = (skutecna_odezva - predikovano)**2
    baseline = skutecna_odezva.mean()
    chyby["chyba_na_druhou_baseline"] = (skutecna_odezva - baseline)**2

    MSE = chyby["chyba_na_druhou"].mean()
    MAE = chyby["absolutní_chyba"].mean()
    R2 = 1 - MSE/chyby["chyba_na_druhou_baseline"].mean()
    
    return chyby, MSE, MAE, R2
In [3]:
df_chyby, MSE, MAE, R2 = spocti_metriky(df["správně"], df["predikováno"])
# zobrazme si tabulku spolu s odpovídajícími chybami  
pd.concat([df, df_chyby], axis="columns")
Out[3]:
správně predikováno absolutní_chyba chyba_na_druhou chyba_na_druhou_baseline
0 24 23 1 1 767.29
1 61 51 10 100 86.49
2 26 22 4 16 660.49
3 86 95 9 81 1176.49
4 78 85 7 49 691.69
5 10 19 9 81 1738.89
6 40 44 4 16 136.89
7 84 92 8 64 1043.29
8 25 28 3 9 712.89
9 83 92 9 81 979.69
In [4]:
# vypišme si hodnoty metrik
print(f"MSE = {MSE}")
print(f"MAE = {MAE}")
print(f"R2 = {R2}")
MSE = 49.8
MAE = 6.4
R2 = 0.9377040567418471

Z tabulky výše i ze zobrazených chyb vidíme, že MSE daleko více penalizuje větší chyby.

Zkusme si ještě nasimulovat řešení, které bude poměrně přesné (náhodná odchylka, kterou přičítáme, bude z intervalu (-1,1)).

In [5]:
df2 = pd.DataFrame()
df2["správně"] = df["správně"]
df2["predikováno"] = df2["správně"].apply(lambda predikovano: predikovano + random.uniform(-1., 1.))
df2
Out[5]:
správně predikováno
0 24 24.786030
1 61 61.307684
2 26 25.145564
3 86 86.599629
4 78 78.037996
5 10 10.434443
6 40 40.929654
7 84 83.041753
8 25 25.498867
9 83 83.748930

Opět zorbrazme chyby:

In [6]:
df2_chyby, MSE_2, MAE_2, R2_2 = spocti_metriky(df2["správně"], df2["predikováno"])
pd.concat([df2, df2_chyby], axis="columns")
Out[6]:
správně predikováno absolutní_chyba chyba_na_druhou chyba_na_druhou_baseline
0 24 24.786030 0.786030 0.617843 767.29
1 61 61.307684 0.307684 0.094669 86.49
2 26 25.145564 0.854436 0.730061 660.49
3 86 86.599629 0.599629 0.359555 1176.49
4 78 78.037996 0.037996 0.001444 691.69
5 10 10.434443 0.434443 0.188741 1738.89
6 40 40.929654 0.929654 0.864256 136.89
7 84 83.041753 0.958247 0.918237 1043.29
8 25 25.498867 0.498867 0.248868 712.89
9 83 83.748930 0.748930 0.560897 979.69

A vypišme si hodnoty metrik:

In [7]:
print(f"MSE = {MSE_2:.3f} (minule: {MSE})")   # :.2f znamená float na dvě desetinná místa
print(f"MAE = {MAE_2:.3f} (minule: {MAE})")
print(f"R2  = {R2_2:.3f} (minule: {R2})")
MSE = 0.458 (minule: 49.8)
MAE = 0.616 (minule: 6.4)
R2  = 0.999 (minule: 0.9377040567418471)

Vidíme, že hodnoty MSE a MAE jsou teď výrazně menší než minule. To je proto, že "predikované" hodnoty jsou velmi blízko hodnotám skutečným. $R^2$ skóre vyšlo naopak vyšší (blíže jedné).

Pozn.: Pozor, nyní vyšla hodnota MAE vyšší než MSE, to je proto, že jednotlivé chyby jsou teď menší než jedna (mocnina je menší než absolutní hodnota).

In [ ]:


Toto je stránka lekce z kurzu, který probíhá nebo proběhl naživo s instruktorem.