Obsah
1. Role aktivačních funkcí v neuronových sítích
2. Aktivační funkce používané v oblasti strojového učení
3. Aktivační funkce, které nejsou diferencovatelné
4. Diferencovatelné aktivační funkce
5. Rozdíly mezi funkcemi Tanh, Sigmoid a SoftSign
6. Aktivační funkce v knihovně scikit-learn
7. Skript pro zobrazení průběhů aktivačních funkcí
8. Specifikace typu aktivační funkce při konstrukci neuronové sítě
9. Matice záměn a přesnosti modelů založených na neuronové síti s různými aktivačními funkcemi
10. Jaké číslice nebyly rozpoznány jednotlivými neuronovými sítěmi?
11. Porovnání přesností všech čtyř neuronových sítí
12. Specifikace algoritmu pro trénink neuronové sítě
13. Skript, který použije různé algoritmy pro trénink neuronové sítě
14. Matice záměn a přesnosti modelů pro různé trénovací algoritmy
15. Jaké číslice nebyly rozpoznány jednotlivými neuronovými sítěmi?
16. Kombinace nejlepší aktivační funkce a nejlepšího algoritmu = nejlepší výsledky?
19. Repositář s demonstračními příklady
1. Role aktivačních funkcí v neuronových sítích
Připomeňme si nejprve, jak vlastně vypadá idealizovaný model neuronu, který je většinou v umělých neuronových sítích používán. Tento model si můžeme vizualizovat následovně:

Obrázek 1: Idealizovaný model neuronu.
Neuron tedy provádí tento výpočet:
y = f(w1x1 + w2x2 + … + wnxn)
Ve skutečnosti není stav neuronu pro n vstupů x1 až xn určen pouze n vahami w1 až wn. Musíme přidat ještě váhu w0, na kterou je připojena konstanta 1 (někdy se proto můžeme setkat s nákresem neuronové sítě, v níž se nachází speciální neurony bez vstupů a s jedničkou na výstupu). Model neuronu se přidáním nového vstupu nepatrně zkomplikuje:

Obrázek 2: Idealizovaný model neuronu s biasem.
Důležitá je však aktivační funkce, která zajistí, že výstup neuronu nebude pouhým součtem váhovaných vstupů, ale do celého výpočtu se navíc přidá vhodně zvolená nelinearita. Nejjednodušší aktivační funkce může pro vstupní hodnoty <0 vracet –1 a pro hodnoty ≥0 vracet 1, což vlastně říká, že je nutné dosáhnout určité hraniční hodnoty váženého součtu vstupů, aby byl neuron aktivován (tj. na výstup vyslal jedničku a nikoli –1). Ostatně právě zde znovu vidíme význam biasu, který onu hraniční hodnotu posunuje. Ovšem v praxi se setkáme i s dalšími typy aktivačních funkcí.
2. Aktivační funkce používané v oblasti strojového učení
Prozatím jsme v našich testovacích neuronových sítích používali pouze jeden výchozí typ aktivační funkce. Jednalo se konkrétně o funkci nazývanou ReLU neboli celým jménem REctified Linear Unit, která se v této oblasti používá již velmi dlouho. Mezi velké výhody této funkce patří velmi rychlý výpočet, což se pozitivně projeví v rozsáhlých neuronových sítích (rozpoznávání obrazu atd.), mezi určité nevýhody pak to, že není v celém svém oboru diferencovatelná. Ovšem k dispozici máme i mnoho dalších aktivačních funkcí, z nichž některé (konkrétně ty podporované knihovnou scikit-learn) budou popsány v navazujícím textu.
3. Aktivační funkce, které nejsou diferencovatelné
Nejprve si ve stručnosti popíšeme ty aktivační funkce, které nejsou diferencovatelné v celém svém rozsahu platnosti. Tyto funkce většinou obsahují buď jedno „koleno“ nebo dokonce jeden či dva skoky, což v praxi znamená, že se výstupní hodnota z neuronu může prudce změnit, a to i pro malé rozdíly na vstupu. V některých případech může být tato vlastnost neuronů užitečná, ovšem o to víc je chování sítě závislé na jejím správném natrénování. Mezi tyto funkce patří především:
Jméno funkce | Hodnoty | Základní vlastnosti |
---|---|---|
ReLU | f(x)=0 pro x≤0, f(x)=x pro x>0 | má jedno koleno při vstupu 0, velmi často používaná v praxi |
ReLU6 | f(x)=0 pro x≤0, f(x)=x pro 0<x<6, f(x)=6 pro x≥6 | má dvě kolena při vstupech 0 a 6, opět velmi často používaná v praxi |
HardTanh | f(x)=-1 pro x< –1, f(x)=1 pro x>1, jinak f(x)=x | funkce s lineárním průběhem pro –1≤x≤1, má dvě kolena |
ELU | f(x) = max(0, x) + min(0, α * (ex – 1)) | pro některé hodnoty α je diferencovatelná |
SoftShrink | f(x)=x-λ pro x>λ, f(x)=x+λ pro x< -λ, jinak f(x)=0 | funkce s lineárním průběhem pro x>λ a x< -λ, dvě kolena na hodnotách -λ a λ |
HardShrink | f(x)=x pro x< -λ a x>λ, jinak f(x)=0 | funkce s lineárním průběhem a dvěma skoky na hodnotách -λ a λ |
PReLU | podobné funkci ReLU, ale má volitelný sklon pro záporné hodnoty x | |
RReLU | podobné předchozí funkce, ale pro záporné hodnoty x je vstup náhodně posunut (jen v režimu tréninku) | |
AddConstant | f(x)=x+k | používá se například při ladění, k je skalární a neměnná hodnota |
MulConstant | f(x)=x*k | používá se například při ladění, k je skalární a neměnná hodnota |

Obrázek 3: Průběh funkcí ReLU, ReLU6, HardTanh, SoftShrink i HardShrink.

Obrázek 4: Průběh funkcí ReLU, ReLU6, HardTanh, SoftShrink i HardShrink, zvětšení na okolí počátku souřadného systému.
4. Diferencovatelné aktivační funkce
Další funkce, které jsou v oblasti strojového učení často používány, jsou již diferencovatelné. Nejčastěji se v praxi setkáme s prvními dvěma funkcemi, tedy konkrétně s funkcí Sigmoid a Tanh:
Jméno funkce | Způsob výpočtu |
---|---|
Sigmoid | f(x) = 1 / (1 + e-x) = ex / (ex+1) |
Tanh | f(x) = (ex – e-x) / (ex + e-x) |
SoftMax | provede normalizaci vstupního tenzoru, provede výpočet fi(x) = exi – maxi(xi) / sumj expxj – max_i(xi) |
SoftMin | dtto, ale vypočte fi(x) = e-xi – maxi(-xi) / sumj e-xj – maxi(-xi) |
SoftPlus | fi(x) = 1/beta * log(1 + ebeta * xi) |
SoftSign | fi(x) = xi / (1+|xi|) |

