Obsah
1. Nejjednodušší prakticky použitelná neuronová síť: výběr jednoho vstupu ze dvou dostupných
2. Výsledky získané otestování jednoduché neuronové sítě
3. Odstranění náhody z procesu tréninku a testování neuronové sítě
4. Skript pro trénink a otestování neuronové sítě se stabilními výsledky
5. Stabilní výsledky získané předchozím skriptem
6. Vylepšení tréninku neuronové sítě zvýšením počtu trénovacích vzorků
7. Skript, který postupně zvětšuje počet vzorků použitých pro trénink neuronové sítě
8. Výsledky běhu předchozího skriptu
9. Grafické znázornění závislosti MSE, vah neuronů a biasu na počtu vzorků
10. Výsledky získané po běhu skriptu
11. Zrychlení tréninku neuronové sítě snížením počtu iterací
12. Výsledky získané po běhu skriptu: snížení počtu iterací při tréninku neuronové sítě
13. Vyšší míra změny vah na vstupu neuronů při tréninku
14. Výsledky získané po běhu skriptu: vyšší míra změna vah neuronů
15. Riziko příliš vysoké hodnoty learning_rate_init
16. Výsledky získané po běhu skriptu: vysoká míra změny vah neuronů
17. Opačný extrém – příliš malá hodnota learning_rate_init
18. Výsledek běhu dnešního posledního demonstračního příkladu
19. Repositář s demonstračními příklady
1. Nejjednodušší prakticky použitelná neuronová síť: výběr jednoho vstupu ze dvou dostupných
Pro pochopení toho, jaký vliv mají hyperparametry modelu na výslednou neuronovou síť si vytvoříme tu nejjednodušší ještě prakticky použitelnou síť, která bude mít dva vstupy a jediný výstup. Bude se jednat o regresní síť, která bude natrénována tak, aby z obou vstupů vybrala vždy hodnotu z jednoho předem určeného vstupu (určení, o který vstup se jedná, se provádí tréninkem). Například síť natrénujeme takovým způsobem, aby vždy vybrala hodnotu druhého vstupu a tu poslala na výstup (jedná se o „analogovou“ hodnotu, ne o logické hradlo, resp. demultiplexor). A navíc síť zjednodušíme do nejmenší možné velikosti, protože bude mít pouze dva neurony ve vstupní vrstvě a jediný neuron ve vrstvě výstupní. Skryté vrstvy nebudou existovat. To tedy znamená, že namísto relativně složité sítě typu:

Obrázek 1: Neuronová síť s více skrytými vrstvami.
Budeme mít síť s celkem pouze třemi neurony:

