V předešlé hodině jsme se vyhýbali programování, jak jen se to dalo. Teď už si ale chceš také sama vše vyzkoušet. Abys mohla úlohu rozmyšlenou v domácím úkolu naprogramovat, projdeme si nejdůležitější funkce, které budeš potřebovat.
Především budeme používat knihovnu Sciki-learn a samozrejmě také pandas. Potřebné věci projdeme na příkladu.
import pandas as pd
import numpy as np
np.random.seed(42)
☑ výběr vstupních proměnných ☑ rozdělení na trénovací a testovací data ☑ chybějící hodnoty ☑ kategorické hodnoty ☑ přeškálování / normování hodnot |
Na začátku vždy bude potřeba připravit data. Čištění dat a použití knihovny pandas už bys měla ovládat, zaměříme se jen na věci, které jsou specifické pro strojové učení.
Načíst data tedy umíš.
df_platy = pd.read_csv("static/salaries.csv", index_col=0)
df_platy.sample(10)
Pro predikci použijeme jako příznaky rank
, discipline
, yrs.since.phd
, yrs.service
a sex
,
predikovat budeme hodnotu salary
.
Pro učení potřebujeme všechny hondoty převést na čísla (float
). Pokud by data obsahovala chybějící
hodnoty, nejjednodušší řešení je takové řádky zahodit. (Bonus: pokud bys měla data s větším množstvím
chybějících hodnot, podívej se na možnosti sklearn.impute)
Důležité je vypořádat se s kategorickými hodnotami. Sloupce obsahující hodnoty typu Boolean nebo dvě hodnoty (např. muž/žena), lze snadno převést na hodnoty $[0,1]$.
df_platy = df_platy.replace({"Male": 0, "Female": 1})
df_platy.sample(10)
Pro kategorické proměnné s více možnostmi použijeme tzv. onehot encoding.
Např. sloupec rank
obsahuje hodnoty Prof
, AsstProf
a AssocProf
. K zakódování pomocí onehot encoding potřebujeme tři sloupce:
Původní hodnota | Kód |
---|---|
Prof | 1 0 0 |
AsstProf | 0 1 0 |
AssocProf | 0 0 1 |
Knihovna Scikitlearn nabízí sklearn.preprocessing.OneHotEncoder, při práci s pandas však můžeme použít rovnou metodu get_dummies. (Pozn. dummies proto, že nám přibudou pomocné proměnné (sloupce), které se označují jako dummy variables.)
df_platy = pd.get_dummies(df_platy)
df_platy
Poslední krok předzpracování bývá přeškálování hodnot. Je to už ale zásah do dat, který využívá hodnot celé množiny. Proto by nebylo fér používat pro něj i část, která bude později sloužit na testování. Je nejvyšší čas, oddělit testovací množinu.
V teorii strojového učení se vstupy modelu (příznaky, vstupní proměnné) typicky označují písmenem X
a výstupy písmenem y
. Řada programátorů toto používá i k označování proměnných v kódu.
X
představuje matici (neboli tabulku), kde každý řádek odpovídá jednomu datovému vzorku a každý sloupec jednomu příznaku (vstupní proměnné). y
je vektor, neboli jeden sloupec s odezvou.
Na vyzobnutí odezvy může hodit metoda pop. Její nevýhodou je ale nemožnost opakovaně spouštět buňku.
#y = df_platy.pop("salary")
#X = df_platy
y = df_platy["salary"]
X = df_platy.drop(columns=["salary"])
print(X.columns)
print(y.name)
X.head()
y.head()
Zbývá data rozdělit na trénovací a testovací. K tomu slouží metoda train_test_split.
Data nám rozdělí náhodně na trénovací a testovací sadu. Velikost testovací množiny můžeme specifikovat parametrem test_size
, jeho defaultní hodnota je 0.25
, t. j. 25%.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
Přeškálování není vždy nutné, ale některým modelům to může pomoci. Využijeme StandardScaler.
StandardScaler nám hodnoty přeškáluje, aby zhruba odpovídaly normálnímu rozdělení. Některé algoritmy to předpokládají. Může se pak např. stát, že příznak (sloupeček), která má výrazně větší rozptyl než ostatní, je brán jako významnější.
from sklearn.preprocessing import StandardScaler
priznaky_ke_konverzi = ["yrs.since.phd", "yrs.service"]
transformace = StandardScaler()
# just to get rid of SettingWithCopyWarning
X_train = X_train.copy()
X_test = X_test.copy()
X_train.loc[:, priznaky_ke_konverzi] = transformace.fit_transform(X_train[priznaky_ke_konverzi])
X_test.loc[:, priznaky_ke_konverzi] = transformace.transform(X_test[priznaky_ke_konverzi])
X_train.sample(10)
Můžeme přejít k samotnému učení. Vybereme si model. Přehled modelů najdeš v sekci Supervised learnig.
Na regresi můžeš použít:
Na klasifikační úlohy (ke kterým se dostaneme v příští hodině) využiješ:
Vytvoříme instanci vybraného modelu (jde nám teď jen o způsob použití knihovny, vezmeme nejjednodušší lineární regresi):
from sklearn.linear_model import LinearRegression
model = LinearRegression()
Model natrénujeme na trénovací množině:
model.fit(X_train, y_train)
Natrénovaný model typicky chceme použít k ohodnocení nějakých nových datových vzorků, k tomu máme metodu predict
. Zavolejme ji jak na trénovací, tak na testovací data.
train_predikce = model.predict(X_train)
test_predikce = model.predict(X_test)
Vypišme si prvních deset testovacích vzorků a jejich predikce:
print(f"skutečný plat predicke platu ")
for i in range(10):
print(f"{y_test.iloc[i]:>10.2f} {test_predikce[i]:>10.2f}")
Můžeme využít funkci score
, která nám vrátí hodnotu $R^2$ metriky:
print("R2 na trénovací množině: ", model.score(X_train, y_train))
print("R2 na testovací množině: ", model.score(X_test, y_test))
Funkce pro všechny možné metriky najdeš v sklearn.metrics. (nyní nás zajímají regresní metriky)
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
MAE_train = mean_absolute_error(y_train, train_predikce)
MAE_test = mean_absolute_error(y_test, test_predikce)
MSE_train = mean_squared_error(y_train, train_predikce)
MSE_test = mean_squared_error(y_test, test_predikce)
R2_train = r2_score(y_train, train_predikce)
R2_test = r2_score(y_test, test_predikce)
print(" Trénovací data Testovací data")
print(f"MSE {MSE_train:>14.3f} {MSE_test:>14.3f}")
print(f"MAE {MAE_train:>14.3f} {MAE_test:>14.3f}")
print(f"R2 {R2_train:>14.3f} {R2_test:>14.3f}")
Někdy si potřebujeme naučený model uchovat na další použití. Model lze uložit do souboru a zase načíst pomocí pickle
.
Kujme pikle:
import pickle
with open("model.pickle", "wb") as soubor:
pickle.dump(model, soubor)
with open("model.pickle", "rb") as soubor:
staronovy_model = pickle.load(soubor)
staronovy_model.score(X_test, y_test)
volba vhodného modelu a jeho hyper-parametrů se skrývá pod klíčovým slovem model selection. Knihovna Scikit-learn obsahuje různé pomůcky k ulehčení toho výběru. Přesahuje to ale rámec tohoto kurzu, narazíš-li na to toho téma při samostudiu, pročti si sklear.model_selection.
v příkladu výše jsme použili různé transformace nad daty a pak teprve tvorbu modelu. Až budeš v těchto věcech zběhlejší, bude se ti hodit propojit tyto věci dohromady. K tomu slouží tzv. pipeline.