Obrázek 5: Průběh funkce SoftPlus.
5. Rozdíly mezi funkcemi Tanh, Sigmoid a SoftSign
Funkce Tanh, Sigmoid a SoftSign sice mají podobný tvar křivky, ovšem jejich skutečný průběh je ve skutečnosti odlišný. O tom se můžeme velmi snadno přesvědčit, když si všechny funkce necháme vykreslit do jednoho grafu a budeme měnit rozsah hodnot na x-ové ose:

Obrázek 6: Průběh funkcí Tanh, Sigmoid a SoftSign pro rozsah vstupních hodnot < –5, 5>.
Vidíme, že se kromě tvaru průběhů funkce liší i obor hodnot.

Obrázek 7: Průběh funkcí Tanh, Sigmoid a SoftSign pro rozsah vstupních hodnot < –10, 10>.

Obrázek 8: Průběh funkcí Tanh, Sigmoid a SoftSign pro rozsah vstupních hodnot < –20, 20>.
6. Aktivační funkce v knihovně scikit-learn
Připomeňme si, že v knihovně scikit-learn se s neuronovými sítěmi pracuje stejně jako s ostatními modely; pouze se liší atributy těchto modelů, jejich hyperparametry a tím pádem i jejich konstruktory. K dispozici máme dva typy modelů/neuronových sítí, které jsou realizovány třídami nazvanými MLPClassifier (model pro klasifikaci) a MLPRegressor (model pro regresi). Při konstrukci instance těchto tříd, tj. při inicializaci modelů, můžeme oběma konstruktorům předat i nepovinný parametr activation, který může nabývat hodnot „identity“, „logistic“, „tanh“ nebo „relu“. První hodnota (jde o řetězec!) představuje lineární funkci y=x, hodnota „logistic“ odpovídá sigmoidu (viz předchozí text) a další dvě možné hodnoty již zajisté rozpoznáte sami.
7. Skript pro zobrazení průběhů aktivačních funkcí
Pro zobrazení průběhu aktivačních funkcí poněkud předběhneme obsah tohoto seriálu, protože využijeme framework Torch, který umožňuje výpočet hodnot těchto funkcí. Výsledek si pak můžeme nechat zobrazit pomocí Matplotlibu, což již dobře známe:
import matplotlib.pyplot as plt import torch import torch.nn as nn # hodnoty na x-ové ose x = torch.linspace(-4, 4, 200) # výpočet hodnot aktivačních funkcí relu = nn.ReLU()(x) tanh = nn.Tanh()(x) sigmoid = nn.Sigmoid()(x) # nový graf s průběhem tří aktivačních funkcí plt.plot(x, sigmoid, label="sigmoid") plt.plot(x, tanh, label="tanh") plt.plot(x, relu, label="ReLU") plt.ylim(-1.5, 2) # zobrazení legendy plt.legend() # uložení do souboru plt.savefig("activation_functions.png") # zobrazení v novém okně plt.show()

Obrázek 9: Průběh aktivačních funkcí, které využijeme v dalších demonstračních příkladech.
8. Specifikace typu aktivační funkce při konstrukci neuronové sítě
Jak jsme si již řekli v předchozím textu, knihovna scikit-learn nám umožňuje specifikovat čtyři typy aktivačních funkcí při konstrukci modelů MLPRegressor i MLPClassifier. Pokusme se nyní zjistit, jak (a zda vůbec) má volba aktivační funkce vliv na kvalitu předpovědí modelu natrénovaného pro rozpoznání číslic. Připravíme si tedy n-tici s názvy všech použitelných aktivačních funkcí:
activation_functions = ("identity", "logistic", "tanh", "relu")
Následně si pro každou s funkcí necháme vytvořit novou neuronovou síť, tu natrénujeme, zvalidujeme a necháme si odvodit matici záměn, přesnost modelu atd. Stále budeme používat stejná data, konkrétně datovou sadu s ručně nakreslenými číslicemi:
for activation_function in activation_functions: score = train_and_test_model(activation_function) scores.append(score)
Celý skript, který tuto operaci provede, bude vypadat následovně:
# Rozpoznání obrazu s využitím knihovny scikit-learn import matplotlib.pyplot as plt import numpy as np from sklearn.neural_network import MLPClassifier from sklearn.model_selection import train_test_split from sklearn.model_selection import cross_val_score from sklearn.metrics import ConfusionMatrixDisplay # Databáze ručně zapsaných číslic from sklearn.datasets import load_digits # načtení obrázků, s nimiž budeme dále pracovat digits = load_digits() # zjištění základních informací o obrázcích print("Description:", digits.DESCR) print("Data:", digits.data.shape) print("Obrázky:", digits.images.shape) # X je matice (feature matrix) X = digits.data # y je vektor (response vector) y = digits.target for_training = len(y) * 8 // 10 print("Vzorků pro trénink:", for_training) print("\n\n") # rozdělení dat trainX = X[:for_training] testX = X[for_training:] trainY = y[:for_training] testY = y[for_training:] def train_and_test_model(activation_function: str, show_results: bool = False): print(f"Neural network with activation function '{activation_function}'") # provést klasifikaci # konstrukce klasifikatoru # (s hyperparametrem) classifier = MLPClassifier(max_iter=5000, activation=activation_function) # vypocet skore scores = cross_val_score(classifier, X, y, cv=10, scoring="accuracy") avg_score = scores.mean() # vypsani prumerneho skore print("Accuracy:", avg_score) print() # trening modelu classifier.fit(trainX, trainY) class_names = digits.target_names # absolutni hodnoty disp = ConfusionMatrixDisplay.from_estimator( classifier, testX, testY, display_labels=class_names, cmap=plt.cm.Blues, normalize=None, ) # zobrazeni matice print(disp.confusion_matrix) print() # ulozeni vysledku plt.savefig(f"{activation_function}_confusion_matrix_abs.png") # vizualizace matice if show_results: plt.show() # relativni hodnoty disp = ConfusionMatrixDisplay.from_estimator( classifier, testX, testY, display_labels=class_names, cmap=plt.cm.Blues, normalize="true", ) # zobrazeni matice print(disp.confusion_matrix) # ulozeni vysledku plt.savefig(f"{activation_function}_confusion_matrix_rel.png") # vizualizace matice if show_results: plt.show() predicted_labels = classifier.predict(testX) images = digits.images[for_training:] fig = plt.figure(figsize=(6.4, 10.0)) # zobrazit patnáct výsledků wrong = 0 i = 0 while wrong < 30: predicted_digit = classifier.predict([testX[i]])[0] correct_digit = testY[i] if predicted_digit != correct_digit: image = images[i] wrong += 1 plt.subplot(6, 5, wrong) plt.axis("off") # zobrazení obrázku plt.imshow(image, cmap=plt.cm.gray_r, interpolation="nearest") # a přidání predikce - o jakou číslici se jedná plt.title(f"{predicted_digit} <> {correct_digit}") i += 1 # nenasli jsme vice cislic if i >= len(testX): break # nakonec vše uložíme a zobrazíme plt.savefig(f"{activation_function}_wrong_digits.png") if show_results: plt.show() print() print("-" * 70) return avg_score activation_functions = ("identity", "logistic", "tanh", "relu") scores = [] for activation_function in activation_functions: score = train_and_test_model(activation_function) scores.append(score) fig, ax = plt.subplots() ax.bar(activation_functions, scores) ax.set_ylabel("Model accuracy") ax.set_title("Activation function") plt.savefig("accuracy.png") plt.show()
9. Matice záměn modelů založených na neuronové síti s různými aktivačními funkcemi
Podívejme se nyní na vypočtené matice záměn pro modely založené na neuronových sítích, u nichž byly použity odlišné aktivační funkce:

Obrázek 10: Použita aktivační funkce „identity“, matice záměn s absolutními hodnotami.

Obrázek 11: Použita aktivační funkce „logistic“ (sigmoid), matice záměn s absolutními hodnotami.

Obrázek 12: Použita aktivační funkce „ReLU“, matice záměn s absolutními hodnotami.

Obrázek 13: Použita aktivační funkce „TanH“, matice záměn s absolutními hodnotami.
Stejné matice záměn, ovšem pro hodnoty relativní:

Obrázek 14: Použita aktivační funkce „identity“, matice záměn s relativními hodnotami.

Obrázek 15: Použita aktivační funkce „logistic“, matice záměn s relativními hodnotami.

Obrázek 16: Použita aktivační funkce „ReLU“, matice záměn s relativními hodnotami.

Obrázek 17: Použita aktivační funkce „TanH“, matice záměn s relativními hodnotami.
Výsledky v textové podobě:
Data: (1797, 64) Obrázky: (1797, 8, 8) Vzorků pro trénink: 1437 Neural network with activation function 'identity' Accuracy: 0.9276505276225947 [[33 0 0 0 1 0 1 0 0 0] [ 0 30 0 1 0 0 0 0 0 5] [ 0 0 35 0 0 0 0 0 0 0] [ 0 0 0 26 0 1 0 2 8 0] [ 0 0 0 0 34 0 0 0 0 3] [ 0 1 0 0 0 36 0 0 0 0] [ 0 0 0 0 0 0 37 0 0 0] [ 0 1 0 0 1 0 0 32 1 1] [ 0 2 0 0 0 0 0 1 30 0] [ 0 2 0 0 0 0 0 1 1 33]] [[0.94285714 0. 0. 0. 0.02857143 0. 0.02857143 0. 0. 0. ] [0. 0.83333333 0. 0.02777778 0. 0. 0. 0. 0. 0.13888889] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0.7027027 0. 0.02702703 0. 0.05405405 0.21621622 0. ] [0. 0. 0. 0. 0.91891892 0. 0. 0. 0. 0.08108108] [0. 0.02702703 0. 0. 0. 0.97297297 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 1. 0. 0. 0. ] [0. 0.02777778 0. 0. 0.02777778 0. 0. 0.88888889 0.02777778 0.02777778] [0. 0.06060606 0. 0. 0. 0. 0. 0.03030303 0.90909091 0. ] [0. 0.05405405 0. 0. 0. 0. 0. 0.02702703 0.02702703 0.89189189]] ---------------------------------------------------------------------- Neural network with activation function 'logistic' Accuracy: 0.9587895716945996 [[33 0 0 0 1 0 1 0 0 0] [ 0 31 0 0 0 0 0 0 0 5] [ 0 0 35 0 0 0 0 0 0 0] [ 0 0 1 28 0 2 0 1 5 0] [ 0 0 0 0 34 0 0 0 0 3] [ 0 0 0 0 0 37 0 0 0 0] [ 0 1 0 0 0 0 36 0 0 0] [ 0 0 0 0 0 0 0 35 1 0] [ 0 2 0 1 0 0 0 0 30 0] [ 0 0 0 0 0 2 0 1 1 33]] [[0.94285714 0. 0. 0. 0.02857143 0. 0.02857143 0. 0. 0. ] [0. 0.86111111 0. 0. 0. 0. 0. 0. 0. 0.13888889] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0.02702703 0.75675676 0. 0.05405405 0. 0.02702703 0.13513514 0. ] [0. 0. 0. 0. 0.91891892 0. 0. 0. 0. 0.08108108] [0. 0. 0. 0. 0. 1. 0. 0. 0. 0. ] [0. 0.02702703 0. 0. 0. 0. 0.97297297 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. 0.97222222 0.02777778 0. ] [0. 0.06060606 0. 0.03030303 0. 0. 0. 0. 0.90909091 0. ] [0. 0. 0. 0. 0. 0.05405405 0. 0.02702703 0.02702703 0.89189189]] ---------------------------------------------------------------------- Neural network with activation function 'tanh' Accuracy: 0.9510180012414648 [[33 0 0 0 1 0 1 0 0 0] [ 0 32 0 0 0 0 0 0 0 4] [ 0 0 35 0 0 0 0 0 0 0] [ 0 0 2 27 0 2 0 2 4 0] [ 0 0 0 0 34 0 0 0 1 2] [ 0 0 0 0 0 37 0 0 0 0] [ 0 1 0 0 0 0 36 0 0 0] [ 0 0 0 0 0 0 0 35 1 0] [ 1 2 0 1 1 1 0 0 27 0] [ 0 0 0 0 0 1 0 2 1 33]] [[0.94285714 0. 0. 0. 0.02857143 0. 0.02857143 0. 0. 0. ] [0. 0.88888889 0. 0. 0. 0. 0. 0. 0. 0.11111111] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0.05405405 0.72972973 0. 0.05405405 0. 0.05405405 0.10810811 0. ] [0. 0. 0. 0. 0.91891892 0. 0. 0. 0.02702703 0.05405405] [0. 0. 0. 0. 0. 1. 0. 0. 0. 0. ] [0. 0.02702703 0. 0. 0. 0. 0.97297297 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. 0.97222222 0.02777778 0. ] [0.03030303 0.06060606 0. 0.03030303 0.03030303 0.03030303 0. 0. 0.81818182 0. ] [0. 0. 0. 0. 0. 0.02702703 0. 0.05405405 0.02702703 0.89189189]] ---------------------------------------------------------------------- Neural network with activation function 'relu' Accuracy: 0.9465704531346988 [[33 0 0 0 1 0 1 0 0 0] [ 0 35 0 0 0 0 0 0 0 1] [ 0 0 34 1 0 0 0 0 0 0] [ 0 0 0 26 0 2 0 3 6 0] [ 0 0 0 0 34 0 0 0 1 2] [ 0 0 0 0 0 37 0 0 0 0] [ 0 1 0 0 0 0 36 0 0 0] [ 0 0 0 0 2 0 0 31 3 0] [ 0 5 0 0 0 0 0 0 28 0] [ 0 0 0 0 0 1 0 0 2 34]] [[0.94285714 0. 0. 0. 0.02857143 0. 0.02857143 0. 0. 0. ] [0. 0.97222222 0. 0. 0. 0. 0. 0. 0. 0.02777778] [0. 0. 0.97142857 0.02857143 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0.7027027 0. 0.05405405 0. 0.08108108 0.16216216 0. ] [0. 0. 0. 0. 0.91891892 0. 0. 0. 0.02702703 0.05405405] [0. 0. 0. 0. 0. 1. 0. 0. 0. 0. ] [0. 0.02702703 0. 0. 0. 0. 0.97297297 0. 0. 0. ] [0. 0. 0. 0. 0.05555556 0. 0. 0.86111111 0.08333333 0. ] [0. 0.15151515 0. 0. 0. 0. 0. 0. 0.84848485 0. ] [0. 0. 0. 0. 0. 0.02702703 0. 0. 0.05405405 0.91891892]] ----------------------------------------------------------------------
10. Jaké číslice nebyly rozpoznány jednotlivými neuronovými sítěmi?
I přesto, že matice záměn vypadaly pro neuronové sítě s různými aktivačními funkcemi podobně, můžeme nalézt rozdíly v tom, které číslice jednotlivé sítě nerozeznávají správně. Podívejme se tedy na příklady. Pro každý typ neuronové sítě (přesněji řečeno sítě používající odlišnou aktivační funkci) se pokusíme zobrazit 30 špatně rozpoznaných číslic. Je zde ovšem jedna výjimka – síť založená na logistické funkci (sigmoidu) je natolik kvalitní, že nerozeznala pouze 28 číslic z celkového počtu 360 neznámých obrázků, takže na grafu je zobrazeno jen oněch 28 špatně určených číslic:

Obrázek 18: Špatně rozeznané číslice pro neuronovou síť používající aktivační funkci „identity“.

Obrázek 19: Špatně rozeznané číslice pro neuronovou síť používající aktivační funkci „logistic“ (sigmoid).

Obrázek 20: Špatně rozeznané číslice pro neuronovou síť používající aktivační funkci „ReLU“.

Obrázek 21: Špatně rozeznané číslice pro neuronovou síť používající aktivační funkci „TanH“.
11. Porovnání přesností všech čtyř neuronových sítí
A nakonec si ukážeme graf s porovnáním celkové přesnosti všech čtyř neuronových sítí. Jedná se o prakticky shodné hodnoty, což ostatně bylo patrné i při prozkoumání a porovnání matic záměn:

Obrázek 22: Graf ukazující přesnosti všech čtyř neuronových sítí.
12. Specifikace algoritmu pro trénink neuronové sítě
V knihovně scikit-learn můžeme kromě volby aktivační funkce specifikovat i algoritmus použitý při tréninku. Ten mj. určuje způsob aplikace zpětné vazby na základě odpovědi trénované sítě a správné odpovědi. K dispozici máme tři algoritmy pojmenované „adam“, „lbfgs“ a „sgd“. Algoritmus „sgd“ je založen na metodě nazvané stochastic gradient descent a „adam“ je její optimalizovanou verzí. K popisu této metody se ještě vrátíme v souvislosti s knihovnou PyTorch. A „lbfgs“ je odvozen z názvu Limited-memory BFGS, kde BFGS značí Broyden–Fletcher–Goldfarb–Shanno algorithm. I k popisu této metody se ještě vrátíme, ovšem nyní je pouze nutné vědět, že si mezi třemi výše uvedenými algoritmy budeme moci vybrat a ovlivnit tak vlastně kvalitu výsledné neuronové sítě, tj. schopnosti její predikce.
13. Skript, který použije různé algoritmy pro trénink neuronové sítě
Výše uvedené trénovací algoritmy si pochopitelně opět můžeme zvolit, a to předáním pojmenovaného parametru solver do konstruktoru modelu, tedy konkrétně do konstruktorů MLPClassifier nebo MLPRegressor. Opět si tedy můžeme vyzkoušet jak (a zda vůbec) volba algoritmu ovlivní kvalitu natrénování a tím pádem i odhadu neuronové sítě:
solvers = ("lbfgs", "sgd", "adam") scores = [] for solver in solvers: score = train_and_test_model(solver) scores.append(score)
Celý skript, který toto srovnání provádí, vypadá následovně:
# Rozpoznání obrazu s využitím knihovny scikit-learn import matplotlib.pyplot as plt import numpy as np from sklearn.neural_network import MLPClassifier from sklearn.model_selection import train_test_split from sklearn.model_selection import cross_val_score from sklearn.metrics import ConfusionMatrixDisplay # Databáze ručně zapsaných číslic from sklearn.datasets import load_digits # načtení obrázků, s nimiž budeme dále pracovat digits = load_digits() # zjištění základních informací o obrázcích print("Description:", digits.DESCR) print("Data:", digits.data.shape) print("Obrázky:", digits.images.shape) # X je matice (feature matrix) X = digits.data # y je vektor (response vector) y = digits.target for_training = len(y) * 8 // 10 print("Vzorků pro trénink:", for_training) print("\n\n") # rozdělení dat trainX = X[:for_training] testX = X[for_training:] trainY = y[:for_training] testY = y[for_training:] def train_and_test_model(solver: str, show_results: bool = False): print(f"Neural network with solver '{solver}'") # provést klasifikaci # konstrukce klasifikatoru # (s hyperparametrem) classifier = MLPClassifier(max_iter=5000, solver=solver) # vypocet skore scores = cross_val_score(classifier, X, y, cv=10, scoring="accuracy") avg_score = scores.mean() # vypsani prumerneho skore print("Accuracy:", avg_score) print() # trening modelu classifier.fit(trainX, trainY) class_names = digits.target_names # absolutni hodnoty disp = ConfusionMatrixDisplay.from_estimator( classifier, testX, testY, display_labels=class_names, cmap=plt.cm.Blues, normalize=None, ) # zobrazeni matice print(disp.confusion_matrix) print() # ulozeni vysledku plt.savefig(f"{solver}_confusion_matrix_abs.png") # vizualizace matice if show_results: plt.show() # relativni hodnoty disp = ConfusionMatrixDisplay.from_estimator( classifier, testX, testY, display_labels=class_names, cmap=plt.cm.Blues, normalize="true", ) # zobrazeni matice print(disp.confusion_matrix) # ulozeni vysledku plt.savefig(f"{solver}_confusion_matrix_rel.png") # vizualizace matice if show_results: plt.show() predicted_labels = classifier.predict(testX) images = digits.images[for_training:] fig = plt.figure(figsize=(6.4, 10.0)) # zobrazit patnáct výsledků wrong = 0 i = 0 while wrong < 30: predicted_digit = classifier.predict([testX[i]])[0] correct_digit = testY[i] if predicted_digit != correct_digit: image = images[i] wrong += 1 plt.subplot(6, 5, wrong) plt.axis("off") # zobrazení obrázku plt.imshow(image, cmap=plt.cm.gray_r, interpolation="nearest") # a přidání predikce - o jakou číslici se jedná plt.title(f"{predicted_digit} <> {correct_digit}") i += 1 # nenasli jsme vice cislic if i >= len(testX): break # nakonec vše uložíme a zobrazíme plt.savefig(f"{solver}_wrong_digits.png") if show_results: plt.show() print() print("-" * 70) return avg_score solvers = ("lbfgs", "sgd", "adam") scores = [] for solver in solvers: score = train_and_test_model(solver) scores.append(score) fig, ax = plt.subplots() ax.bar(solvers, scores) ax.set_ylabel("Model accuracy") ax.set_title("Solver") plt.savefig("accuracy.png") plt.show()
14. Matice záměn a přesnosti modelů pro různé trénovací algoritmy
Výše uvedený skript zobrazí mj. i matice záměn pro jednotlivé algoritmy. Nejprve si uvedeme matice záměn s absolutními hodnotami:

Obrázek 23: Matice záměn s absolutními hodnotami pro neuronovou síť natrénovanou algoritmem „adam“.

Obrázek 24: Matice záměn s absolutními hodnotami pro neuronovou síť natrénovanou algoritmem „lbfgs“.

Obrázek 25: Matice záměn s absolutními hodnotami pro neuronovou síť natrénovanou algoritmem „sgd“.
Matice záměn s hodnotami relativními:

Obrázek 26: Matice záměn s absolutními hodnotami pro neuronovou síť natrénovanou algoritmem „adam“.

Obrázek 27: Matice záměn s absolutními hodnotami pro neuronovou síť natrénovanou algoritmem „lbfgs“.

Obrázek 28: Matice záměn s absolutními hodnotami pro neuronovou síť natrénovanou algoritmem „sgd“.
Textová podoba výsledků:
Data: (1797, 64) Obrázky: (1797, 8, 8) Vzorků pro trénink: 1437 Neural network with solver 'lbfgs' Accuracy: 0.948786468032278 [[33 0 0 0 1 0 1 0 0 0] [ 0 32 0 1 0 0 0 0 0 3] [ 0 0 35 0 0 0 0 0 0 0] [ 0 0 0 31 0 2 0 1 3 0] [ 0 1 0 0 34 0 0 0 0 2] [ 0 0 0 0 0 37 0 0 0 0] [ 0 1 0 0 0 0 36 0 0 0] [ 0 1 0 0 1 0 0 33 1 0] [ 0 2 0 1 1 2 0 0 27 0] [ 0 1 0 1 0 1 0 2 0 32]] [[0.94285714 0. 0. 0. 0.02857143 0. 0.02857143 0. 0. 0. ] [0. 0.88888889 0. 0.02777778 0. 0. 0. 0. 0. 0.08333333] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0.83783784 0. 0.05405405 0. 0.02702703 0.08108108 0. ] [0. 0.02702703 0. 0. 0.91891892 0. 0. 0. 0. 0.05405405] [0. 0. 0. 0. 0. 1. 0. 0. 0. 0. ] [0. 0.02702703 0. 0. 0. 0. 0.97297297 0. 0. 0. ] [0. 0.02777778 0. 0. 0.02777778 0. 0. 0.91666667 0.02777778 0. ] [0. 0.06060606 0. 0.03030303 0.03030303 0.06060606 0. 0. 0.81818182 0. ] [0. 0.02702703 0. 0.02702703 0. 0.02702703 0. 0.05405405 0. 0.86486486]] ---------------------------------------------------------------------- Neural network with solver 'sgd' Accuracy: 0.9465611421477342 [[33 0 0 0 1 0 1 0 0 0] [ 0 31 0 0 0 0 0 0 0 5] [ 0 0 35 0 0 0 0 0 0 0] [ 0 0 2 27 0 3 0 1 4 0] [ 0 1 0 0 34 0 0 0 0 2] [ 0 0 0 0 0 37 0 0 0 0] [ 0 1 0 0 0 0 36 0 0 0] [ 0 0 0 0 1 0 0 34 1 0] [ 0 3 0 1 0 1 0 1 27 0] [ 1 0 0 0 0 1 0 0 1 34]] [[0.94285714 0. 0. 0. 0.02857143 0. 0.02857143 0. 0. 0. ] [0. 0.86111111 0. 0. 0. 0. 0. 0. 0. 0.13888889] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0.05405405 0.72972973 0. 0.08108108 0. 0.02702703 0.10810811 0. ] [0. 0.02702703 0. 0. 0.91891892 0. 0. 0. 0. 0.05405405] [0. 0. 0. 0. 0. 1. 0. 0. 0. 0. ] [0. 0.02702703 0. 0. 0. 0. 0.97297297 0. 0. 0. ] [0. 0. 0. 0. 0.02777778 0. 0. 0.94444444 0.02777778 0. ] [0. 0.09090909 0. 0.03030303 0. 0.03030303 0. 0.03030303 0.81818182 0. ] [0.02702703 0. 0. 0. 0. 0.02702703 0. 0. 0.02702703 0.91891892]] ---------------------------------------------------------------------- Neural network with solver 'adam' Accuracy: 0.9549130974549968 [[33 0 0 0 1 0 1 0 0 0] [ 0 35 0 0 0 0 0 0 0 1] [ 0 0 34 1 0 0 0 0 0 0] [ 0 0 0 30 0 3 0 1 3 0] [ 0 0 0 0 34 0 0 0 0 3] [ 0 1 0 0 0 36 0 0 0 0] [ 0 1 0 0 0 0 36 0 0 0] [ 0 0 0 0 1 0 0 35 0 0] [ 0 2 0 0 1 0 0 0 29 1] [ 0 1 0 1 0 0 0 3 1 31]] [[0.94285714 0. 0. 0. 0.02857143 0. 0.02857143 0. 0. 0. ] [0. 0.97222222 0. 0. 0. 0. 0. 0. 0. 0.02777778] [0. 0. 0.97142857 0.02857143 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0.81081081 0. 0.08108108 0. 0.02702703 0.08108108 0. ] [0. 0. 0. 0. 0.91891892 0. 0. 0. 0. 0.08108108] [0. 0.02702703 0. 0. 0. 0.97297297 0. 0. 0. 0. ] [0. 0.02702703 0. 0. 0. 0. 0.97297297 0. 0. 0. ] [0. 0. 0. 0. 0.02777778 0. 0. 0.97222222 0. 0. ] [0. 0.06060606 0. 0. 0.03030303 0. 0. 0. 0.87878788 0.03030303] [0. 0.02702703 0. 0.02702703 0. 0. 0. 0.08108108 0.02702703 0.83783784]] ----------------------------------------------------------------------
15. Jaké číslice nebyly rozpoznány jednotlivými neuronovými sítěmi?
Samozřejmě si taktéž ukážeme, jaký vliv měla volba trénovacích algoritmů na to, které číslice jsou rozeznány či naopak nerozeznány jednotlivými natrénovanými sítěmi. Opět se pokusíme zobrazit 30 špatných výsledků z celkem 360 pokusů o rozeznání, které každá síť provedla. Pokud je některá ze sítí tak dobře natrénovaná, že neměla víc než 30 chybných odhadů, bude ve výsledku zobrazeno menší množství číslic:

Obrázek 29: Číslice, které nebyly rozeznány sítí natrénovanou algoritmem „adam“.

Obrázek 30: Číslice, které nebyly rozeznány sítí natrénovanou algoritmem „lbfgs“.

Obrázek 31: Číslice, které nebyly rozeznány sítí natrénovanou algoritmem „sgd“.
16. Kombinace nejlepší aktivační funkce a nejlepšího algoritmu = nejlepší výsledky?
Z předchozích výsledků vyplývá, že použitím aktivační funkce jsme dostali (beze změny trénovacího algoritmu) ty nejlepší výsledky. A naopak, pokud pouze měníme trénovací algoritmy, dosáhneme nejlepších výsledků při výběru algoritmu „adam“:

Obrázek 32: Přesnosti odpovědí neuronových sítí natrénovaných různými algoritmy. Nejlépe dopadlo použití algoritmu „adam“.
Mohlo by se tedy zdát, že pokud zkombinujeme tu nejlepší aktivační funkci s nejlepším trénovacím algoritmem, dostaneme vždy ty nejlepší výsledky – ideálně natrénovanou neuronovou síť. V praxi to tak ovšem není, a to z mnoha důvodů. Jedním z nich je fakt, že se při tréninku používají náhodné hodnoty a ani samotná kombinace dvou „nejlepších“ parametrů obecně nedává nejlepší výsledek. Jedinou spolehlivou metodou je vyzkoušet všechno možnosti a navíc použít i křížovou validaci – což je ovšem v případě neuronových sítí časově velmi složité.
Ostatně si vyzkoušejme kombinaci „nejlepších“ algoritmů v praxi:
# Rozpoznání obrazu s využitím knihovny scikit-learn import matplotlib.pyplot as plt import numpy as np from sklearn.neural_network import MLPClassifier from sklearn.model_selection import train_test_split from sklearn.model_selection import cross_val_score from sklearn.metrics import ConfusionMatrixDisplay # Databáze ručně zapsaných číslic from sklearn.datasets import load_digits ACTIVATION_FUNCTION="logistic" SOLVER="adam" # načtení obrázků, s nimiž budeme dále pracovat digits = load_digits() # zjištění základních informací o obrázcích print("Description:", digits.DESCR) print("Data:", digits.data.shape) print("Obrázky:", digits.images.shape) # X je matice (feature matrix) X = digits.data # y je vektor (response vector) y = digits.target for_training = len(y) * 8 // 10 print("Vzorků pro trénink:", for_training) print("\n\n") # rozdělení dat trainX = X[:for_training] testX = X[for_training:] trainY = y[:for_training] testY = y[for_training:] def train_and_test_model(show_results: bool = False): # provést klasifikaci # konstrukce klasifikatoru # (s hyperparametrem) classifier = MLPClassifier(max_iter=5000, activation=ACTIVATION_FUNCTION, solver=SOLVER) # vypocet skore scores = cross_val_score(classifier, X, y, cv=10, scoring="accuracy") avg_score = scores.mean() # vypsani prumerneho skore print("Accuracy:", avg_score) print() # trening modelu classifier.fit(trainX, trainY) class_names = digits.target_names # absolutni hodnoty disp = ConfusionMatrixDisplay.from_estimator( classifier, testX, testY, display_labels=class_names, cmap=plt.cm.Blues, normalize=None, ) # zobrazeni matice print(disp.confusion_matrix) print() # ulozeni vysledku plt.savefig("confusion_matrix_abs.png") # vizualizace matice if show_results: plt.show() # relativni hodnoty disp = ConfusionMatrixDisplay.from_estimator( classifier, testX, testY, display_labels=class_names, cmap=plt.cm.Blues, normalize="true", ) # zobrazeni matice print(disp.confusion_matrix) # ulozeni vysledku plt.savefig("confusion_matrix_rel.png") # vizualizace matice if show_results: plt.show() predicted_labels = classifier.predict(testX) images = digits.images[for_training:] fig = plt.figure(figsize=(6.4, 10.0)) # zobrazit patnáct výsledků wrong = 0 i = 0 while wrong < 30: predicted_digit = classifier.predict([testX[i]])[0] correct_digit = testY[i] if predicted_digit != correct_digit: image = images[i] wrong += 1 plt.subplot(6, 5, wrong) plt.axis("off") # zobrazení obrázku plt.imshow(image, cmap=plt.cm.gray_r, interpolation="nearest") # a přidání predikce - o jakou číslici se jedná plt.title(f"{predicted_digit} <> {correct_digit}") i += 1 # nenasli jsme vice cislic if i >= len(testX): break # nakonec vše uložíme a zobrazíme plt.savefig("wrong_digits.png") if show_results: plt.show() print() print("-" * 70) return avg_score train_and_test_model()
17. Dosažené výsledky
Výsledky získané spuštěním předchozího skriptu mohou být následující (ovšem bez křížové validace nebude skóre vždy stejné):