Obrázek 2: Neuronová síť bez skrytých vrstev; vstupní vrstva má dva neurony, výstupní vrstva neuron jediný.
Skript, který si připraví data pro trénink a testování (začneme na 10 záznamech), zkonstruuje síť a následně ověří její (ne)funkčnost, může vypadat následovně. Naprostou většinu konceptů použitých v tomto skriptu již známe:
import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 10 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku # priprava dat pro trenink i otestovani neuronove site for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=()) # trénink modelu nn.fit(X_train, y_train) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce print("Mean squared error: %.2f" % mean_squared_error(y_test, y_pred)) # 1 = nejlepší predikce modelu print("Coefficient of determination: %.2f" % r2_score(y_test, y_pred)) # zobrazit parametry neuronove site print(f"Features: {nn.n_features_in_}") print(f"Layers: {nn.n_layers_}") print(f"Outputs: {nn.n_outputs_}") print("Weights:") # vahy neuronu for layer, weights in enumerate(nn.coefs_): print("\t", layer, weights.shape) print(weights) print() # posuny (dalsi vstup do neuronu) print("Biases:") for layer, biases in enumerate(nn.intercepts_): print("\t", layer, biases.shape) print(biases) print() # test neuronove site na (potencialne) nezname vstupy inputs = [] for i in range(0, MAX_N): for j in range(0, MAX_N): inputs.append([i, j]) predicted = nn.predict(inputs) print() # odhady neuronove site po zaokrouhleni all = 0 wrong = 0 # projit vsemi odhady a najit spatne vystupy site for i, p in zip(inputs, predicted): # spatny odhad? if i[1] != round(p): print(f"{i[0]:2}, {i[1]:2} = {round(p):2}") wrong += 1 all += 1 # vysledna statistika print(f"{wrong}/{all}")
2. Výsledky získané otestování jednoduché neuronové sítě
Užitečné bude zjistit, jak se bude výše nakonfigurovaná neuronová síť chovat. Ovšem vzhledem k tomu, že se v průběhu tréninku používají náhodná čísla, nebudou výsledky vždy totožné. Ovšem poměrně často je síť natrénována tak vhodným způsobem, že má prakticky stoprocentní odpovědi:
Mean squared error: 0.10 Coefficient of determination: 0.00
Interní struktura takové sítě vypadá následovně:
Features: 2 Layers: 2 Outputs: 1 Weights: 0 (2, 1) [[-0.00311307] [ 0.96168339]] Biases: 0 (1,) [-0.08298607]
Povšimněte si toho, že váhy na vstupu neuronu ve výstupní vrstvě jsou poměrně blízko hodnotám 0,0 a 1,0, což odpovídá požadované funkci sítě. A bias (tedy váha pro posuny hodnot na vstupu tohoto neuronu) je taky prakticky nulový. Neuron tedy skutečně vybere druhou vstupní hodnotu, kterou předá do aktivační funkce. Ta je pro kladné hodnoty funkcí lineární, takže ji můžeme ignorovat. Ze vztahu:
y = f(w0 + w1x1 + w2x2 + … + wnxn)
Tedy získáme tento výpočet, který neuron provádí:
y = w0 + w1x1 + w2x2
A po dosazení ideálních hodnot:
y = 0×1 + 1×2 = x2
Ideálně natrénované neuronové síti odpovídá tento výsledek:
rounded: 0/100
Ovšem v některých případech dopadne trénink odlišně, a to opět kvůli (pseudo)náhodným hodnotám, které do celého procesu vstupují. Povšimněte si odlišných vah a o snahu sítě vše „vyvážit“ vyšším biasem:
Mean squared error: 0.49 Coefficient of determination: 0.92 Features: 2 Layers: 2 Outputs: 1 Weights: 0 (2, 1) [[0.04786446] [0.95183809]] Biases: 0 (1,) [0.47868983] rounded: 1, 0 = 1 2, 0 = 1 2, 1 = 2 3, 0 = 1 3, 1 = 2 3, 2 = 3 4, 0 = 1 4, 1 = 2 4, 2 = 3 4, 3 = 4 5, 0 = 1 5, 1 = 2 5, 2 = 3 5, 3 = 4 5, 4 = 5 6, 0 = 1 6, 1 = 2 6, 2 = 3 6, 3 = 4 6, 4 = 5 6, 5 = 6 7, 0 = 1 7, 1 = 2 7, 2 = 3 7, 3 = 4 7, 4 = 5 7, 5 = 6 7, 6 = 7 8, 0 = 1 8, 1 = 2 8, 2 = 3 8, 3 = 4 8, 4 = 5 8, 5 = 6 8, 6 = 7 8, 7 = 8 9, 0 = 1 9, 1 = 2 9, 2 = 3 9, 3 = 4 9, 4 = 5 9, 5 = 6 9, 6 = 7 9, 7 = 8 9, 8 = 9 45/100
3. Odstranění náhody z procesu tréninku a testování neuronové sítě
Abychom se vyhnuli tomu, že po každém spuštění procesu tréninku a testování získáme poněkud odlišné hodnoty, pokusíme se odstranit všechny náhody (náhodná čísla), která jsou používána. Nejprve nastavíme konstantní „semínko“ (seed) použité pro inicializaci generátoru pseudonáhodných čísel. Tím zajistíme, že stejné pořadí volání funkce random.randint() bude vracet stejné pořadí výsledků:
# zadne skutecne nahodne hodnoty random.seed(19) # priprava dat pro trenink i otestovani neuronove site for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1]
Náhodu odstraníme i z procesu rozdělení datové sady na trénovací a validační data:
# rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
A konečně předáme „náhodný stav“, který ovšem evidentně náhodný není, i jako hyperparametr modelu:
# konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000)
4. Skript pro trénink a otestování neuronové sítě se stabilními výsledky
Po úpravě zdrojového kódu tak, aby se v něm nevyskytovaly žádné náhodné hodnoty, dojdeme k následujícímu skriptu, jenž by měl při každém spuštění vždy odpovědět stejně:
import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 20 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku # zadne skutecne nahodne hodnoty random.seed(19) # priprava dat pro trenink i otestovani neuronove site for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000) # trénink modelu nn.fit(X_train, y_train) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce print("Mean squared error: %.2f" % mean_squared_error(y_test, y_pred)) # 1 = nejlepší predikce modelu print("Coefficient of determination: %.2f" % r2_score(y_test, y_pred)) # zobrazit parametry neuronove site print(f"Features: {nn.n_features_in_}") print(f"Layers: {nn.n_layers_}") print(f"Outputs: {nn.n_outputs_}") print("Weights:") # vahy neuronu for layer, weights in enumerate(nn.coefs_): print("\t", layer, weights.shape) print(weights) print() # posuny (dalsi vstup do neuronu) print("Biases:") for layer, biases in enumerate(nn.intercepts_): print("\t", layer, biases.shape) print(biases) print() # test neuronove site na (potencialne) nezname vstupy inputs = [] for i in range(0, MAX_N): for j in range(0, MAX_N): inputs.append([i, j]) predicted = nn.predict(inputs) print() # odhady neuronove site po zaokrouhleni all = 0 wrong = 0 for i, p in zip(inputs, predicted): # spatny odhad? if i[1] != round(p): print(f"{i[0]:2}, {i[1]:2} = {round(p):2}") wrong += 1 all += 1 # vysledna statistika print(f"{wrong}/{all}")
5. Stabilní výsledky získané předchozím skriptem
Výsledky, které získáme po každém spuštění skriptu popsaného v předchozí kapitole, vypadají na mém počítači následovně (teoreticky se totiž mohou výsledky na jiném počítači odlišovat, pokud je použitý jiný algoritmus generování náhodných čísel):
Mean squared error: 0.08 Coefficient of determination: 1.00 Features: 2 Layers: 2 Outputs: 1 Weights: 0 (2, 1) [[0.01515987] [0.96449027]] Biases: 0 (1,) [0.08740665]
Povšimněte si, že síť nebyla natrénována zcela ideálně, protože váha u druhého vstupu neuronu by mohla být blíže jedničce a naopak bias by mohl být blíže k nule. Ne zcela ideálnímu natrénovaní odpovídá i několik chybných odhadů nalezených při testování, ovšem není jich příliš mnoho – tři procenta:
0, 17 = 16 0, 18 = 17 0, 19 = 18 1, 17 = 16 1, 18 = 17 1, 19 = 18 2, 18 = 17 2, 19 = 18 3, 18 = 17 3, 19 = 18 4, 19 = 18 5, 19 = 18 12/400
6. Vylepšení tréninku neuronové sítě zvýšením počtu trénovacích vzorků
Jak můžeme vylepšit chování neuronové sítě s pouhými dvěma vrstvami (vstupní a výstupní) a třemi neurony? Z teoretického pohledu nemá smysl zvyšovat počet vrstev ani neuronů, protože i jediný neuron dokáže jeden ze vstupů vynásobit váhou 0 a druhý vstup vynásobit jedničkou – což je přesně to, co od této sítě očekáváme. Ovlivnit však můžeme natrénování sítě, tj. dosažení toho, aby váhové faktory byly skutečně nastaveny na [0.0, 1.0] a bias na 0.0. První způsob je ten nejznámější – jednoduše zvýšíme počet vzorků použitých při tréninku neuronové sítě. Jaký vliv počet vzorků pro trénink má, si lze relativně snadno ověřit (ovšem opět se vyhneme použití náhodných čísel).
7. Skript, který postupně zvětšuje počet vzorků použitých pro trénink neuronové sítě
Podívejme se nyní na to, jak snadno bylo možné upravit skript ze čtvrté kapitoly takovým způsobem, že se postupně zvětšuje počet vzorků určených pro trénink (vzorky pro ověření sítě se nemění). Jednoduše jsme do funkce train_and_testnn předáme celočíselnou hodnotu, kterou použijeme pro „vyseknutí“ trénovacích a validačních dat z připravené sady čtyřiceti vzorků. Využijeme k tomu operaci řezu (slice):
import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 40 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku # zadne skutecne nahodne hodnoty random.seed(19) # priprava dat pro trenink i otestovani neuronove site for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) def train_and_test_nn(size: int): X_train_ = X_train[:size] y_train_ = y_train[:size] # konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000) # trénink modelu nn.fit(X_train_, y_train_) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce # 1 = nejlepší predikce modelu print("%2d" % size, "%.2f" % mean_squared_error(y_test, y_pred), "%.2f" % r2_score(y_test, y_pred)) # postupne zvetsovani datove sady for i in range(1, MAX_N+1): train_and_test_nn(i)
8. Výsledky běhu předchozího skriptu
V případě, že skript popsaný v předchozí kapitole spustíme, poměrně snadno zjistíme, že už pro relativně malý počet trénovacích vzorků se neuronová síť (tedy přesněji řečeno váhy na vstupech neuronů) natrénuje takovým způsobem, že se zmenší MSE, tedy odchylka odpovědí sítě od očekávané odpovědi (připomeňme si, že pro regresní síť se jedná o dvojici reálných čísel, které od sebe odečteme a vypočteme čtverec jejich rozdílu). Už pro cca jedenáct trénovacích vzorků se přibližně dosáhne maximální (v této chvíli možné) přesnosti natrénování:
1 106.64 -1.06 2 88.05 -0.70 3 0.15 1.00 4 0.15 1.00 5 0.14 1.00 6 0.18 1.00 7 0.16 1.00 8 0.17 1.00 9 0.20 1.00 10 0.12 1.00 11 0.08 1.00 12 0.08 1.00 13 0.06 1.00 14 0.07 1.00 15 0.08 1.00 16 0.09 1.00 17 0.07 1.00 18 0.08 1.00 19 0.09 1.00 20 0.06 1.00 21 0.07 1.00 22 0.08 1.00 23 0.08 1.00 24 0.09 1.00 25 0.07 1.00 26 0.07 1.00 27 0.07 1.00 28 0.08 1.00 29 0.09 1.00 30 0.09 1.00 31 0.08 1.00 32 0.08 1.00 33 0.08 1.00 34 0.08 1.00 35 0.08 1.00 36 0.08 1.00 37 0.08 1.00 38 0.08 1.00 39 0.08 1.00 40 0.08 1.00
9. Grafické znázornění závislosti MSE, vah neuronů a biasu na počtu vzorků
Fakt, že se neuronová síť dokáže kvalitněji naučit v případě, že jí předáme na trénink větší množství vzorků, jsme si již ověřili, a to dokonce několikrát. Nyní nás ovšem bude zajímat, jak konkrétně toto vylepšení vlastností neuronové sítě vypadá interně, tedy jak (a zda vůbec) se mění váhy a biasy na vstupech neuronů. Pro naši jednoduchou síť se třemi neurony tedy budeme sledovat dvě váhy (vstup do posledního neuronu) a jeho bias. Pro větší přehlednost si necháme vykreslit i průběh MSE a hodnoty R2 score, tedy veličin, které souhrnně určují kvalitu odpovědí sítě (pro klasifikační sítě jsou však lepší matice záměn):
from types import NoneType import matplotlib.pyplot as plt import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 50 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku # zadne skutecne nahodne hodnoty random.seed(19) # priprava dat pro trenink i otestovani neuronove site for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) def train_and_test_nn(size: int): X_train_ = X_train[:size] y_train_ = y_train[:size] # konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000) # trénink modelu nn.fit(X_train_, y_train_) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce # 1 = nejlepší predikce modelu mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print("%2d" % size, "%.2f" % mse, "%.2f" % r2) # vahy na vstupu neuronu ve vystupni vrstve w = nn.coefs_[0] # bias na vstupu neuronu ve vystupni vrstve b = nn.intercepts_[0] # vratit obe vahy i bias return mse, r2, w[0][0], w[1][0], b[0] # trening site az do poctu prvku MAX_N r = range(1, MAX_N+1) weights1 = [] weights2 = [] biases = [] mses = [] r2s = [] # postupne provest trenink site, vyplneni poli s vahami a biasy for i in r: mse, r2, weight1, weight2, bias = train_and_test_nn(i) mses.append(mse) r2s.append(r2) weights1.append(weight1) weights2.append(weight2) biases.append(bias) print(weights1) print(weights2) print(biases) plt.plot(r, mses, r, r2s) plt.legend(["MSE", "R2 score"]) plt.savefig("mse_r2.png") plt.show() plt.plot(r, weights1, r, weights2) plt.legend(["weight1", "weight2"]) plt.savefig("weights.png") plt.show() plt.plot(r, biases) plt.legend(["bias"]) plt.savefig("biases.png") plt.show()
10. Výsledky získané po běhu skriptu
Podívejme se nyní, jak vypadá trénink neuronové sítě po jeho vizualizaci do grafů:

Obrázek 3: Změna vah na vstupu jediného neuronu ve výstupní vrstvě. Po několika kolech učení se síť skutečně naučila správné váhy 0,0 a 1,0.

Obrázek 4: Změna biasu na vstupu jediného neuronu ve výstupní vrstvě. Opět zde můžeme vidět, že po několika iteracích tréninku se bias ustálil na očekávané nulové hodnotě.

Obrázek 5: Četnost chybných odpovědí, které síť při testování produkuje, se postupně zmenšuje a odpovídá předchozím dvěma grafům.
11. Zrychlení tréninku neuronové sítě snížením počtu iterací
Hyperparametrem nazvaným max_iter lze modifikovat počet iterací při tréninku neuronové sítě. Prozatím jsme používali výchozí hodnotu 5000, takže konstrukce neuronové sítě vypadala následovně:
# konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000)
Ovšem celý proces učení můžeme urychlit zadáním menší hodnoty. Samotná topologie neuronové sítě se vůbec nezmění:
# konstrukce modelu nn = MLPRegressor(max_iter=1000, hidden_layer_sizes=(), random_state=1000)
Opět se podívejme na to, jak může vypadat skript, který neuronovou síť natrénuje a použije přitom menší počet iterací, než je výchozí hodnota 5000. Oproti předchozímu skriptu se změnil jen jediný řádek se specifikací hyperparametrů modelu:
from types import NoneType import matplotlib.pyplot as plt import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 50 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku random.seed(19) for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) def train_and_test_nn(size: int): X_train_ = X_train[:size] y_train_ = y_train[:size] # konstrukce modelu nn = MLPRegressor(max_iter=1000, hidden_layer_sizes=(), random_state=1000) # trénink modelu nn.fit(X_train_, y_train_) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce # 1 = nejlepší predikce modelu mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print("%2d" % size, "%.2f" % mse, "%.2f" % r2) # vahy na vstupu neuronu ve vystupni vrstve w = nn.coefs_[0] # bias na vstupu neuronu ve vystupni vrstve b = nn.intercepts_[0] # vratit obe vahy i bias return mse, r2, w[0][0], w[1][0], b[0] # trening site az do poctu prvku MAX_N r = range(1, MAX_N+1) weights1 = [] weights2 = [] biases = [] mses = [] r2s = [] # postupne provest trening site, vyplneni poli s vahami a biasy for i in r: mse, r2, weight1, weight2, bias = train_and_test_nn(i) mses.append(mse) r2s.append(r2) weights1.append(weight1) weights2.append(weight2) biases.append(bias) print(weights1) print(weights2) print(biases) plt.plot(r, mses, r, r2s) plt.legend(["MSE", "R2 score"]) plt.savefig("mse_r2.png") plt.show() plt.plot(r, weights1, r, weights2) plt.legend(["weight1", "weight2"]) plt.savefig("weights.png") plt.show() plt.plot(r, biases) plt.legend(["bias"]) plt.savefig("biases.png") plt.show()
12. Výsledky získané po běhu skriptu: snížení počtu iterací při tréninku neuronové sítě
Výsledky nyní budou vypadat odlišně:

Obrázek 6: Změna vah na vstupu jediného neuronu ve výstupní vrstvě. Neuronová síť se sice učí rychleji, váhy neuronů jsou ale nastaveny špatně. A navíc větší počet trénovacích dat pravděpodobně již nepomůže, což naznačuje pravá strana grafu).

Obrázek 7: Změna biasu na vstupu jediného neuronu ve výstupní vrstvě. Opět si povšimněte, jak špatně se síť naučila – evidentně skončila v lokálním maximu, nikoli v maximu globálním.

Obrázek 8: Četnost chybných odpovědí je oproti původní síti mnohem větší – síť nedokáže odpovídat korektně.
13. Vyšší míra změny vah na vstupu neuronů při tréninku
Kromě počtu iterací můžeme modifikovat i míru změny vah na vstupech jednotlivých neuronů při tréninku. Příliš velká míra změny může znamenat, že sít bude „vyskakovat“ z optimálního stavu (každý nový vstup při tréninku ji bude z tohoto stavu posouvat), na druhou stranu se však může trénink urychlit a dokonce lze překonat lokální maxima. Výchozí hodnotou learning_rate_init je 0.001 a důležité je, že se změna projeví jen u trénovacích algoritmů „adam“ a „sgd“ (viz též předchozí článek).
Pokusme se tuto hodnotu padesátkrát zvýšit:
# konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000, learning_rate_init=0.05)
Upravený skript bude vypadat následovně:
from types import NoneType import matplotlib.pyplot as plt import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 50 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku random.seed(19) for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) def train_and_test_nn(size: int): X_train_ = X_train[:size] y_train_ = y_train[:size] # konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000, learning_rate_init=0.05) # trénink modelu nn.fit(X_train_, y_train_) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce # 1 = nejlepší predikce modelu mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print("%2d" % size, "%.2f" % mse, "%.2f" % r2) # vahy na vstupu neuronu ve vystupni vrstve w = nn.coefs_[0] # bias na vstupu neuronu ve vystupni vrstve b = nn.intercepts_[0] # vratit obe vahy i bias return mse, r2, w[0][0], w[1][0], b[0] # trening site az do poctu prvku MAX_N r = range(1, MAX_N+1) weights1 = [] weights2 = [] biases = [] mses = [] r2s = [] # postupne provest trening site, vyplneni poli s vahami a biasy for i in r: mse, r2, weight1, weight2, bias = train_and_test_nn(i) mses.append(mse) r2s.append(r2) weights1.append(weight1) weights2.append(weight2) biases.append(bias) print(weights1) print(weights2) print(biases) plt.plot(r, mses, r, r2s) plt.legend(["MSE", "R2 score"]) plt.savefig("mse_r2.png") plt.show() plt.plot(r, weights1, r, weights2) plt.legend(["weight1", "weight2"]) plt.savefig("weights.png") plt.show() plt.plot(r, biases) plt.legend(["bias"]) plt.savefig("biases.png") plt.show()
14. Výsledky získané po běhu skriptu: vyšší míra změna vah neuronů
Podívejme se nyní, jak vypadá trénink neuronové sítě po jeho vizualizaci do grafů:

Obrázek 9: Změna vah na vstupu jediného neuronu ve výstupní vrstvě. Po několika kolech učení se síť skutečně naučila správné váhy 0,0 a 1,0.

Obrázek 10: Změna biasu na vstupu jediného neuronu ve výstupní vrstvě. Opět zde můžeme vidět, že po několika iteracích tréninku se bias ustálil na očekávané nulové hodnotě.

Obrázek 11: Četnost chybných odpovědí, které síť při testování produkuje, se postupně zmenšuje a odpovídá předchozím dvěma grafům.
15. Riziko příliš vysoké hodnoty learning_rate_init
Hodnotu learning_rate_init samozřejmě můžeme dále zvyšovat ve smyslu logiky „když poněkud vyšší hodnota pomohla, ještě vyšší hodnota povede k mnohem lepším výsledkům“. Pokusme se tedy tuto hodnotu zvýšit na 0,2, což je v praxi již příliš mnoho (jak posléze uvidíme):
# konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000, learning_rate_init=0.2)
Celý skript:
from types import NoneType import matplotlib.pyplot as plt import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 50 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku random.seed(19) for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) def train_and_test_nn(size: int): X_train_ = X_train[:size] y_train_ = y_train[:size] # konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000, learning_rate_init=0.2) # trénink modelu nn.fit(X_train_, y_train_) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce # 1 = nejlepší predikce modelu mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print("%2d" % size, "%.2f" % mse, "%.2f" % r2) # vahy na vstupu neuronu ve vystupni vrstve w = nn.coefs_[0] # bias na vstupu neuronu ve vystupni vrstve b = nn.intercepts_[0] # vratit obe vahy i bias return mse, r2, w[0][0], w[1][0], b[0] # trening site az do poctu prvku MAX_N r = range(1, MAX_N+1) weights1 = [] weights2 = [] biases = [] mses = [] r2s = [] # postupne provest trening site, vyplneni poli s vahami a biasy for i in r: mse, r2, weight1, weight2, bias = train_and_test_nn(i) mses.append(mse) r2s.append(r2) weights1.append(weight1) weights2.append(weight2) biases.append(bias) print(weights1) print(weights2) print(biases) plt.plot(r, mses, r, r2s) plt.legend(["MSE", "R2 score"]) plt.savefig("mse_r2.png") plt.show() plt.plot(r, weights1, r, weights2) plt.legend(["weight1", "weight2"]) plt.savefig("weights.png") plt.show() plt.plot(r, biases) plt.legend(["bias"]) plt.savefig("biases.png") plt.show()
16. Výsledky získané po běhu skriptu: vysoká míra změny vah neuronů
Neuronová síť již pro hodnotu learning_rate_init==0.2 nebude dobře natrénovaná, což je jasně patrné z následujících průběhů:

Obrázek 12: Změna vah na vstupu jediného neuronu ve výstupní vrstvě. Nyní je síť naučena (zcela) špatně, protože váhy nejsou rovny 0,0 a 1,0.

Obrázek 13: Změna biasu na vstupu jediného neuronu ve výstupní vrstvě. Opět zde můžeme vidět, že po několika iteracích tréninku se bias ustálil, ovšem na nekorektní (nenulové) hodnotě.

Obrázek 14: Četnost chybných odpovědí, které síť při testování produkuje, se již nikdy nezmenší na nulu.
17. Opačný extrém – příliš malá hodnota learning_rate_init
Příliš velká hodnota learning_rate_init nám příliš nepomohla, takže zkusíme opačný extrém, tj. nastavit tento hyperparametr na příliš malou hodnotu, konkrétně na desetinu výchozí hodnoty:
# konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000, learning_rate_init=0.0001)
Opět si – pouze pro úplnost – uvedeme celý skript:
from types import NoneType import matplotlib.pyplot as plt import numpy as np import random from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # model zalozeny na neuronove siti from sklearn.neural_network import MLPRegressor # velikost vstupu MAX_N = 50 # X je matice, y je vektor X = np.zeros( (MAX_N, 2) ) # kombinace vstupu y = np.zeros( (MAX_N, )) # vektor vysledku random.seed(19) for i in range(0, MAX_N): X[i, 0] = random.randint(-10, 10) X[i, 1] = random.randint(-10, 10) y[i] = X[i, 1] # rozdeleni dat na treninkovou a testovaci mnozinu X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) def train_and_test_nn(size: int): X_train_ = X_train[:size] y_train_ = y_train[:size] # konstrukce modelu nn = MLPRegressor(max_iter=5000, hidden_layer_sizes=(), random_state=1000, learning_rate_init=0.0001) # trénink modelu nn.fit(X_train_, y_train_) # predikce modelu y_pred = nn.predict(X_test) # chyba predikce # 1 = nejlepší predikce modelu mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print("%2d" % size, "%.2f" % mse, "%.2f" % r2) # vahy na vstupu neuronu ve vystupni vrstve w = nn.coefs_[0] # bias na vstupu neuronu ve vystupni vrstve b = nn.intercepts_[0] # vratit obe vahy i bias return mse, r2, w[0][0], w[1][0], b[0] # trening site az do poctu prvku MAX_N r = range(1, MAX_N+1) weights1 = [] weights2 = [] biases = [] mses = [] r2s = [] # postupne provest trening site, vyplneni poli s vahami a biasy for i in r: mse, r2, weight1, weight2, bias = train_and_test_nn(i) mses.append(mse) r2s.append(r2) weights1.append(weight1) weights2.append(weight2) biases.append(bias) print(weights1) print(weights2) print(biases) plt.plot(r, mses, r, r2s) plt.legend(["MSE", "R2 score"]) plt.savefig("mse_r2.png") plt.show() plt.plot(r, weights1, r, weights2) plt.legend(["weight1", "weight2"]) plt.savefig("weights.png") plt.show() plt.plot(r, biases) plt.legend(["bias"]) plt.savefig("biases.png") plt.show()
18. Výsledek běhu dnešního posledního demonstračního příkladu
Již naposledy se dnes podívejme na vizualizovanou interní strukturu naší neuronové sítě se třemi neurony:

Obrázek 15: Změna vah na vstupu jediného neuronu ve výstupní vrstvě. Nyní je síť opět naučena (zcela) špatně, protože váhy nejsou rovny 0,0 a 1,0.

Obrázek 16: Změna biasu na vstupu jediného neuronu ve výstupní vrstvě. Opět zde můžeme vidět, že po několika iteracích tréninku se bias ustálil, ovšem na nekorektní (nenulové) hodnotě.

Obrázek 17: Četnost chybných odpovědí, které síť při testování produkuje, se již nikdy nezmenší na nulu a navíc je hodnota MSE obrovská (měla by být ideálně desetinová nebo ještě menší).
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