Obrázek 33: Matice záměn s absolutními hodnotami.

Obrázek 34: Matice záměn s relativními hodnotami.

Obrázek 35: Špatně rozpoznané číslice z 360 vzorků (více jich není).
18. Obsah navazujícího článku
V dnešním článku jsme dokončili popis většiny užitečných vlastností knihovny scikit-learn. Příště se ještě na chvíli zastavíme u sledování jednotlivých fází učení neuronových sítí. Ovšem knihovna scikit-learn má i některá omezení, která se týkají právě problematiky neuronových sítí. Z tohoto důvodu se v navazujících článcích seznámíme s knihovnou, která je přímo určena pro trénink a aplikaci neuronových sítí. Tato knihovna se jmenuje PyTorch. Původně tato knihovna částečně vycházela z knihovny Torch, s níž jsme se již na stránkách Roota setkali v seriálu Torch: framework pro strojové učení. Nicméně později PyTorch dospěl do zcela samostatného projektu, který je navíc v praxi poměrně intenzivně používán, takže je dobré znát koncepty, na kterých je postaven.

Obrázek 36: Logo projektu PyTorch.
19. Repositář s demonstračními příklady
Všechny demonstrační příklady využívající knihovnu Scikit-learn lze nalézt v repositáři https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady i na (Jupyter) diáře s postupem výpočtů a analýz:
V repositáři nalezneme taktéž projektový soubor a Jupyter Notebook s vysvětlením, jak lze modely využít pro rozpoznávání obsahu rastrových obrázků:
# | Příklad | Stručný popis | Adresa příkladu |
---|---|---|---|
1 | pyproject.toml | projektový soubor (pro PDM) se všemi závislostmi | https://github.com/tisnik/most-popular-python-libs/blob/master/sklearn/pyproject.toml |
2 | pdm.lock | lock soubor s konkrétními verzemi všech přímých i tranzitivních závislostí | https://github.com/tisnik/most-popular-python-libs/blob/master/sklearn/pdm.lock |
3 | Rozpoznání_obrazu_scikit-learn.ipynb | Jupyter notebook s celým postupem | https://github.com/tisnik/most-popular-python-libs/blob/master/sklearn/Rozpoznání_obrazu_scikit-learn.ipynb |
4 | particle_life.py | emergence: příklad vzniku struktury | https://github.com/tisnik/most-popular-python-libs/blob/master/particles/particle_life.py |
20. Odkazy na Internetu
- Shluková analýza (clustering) a knihovna Scikit-learn
https://www.root.cz/clanky/shlukova-analyza-clustering-a-knihovna-scikit-learn/ - Shluková analýza (clustering) a knihovna Scikit-learn (2)
https://www.root.cz/clanky/shlukova-analyza-clustering-a-knihovna-scikit-learn-2/ - Shluková analýza (clustering) a knihovna Scikit-learn (z plochy do 3D prostoru)
https://www.root.cz/clanky/shlukova-analyza-clustering-a-knihovna-scikit-learn-z-plochy-do-3d-prostoru/ - Rozpoznávání obrázků knihovnou Scikit-learn: první kroky
https://www.root.cz/clanky/rozpoznavani-obrazku-knihovnou-scikit-learn-prvni-kroky/ - scikit-learn: Machine Learning in Python
https://scikit-learn.org/stable/index.html - Sklearn-pandas
https://github.com/scikit-learn-contrib/sklearn-pandas - sklearn-xarray
https://github.com/phausamann/sklearn-xarray/ - Clustering
https://scikit-learn.org/stable/modules/clustering.html - Cluster analysis (Wikipedia)
https://en.wikipedia.org/wiki/Cluster_analysis - Shluková analýza (Wikipedia)
https://cs.wikipedia.org/wiki/Shlukov%C3%A1_anal%C3%BDza - K-means
https://cs.wikipedia.org/wiki/K-means - k-means clustering
https://en.wikipedia.org/wiki/K-means_clustering - Spectral clustering
https://en.wikipedia.org/wiki/Spectral_clustering - Emergence
https://cs.wikipedia.org/wiki/Emergence - Particle Life: Vivid structures from rudimentary rules
https://particle-life.com/ - Hertzsprungův–Russellův diagram
https://cs.wikipedia.org/wiki/Hertzsprung%C5%AFv%E2%80%93Russell%C5%AFv_diagram - Using Machine Learning in an HR Diagram
https://cocalc.com/share/public_paths/08b6e03583cbdef3cdb9813a54ec68ff773c747f - Gaia H-R diagrams: Querying Gaia data for one million nearby stars
https://vlas.dev/post/gaia-dr2-hrd/ - The Hertzsprung–Russell diagram
https://scipython.com/book2/chapter-9-data-analysis-with-pandas/problems/p92/the-hertzsprung-russell-diagram/ - Animated Hertzsprung-Russell Diagram with 119,614 datapoints
https://github.com/zonination/h-r-diagram - Neuraxle Pipelines
https://github.com/Neuraxio/Neuraxle - scikit-learn: Getting Started
https://scikit-learn.org/stable/getting_started.html - Support Vector Machines
https://scikit-learn.org/stable/modules/svm.html - Use Deep Learning to Detect Programming Languages
http://searene.me/2017/11/26/use-neural-networks-to-detect-programming-languages/ - Natural-language processing
https://en.wikipedia.org/wiki/Natural-language_processing - THE MNIST DATABASE of handwritten digits
http://yann.lecun.com/exdb/mnist/ - MNIST database (Wikipedia)
https://en.wikipedia.org/wiki/MNIST_database - MNIST For ML Beginners
https://www.tensorflow.org/get_started/mnist/beginners - Stránka projektu Torch
http://torch.ch/ - Torch: Serialization
https://github.com/torch/torch7/blob/master/doc/serialization.md - Torch: modul image
https://github.com/torch/image/blob/master/README.md - Data pro neuronové sítě
http://archive.ics.uci.edu/ml/index.php - Torch na GitHubu (několik repositářů)
https://github.com/torch - Torch (machine learning), Wikipedia
https://en.wikipedia.org/wiki/Torch_%28machine_learning%29 - Torch Package Reference Manual
https://github.com/torch/torch7/blob/master/README.md - Torch Cheatsheet
https://github.com/torch/torch7/wiki/Cheatsheet - Neural network containres (Torch)
https://github.com/torch/nn/blob/master/doc/containers.md - Simple layers
https://github.com/torch/nn/blob/master/doc/simple.md#nn.Linear - Transfer Function Layers
https://github.com/torch/nn/blob/master/doc/transfer.md#nn.transfer.dok - Feedforward neural network
https://en.wikipedia.org/wiki/Feedforward_neural_network - Biologické algoritmy (4) – Neuronové sítě
https://www.root.cz/clanky/biologicke-algoritmy-4-neuronove-site/ - Biologické algoritmy (5) – Neuronové sítě
https://www.root.cz/clanky/biologicke-algoritmy-5-neuronove-site/ - Umělá neuronová síť (Wikipedia)
https://cs.wikipedia.org/wiki/Um%C4%9Bl%C3%A1_neuronov%C3%A1_s%C3%AD%C5%A5 - PyTorch
http://pytorch.org/ - JupyterLite na PyPi
https://pypi.org/project/jupyterlite/ - JupyterLite na GitHubu
https://github.com/jupyterlite/jupyterlite - Dokumentace k projektu JupyterLite
https://github.com/jupyterlite/jupyterlite - Matplotlib Home Page
http://matplotlib.org/ - Matplotlib (Wikipedia)
https://en.wikipedia.org/wiki/Matplotlib - Popis barvových map modulu matplotlib.cm
https://gist.github.com/endolith/2719900#id7 - Ukázky (palety) barvových map modulu matplotlib.cm
http://matplotlib.org/examples/color/colormaps_reference.html - Galerie grafů vytvořených v Matplotlibu
https://matplotlib.org/3.2.1/gallery/ - 3D rendering
https://en.wikipedia.org/wiki/3D_rendering - 3D computer graphics
https://en.wikipedia.org/wiki/3D_computer_graphics - Primary 3D view planes
https://matplotlib.org/stable/gallery/mplot3d/view_planes_3d.html - Getting started in scikit-learn with the famous iris dataset
https://www.youtube.com/watch?v=hd1W4CyPX58 - Training a machine learning model with scikit-learn
https://www.youtube.com/watch?v=RlQuVL6-qe8 - Iris (plant)
https://en.wikipedia.org/wiki/Iris_(plant) - Kosatec
https://cs.wikipedia.org/wiki/Kosatec - Iris setosa
https://en.wikipedia.org/wiki/Iris_setosa - Iris versicolor
https://en.wikipedia.org/wiki/Iris_versicolor - Iris virginica
https://en.wikipedia.org/wiki/Iris_virginica - Druh
https://cs.wikipedia.org/wiki/Druh - Iris subg. Limniris
https://en.wikipedia.org/wiki/Iris_subg._Limniris - Iris Dataset Classification with Python: A Tutorial
https://www.pycodemates.com/2022/05/iris-dataset-classification-with-python.html - Iris flower data set
https://en.wikipedia.org/wiki/Iris_flower_data_set - List of datasets for machine-learning research
https://en.wikipedia.org/wiki/List_of_datasets_for_machine-learning_research - Analýza hlavních komponent
https://cs.wikipedia.org/wiki/Anal%C3%BDza_hlavn%C3%ADch_komponent - Principal component analysis
https://en.wikipedia.org/wiki/Principal_component_analysis - Scikit-learn Crash Course – Machine Learning Library for Python
https://www.youtube.com/watch?v=0B5eIE_1vpU - calm-notebooks
https://github.com/koaning/calm-notebooks - Should you teach Python or R for data science?
https://www.dataschool.io/python-or-r-for-data-science/ - nbviewer: A simple way to share Jupyter Notebooks
https://nbviewer.org/ - AI vs Machine Learning (Youtube)
https://www.youtube.com/watch?v=4RixMPF4×is - Machine Learning | What Is Machine Learning? | Introduction To Machine Learning | 2024 | Simplilearn (Youtube)
https://www.youtube.com/watch?v=ukzFI9rgwfU - A Gentle Introduction to Machine Learning (Youtube)
https://www.youtube.com/watch?v=Gv9_4yMHFhI - Machine Learning vs Deep Learning
https://www.youtube.com/watch?v=q6kJ71tEYqM - Umělá inteligence (slajdy)
https://slideplayer.cz/slide/12119218/ - Úvod do umělé inteligence
https://slideplayer.cz/slide/2505525/ - Umělá inteligence I / Artificial Intelligence I
https://ktiml.mff.cuni.cz/~bartak/ui/ - Matplotlib vs. seaborn vs. Plotly vs. MATLAB vs. ggplot2 vs. pandas
https://ritza.co/articles/matplotlib-vs-seaborn-vs-plotly-vs-MATLAB-vs-ggplot2-vs-pandas/ - Matplotlib, Seaborn or Plotnine?
https://www.reddit.com/r/datascience/comments/jvrqxt/matplotlib_seaborn_or_plotnine/ - @Rabeez: Rabeez/plotting_comparison.ipynb
https://gist.github.com/Rabeez/ffc0b59d4a41e20fa8d944c44a96adbc - Matplotlib, Seaborn, Plotly and Plotnine Comparison
https://python.plainenglish.io/matplotlib-seaborn-plotly-and-plotnine-comparison-baf2db5a9c40 - Data Visualization 101: How to Choose a Python Plotting Library
https://towardsdatascience.com/data-visualization-101-how-to-choose-a-python-plotting-library-853460a08a8a - Data science in Python: pandas, seaborn, scikit-learn
https://www.youtube.com/watch?v=3ZWuPVWq7p4 - 7.2. Real world datasets
https://scikit-learn.org/stable/datasets/real_world.html#california-housing-dataset - 7.2.7. California Housing dataset
https://scikit-learn.org/stable/datasets/real_world.html#california-housing-dataset - Comprehensive Guide to Classification Models in Scikit-Learn
https://www.geeksforgeeks.org/comprehensive-guide-to-classification-models-in-scikit-learn/ - Tidy Data Visualization: ggplot2 vs seaborn
https://blog.tidy-intelligence.com/posts/ggplot2-vs-seaborn/ - seaborn: statistical data visualization
https://seaborn.pydata.org/ - Linear regression (Wikipedia)
https://en.wikipedia.org/wiki/Linear_regression - Lineární regrese (Wikipedia)
https://cs.wikipedia.org/wiki/Line%C3%A1rn%C3%AD_regrese - Iris Flower Classification with MLP Classifier
https://www.metriccoders.com/post/iris-flower-classification-with-mlp-classifier