Obsah
1. Deklarace třídy představující neuronovou síť
2. Definice vrstev neuronové sítě
3. Pomocný modul pro přípravu trénovacích a testovacích dat
5. Třetí demonstrační příklad: trénink neuronové sítě
6. Vizualizace výsledků tréninku
7. Čtvrtý demonstrační příklad: trénink neuronové sítě se zobrazením kvality tréninku
8. Přidání dalších vrstev do neuronové sítě
9. Pátý demonstrační příklad: neuronová síť s jednou skrytou vrstvou
10. Riziko nedoučení složitější neuronové sítě
11. Šestý demonstrační příklad: neuronová síť s více skrytými vrstvami, která nebude dotrénována
12. Sedmý demonstrační příklad: vliv parametru learning_rate na rychlosti naučení sítě
13. Porovnání účelové funkce všech tří doposud použitých neuronových sítí
14. Ověření kvality neuronové sítě
15. Osmý demonstrační příklad: výpočet kvality neuronové sítě
16. Vizualizace predikce neuronové sítě: body patřící do první nebo druhé skupiny
17. Devátý demonstrační příklad: vizualizace predikce neuronové sítě
18. Výsledky získané devátým demonstračním příkladem
19. Repositář s demonstračními příklady
1. Deklarace třídy představující neuronovou síť
Dnešní článek je, částečně na rozdíl od článku předchozího, zaměřen prakticky. Ukážeme si v něm tvorbu a konfiguraci neuronové sítě, natrénování této sítě, její otestování, vizualizaci výsledků atd. Taktéž se zmíníme o problému přeučení a nedoučení. Celý postup si ukážeme krok za krokem a z tohoto důvodu je dnešní první příklad triviální. Je v něm ukázáno, jakým způsobem se s využitím knihovny PyTorch deklaruje třída představující neuronovou síť. V té nejjednodušší podobě postačuje nadeklarovat novou třídu odvozenou od třídy torch.nn.Module:
from torch import nn
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self):
super().__init__()
# konstrukce neuronové sítě
nn1 = NeuralNetwork()
# výpis základních informací o neuronové síti
print(nn1)
Po spuštění tohoto skriptu se zobrazí základní informace o této síti:
NeuralNetwork()
2. Definice vrstev neuronové sítě
Minule jsme si řekli, že umělé neuronové sítě se typicky skládají z vrstev neuronů. Velmi jednoduchá síť může vypadat následovně:
Obrázek 1: Uspořádání neuronů do vrstev ve feed-forward síti.
V PyTorchi je přidání nové vrstvy (resp. přesněji řečeno propojení mezi vrstvami) relativně snadné. Ukažme si tu nejjednodušší konfiguraci sítě, tj. síť, která bude mít input_dim vstupů a output_dim výstupů. Mezi vstupy a výstupy se provádí výpočet běžné afinní (lineární) transformace a v metodě forward aplikace aktivační funkce. Tím je vlastně realizována funkce umělého neuronu – váhování vstupů a přičtení biasu. Interně je tato část realizována maticí input_dim×output_dim vah a vektorem s biasy. Výpočet s využitím aktivační funkce je deklarován v metodě forward. Tento výpočet je prováděn se všemi vstupy a výsledek je poslán na výstup neuronové sítě:
from torch import nn
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronovou síť
x = nn.functional.sigmoid(self.layer_1(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
output_dim = 1
# konstrukce neuronové sítě
nn2 = NeuralNetwork(input_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn2)
# výpis informace o vrstvě neuronové sítě
print(nn2.layer_1)
# výpis informace o transformační matici a biasech
print(nn2.layer_1.weight)
print(nn2.layer_1.bias)
Po spuštění se nejdříve vypíše informace o celé neuronové síti:
NeuralNetwork( (layer_1): Linear(in_features=2, out_features=1, bias=True) )
Dále se vypíše informace o její jediné vrstvě:
Linear(in_features=2, out_features=1, bias=True)
A na závěr obsah transformační matice (2×1) a vektor biasů (má jediný bias). Ve výchozím nastavení jsou tyto hodnoty náhodné:
Parameter containing: tensor([[0.2180, 0.6056]], requires_grad=True) Parameter containing: tensor([0.2079], requires_grad=True)
Tato síť tedy pro vstupy [x1, x2] provádí výpočet:
y = x1 * 0,2180 + x2 * 0,6056 + 0,2079
Což je triviální lineární transformace z roviny na přímku.
3. Pomocný modul pro přípravu trénovacích a testovacích dat
Pro neuronové sítě, které budeme tvořit v rámci dalších kapitol, je nutné připravit trénovací a testovací data. Základy jsme si již ukázali minule. Připomeňme si, že jsme k tomuto účelu použili funkci sklearn.datasets.make_circles určenou pro vygenerování sady bodů v rovině, přičemž každý bod patří buď do vnější nebo vnitřní kružnice (každý bod má nastaven příslušný label). Následně se sada bodů rozdělí na trénovací data a testovací data – tyto skupiny bodů se nepřekrývají a jsou ze vstupu vybrány náhodně.
Obrázek 2: Trénovací a testovací data získaná rozdělením bodů získanýchfunkcí make_circles.
Skript byl upraven do takové podoby, aby trénovací a testovací data vracel z funkce compute_train_and_test_data, což nám později usnadní použití tohoto modulu:
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split
import torch
import numpy as np
from torch.utils.data import Dataset, DataLoader
# konverze původních dat z NumPy do tenzorů
class Data(Dataset):
def __init__(self, X, y):
self.X = torch.from_numpy(X.astype(np.float32))
self.y = torch.from_numpy(y.astype(np.float32))
self.len = self.X.shape[0]
def __getitem__(self, index):
return self.X[index], self.y[index]
def __len__(self):
return self.len
def compute_train_and_test_data(
n_samples=2000, factor=0.5, noise=0.05, test_size=1 / 3
):
samples, labels = make_circles(n_samples=n_samples, factor=factor, noise=noise)
# rozdělení na trénovací a testovací množinu
X_train, X_test, y_train, y_test = train_test_split(
samples, labels, test_size=test_size, random_state=26
)
# trénovací a testovací sada
# trénovací sada
train_data = Data(X_train, y_train)
# testovací sada
test_data = Data(X_test, y_test)
return train_data, test_data
Použití tohoto modulu je snadné:
# trénovací a testovací data from compute_train_and_test_data import compute_train_and_test_data train_data, test_data = compute_train_and_test_data() print(train_data.X) print(train_data.y) print() print(test_data.X) print(test_data.y)
Po spuštění se vypíše matice X a vektor y pro trénovací i testovací data:
tensor([[ 0.4599, 0.0053],
[ 0.7305, 0.6499],
[ 0.2827, 0.4137],
...,
[-0.4188, -0.3083],
[ 0.0909, -0.5549],
[-0.4897, 0.2897]])
tensor([1., 0., 1., ..., 1., 1., 1.])
tensor([[-0.2496, 0.9122],
[ 0.4308, 0.2262],
[ 0.5084, 0.2717],
...,
[ 0.4003, 0.3459],
[-0.3190, -0.9857],
[-0.3120, 0.3337]])
tensor([0., 1., 1., 1., 1., 1., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0.,
...
...
...
4. Trénink neuronové sítě
Nejzajímavější je vlastní proces tréninku (učení) neuronové sítě. Ten může probíhat několika způsoby, ovšem nejčastější je učení založené na tom, že na vstup sítě přivedeme data, u nichž dopředu známe očekávaný výsledek (takzvaná trénovací data). Neuronová síť pro tato vstupní data provede svůj odhad (z počátku náhodný, v dalším kroku velmi špatný, potom lepší atd.) a na základě rozdílů mezi odhadem sítě a očekávaným výsledkem se více či méně sofistikovanými algoritmy nepatrně pozmění váhy wi na vstupech do neuronů (včetně biasu, tedy w0).
Obrázek 3: Idealizovaný model neuronu s biasem. V průběhu tréninku se upravují váhy wi.
Konkrétní míra změn váhy na vstupech neuronů v jednotlivých vrstvách sítě je globálně řízena dalším parametrem či několika parametry, z nichž ten nejdůležitější ovlivňuje rychlost učení. Ta by neměla být příliš nízká (to ovšem vyžaduje objemná trénovací data nebo jejich opakování), ale ani příliš vysoká, protože by síť mohla „oscilovat“ mezi několika neoptimálními stavy. Základní algoritmus učení neuronové sítě se jmenuje backpropagation, protože se váhy skutečně mění v opačném směru – od výstupů (na něž se přivede vypočtená chyba) ke vstupům. Asi nejlépe je tento koncept popsán v článku dostupném na adrese https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/, tuto část za nás však vykoná knihovna PyTorch ve fázi učení zcela automaticky.
5. Třetí demonstrační příklad: trénink neuronové sítě
Trénink neuronové sítě je ukázán v dnešním třetím demonstračním příkladu. Ten je rozdělen do čtyř částí. První část již známe – ta slouží pro konstrukci neuronové sítě, která je v našem případě reprezentována objektem typu NeuralNetwork. Ve druhé části získáme trénovací data (prozatím skutečně jen trénovací data) z modulu compute_train_and_test_data popsaného ve třetí kapitole. V části třetí je provedeno vlastní učení (trénink) neuronové sítě s využitím trénovacích dat. A konečně v části čtvrté si necháme vypsat hodnoty vypočtené takzvanou účelovou funkcí (loss function), jejíž hodnoty reprezentují rozdíly mezi očekávaným výsledkem (ten při tréninku pochopitelně musíme znát) a odhadem neuronové sítě. V ideálním případě by měly tyto hodnoty postupně klesat, protože síť by měla v procesu učení zlepšovat své odhady:
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = nn.functional.sigmoid(self.layer_1(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
output_dim = 1
# konstrukce neuronové sítě
nn3 = NeuralNetwork(input_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn3)
# příprava na trénink neuronové sítě
learning_rate = 0.1
loss_fn = nn.BCELoss()
optimizer = optim.SGD(nn3.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, _ = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 100
loss_values = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
last_lost_value = None
for X, y in train_dataloader:
optimizer.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn3(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values.append(loss.item())
loss.backward()
optimizer.step()
last_lost_value = loss.item()
print(".", end="")
print(last_lost_value)
print("Training completed")
print("Loss values")
for i, loss_value in enumerate(loss_values):
print(i, loss_value)
Výsledky ukazují jednotlivé prováděné kroky:
Konstrukce neuronové sítě:
NeuralNetwork( (layer_1): Linear(in_features=2, out_features=1, bias=True) )
Rozdělená trénovací data:
Batches: 21
Trénink neuronové sítě:
Training started
Epoch 0: .....................0.7136642932891846
Epoch 1: .....................0.7086359858512878
Epoch 2: .....................0.7138426899909973
Epoch 3: .....................0.71360182762146
Epoch 4: .....................0.7031393051147461
Epoch 5: .....................0.6998087763786316
Epoch 6: .....................0.685001790523529
Epoch 7: .....................0.701408326625824
Epoch 8: .....................0.6959707140922546
Epoch 9: .....................0.6810523271560669
Epoch 10: .....................0.6941555738449097
...
...
...
Epoch 87: .....................0.6884103417396545
Epoch 88: .....................0.698021650314331
Epoch 89: .....................0.6896729469299316
Epoch 90: .....................0.691299557685852
Epoch 91: .....................0.6931966543197632
Epoch 92: .....................0.6909589171409607
Epoch 93: .....................0.6942797899246216
Epoch 94: .....................0.6978365182876587
Epoch 95: .....................0.6871546506881714
Epoch 96: .....................0.6888548135757446
Epoch 97: .....................0.6873869299888611
Epoch 98: .....................0.6864196062088013
Epoch 99: .....................0.6999951601028442
Training completed
Hodnoty účelové funkce v průběhu tréninku:
Loss values 0 0.7395060062408447 1 0.7825191020965576 2 0.7868967652320862 3 0.786351203918457 4 0.7562863826751709 5 0.7235647439956665 6 0.742216944694519 7 0.6739267110824585 8 0.7016011476516724 9 0.7245702147483826 10 0.664133608341217 ... ... ... 82 0.697323203086853 83 0.6908646821975708 84 0.6865593791007996 85 0.6937276124954224 86 0.7040309309959412 87 0.6995502710342407 88 0.7057774066925049
6. Vizualizace výsledků tréninku
Tabulka s hodnotami účelové funkce nám může prozradit, jak rychle (a zda vůbec) se síť dokáže učit. Počáteční hodnota této funkce může být vysoká (resp. přesněji řečeno blízká jedničce), protože na začátku učení jsou váhy jednotlivých neuronů nastaveny na náhodnou hodnotu. Ovšem v průběhu tréninku se na vstup sítě zapisují trénovací hodnoty, na výstupu jsou zjištěny rozdíly mezi očekávaným výsledkem a výsledkem, který poskytne síť a podle rozdílu těchto hodnot jsou postupně (od poslední vrstvy) váhy neuronů upravovány tak, aby byl další výsledek (v ideálním případě) lepší.
Neuronová síť by se tedy měla postupně zlepšovat a hodnota účelové funkce by měla postupně klesat směrem k nule. Je zde mnoho proměnných, které tento postup ovlivňují a postupně se s nimi seznámíme v rámci dalšího textu. Základem ovšem bude vizualizace účelové funkce, tj. změny její hodnoty v čase. Pokud nebude hodnota klesat ani po několika stech či tisících kroků, bude nutné změnit parametry sítě (počet vrstev, počet neuronů, typ aktivačních funkcí atd.).
7. Čtvrtý demonstrační příklad: trénink neuronové sítě se zobrazením kvality tréninku
Čtvrtý demonstrační příklad se do značné míry podobá příkladu třetímu, ovšem s tím rozdílem, že výsledky průběhu tréninku jsou zobrazeny formou grafu (poslední, pátá část skriptu). Pro vizualizaci opět použijeme, podobně jako v předchozím článku, knihovnu Matplotlib. Povšimněte si, že Matplotlib dokáže pracovat s n-dimenzionálními poli knihovny NumPy, ale nikoli už z tenzory knihovny PyTorch:
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = nn.functional.sigmoid(self.layer_1(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
output_dim = 1
# konstrukce neuronové sítě
nn4 = NeuralNetwork(input_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn4)
# příprava na trénink neuronové sítě
learning_rate = 0.1
loss_fn = nn.BCELoss()
optimizer = optim.SGD(nn4.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, _ = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 100
loss_values = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
last_lost_value = None
for X, y in train_dataloader:
optimizer.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn4(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values.append(loss.item())
loss.backward()
optimizer.step()
last_lost_value = loss.item()
print(".", end="")
print(last_lost_value)
print("Training completed")
step = range(len(loss_values))
# příprava na vykreslení grafu
fig, ax = plt.subplots(figsize=(6.4, 4.8))
plt.plot(step, np.array(loss_values))
plt.title("Průběh tréninku neuronové sítě")
plt.xlabel("Epocha")
plt.ylabel("Účelová funkce")
# uložení do souboru
plt.savefig("nn_4.png")
# vykreslení grafu
plt.show()
Ze zobrazeného grafu je patrné, že naše neuronová síť je velmi mizerná a vlastně se nedokáže skutečně natrénovat (protože vstupní data mají složité interní vztahy, složitější, než lze naučit dva neurony):
Obrázek 4: Průběh učení neuronové sítě bez skryté vrstvy.
8. Přidání dalších vrstev do neuronové sítě
Mohlo by se zdát, že větší neuronová síť (tedy více neuronů) může znamenat, že dostaneme i kvalitnější model a tím pádem i lepší výsledky. Ovšem v praxi můžeme narazit na úplný opak, a to ve chvíli, kdy se neuronová síť nedokáže správně zaučit – datová sada je buď příliš malá, nebo je neuronů tolik, že gradient při změně jejich vah je příliš malý nebo dokonce nulový. Ovšem zaměřme se nejdříve na případ, kdy vyšší počet vrstev a neuronů v těchto vrstvách má dobrý vliv na kvalitu modelu. Do nové verze naší neuronové sítě přidáme další vrstvu. Již se nebude jednat o vrstvu vstupní ani výstupní, ale o takzvanou skrytou vrstvu:
self.layer_1 = nn.Linear(input_dim, hidden_dim) self.layer_2 = nn.Linear(hidden_dim, output_dim)
Konfigurace vrstev:
input_dim = 2 hidden_dim = 10 output_dim = 1
Na vstupu neuronové sítě jsou dva vstupy, což odpovídá dvojicím souřadnic bodů [x, y]. Výsledkem (výstupem) je jediná hodnota, která bude naznačovat, do které skupiny body patří. A skrytá vrstva bude mít deset neuronů. To je již poměrně komplikovaná síť 2→10→1 neurony, která by mohla mít lepší učící schopnosti, než první verze sítě.
Mimochodem: pochopitelně se změní i výpočet prováděný neuronovou sítí. Ten nyní může vypadat takto (v každé vrstvě použijeme odlišné aktivační funkce):
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = torch.nn.functional.relu(self.layer_1(x))
x = torch.nn.functional.sigmoid(self.layer_2(x))
return x
9. Pátý demonstrační příklad: neuronová síť s jednou skrytou vrstvou
V pátém demonstračním příkladu použijeme pro trénink a vyhodnocení neuronové sítě síť s jednou skrytou vrstvou. Konfigurace sítě přesně odpovídá popisu z osmé kapitoly:
import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = torch.nn.functional.relu(self.layer_1(x))
x = torch.nn.functional.sigmoid(self.layer_2(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
hidden_dim = 10
output_dim = 1
# konstrukce neuronové sítě
nn5 = NeuralNetwork(input_dim, hidden_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn5)
# příprava na trénink neuronové sítě
learning_rate = 0.1
loss_fn = nn.BCELoss()
optimizer = optim.SGD(nn5.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, _ = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 100
loss_values = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
last_lost_value = None
for X, y in train_dataloader:
optimizer.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn5(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values.append(loss.item())
loss.backward()
optimizer.step()
last_lost_value = loss.item()
print(".", end="")
print(last_lost_value)
print("Training completed")
step = range(len(loss_values))
# příprava na vykreslení grafu
fig, ax = plt.subplots(figsize=(6.4, 4.8))
plt.plot(step, np.array(loss_values))
plt.title("Průběh tréninku neuronové sítě")
plt.xlabel("Epocha")
plt.ylabel("Účelová funkce")
# uložení do souboru
plt.savefig("nn_5.png")
# vykreslení grafu
plt.show()
Obrázek 5: Průběh učení neuronové sítě s jednou skrytou vrstvou.
10. Riziko nedoučení složitější neuronové sítě
Při porovnání průběhů účelové funkce pro neuronovou síť bez skryté vrstvy a pro sít s jednou vrstvou jsou výsledky zřejmé: první síť se nedokáže učit, kdežto druhá ano:
Obrázek 6: Průběh učení neuronové sítě bez skryté vrstvy a sítě s jednou skrytou vrstvou.
Z toho by mohl plynout chybný závěr, že čím více vrstev (a čím více neuronů) bude neuronová síť obsahovat, tím bude kvalitnější a bude se i lépe učit. V praxi tomu tak není, protože se zde projevuje další proměnná – learning rate. Tu potřebujeme mít dostatečně velkou na to, aby se síť s každými dalšími trénovacími daty učila, ale na druhou stranu dostatečně malou, aby nedocházelo k oscilacím. Navíc u rozsáhlých sítí dochází k efektu nazvanému vanishing gradient, kterému se budeme podrobněji věnovat příště. Ovšem závěr je (pro tuto chvíli) následující: neuronová síť má být dostatečně rozsáhlá, aby se naučila řešit náš problém, ale ne rozsáhlejší.
Mimochodem – obrázek 6 byl vypočten tímto skriptem, který v sobě spojuje předchozí dva příklady (a několik zjednodušení):
import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
class NeuralNetwork4(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronovou síť
x = nn.functional.sigmoid(self.layer_1(x))
return x
class NeuralNetwork5(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronovou síť
x = torch.nn.functional.relu(self.layer_1(x))
x = torch.nn.functional.sigmoid(self.layer_2(x))
return x
# konstrukce dvou neuronových sítí
nn4 = NeuralNetwork4(2, 1)
nn5 = NeuralNetwork5(2, 10, 1)
# příprava na trénink neuronové sítě
learning_rate = 0.1
loss_fn = nn.BCELoss()
optimizer4 = optim.SGD(nn4.parameters(), lr=learning_rate)
optimizer5 = optim.SGD(nn5.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, _ = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 100
loss_values_4 = []
loss_values_5 = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
for X, y in train_dataloader:
optimizer4.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn4(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values_4.append(loss.item())
loss.backward()
optimizer4.step()
optimizer5.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn5(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values_5.append(loss.item())
loss.backward()
optimizer5.step()
print(".", end="")
print()
print("Training completed")
step = range(len(loss_values_4))
# příprava na vykreslení grafu
fig, ax = plt.subplots(figsize=(6.4, 4.8))
plt.plot(step, np.array(loss_values_4), label="nn4")
plt.plot(step, np.array(loss_values_5), label="nn5")
plt.title("Průběh tréninku neuronové sítě")
plt.xlabel("Epocha")
plt.ylabel("Účelová funkce")
plt.legend(loc="best")
# uložení do souboru
plt.savefig("nn_4_5.png")
# vykreslení grafu
plt.show()
11. Šestý demonstrační příklad: neuronová síť s více skrytými vrstvami, která nebude dotrénována
V dalším demonstračním příkladu je vytvořena sít s mnoha vrstvami, které způsobí nedoučení sítě, protože máme málo trénovacích dat a především hodnota learning date je nastavena velmi nízko:
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, hidden_dim)
self.layer_3 = nn.Linear(hidden_dim, hidden_dim)
self.layer_4 = nn.Linear(hidden_dim, output_dim)
Nastavení parametrů učení:
# příprava na trénink neuronové sítě learning_rate = 0.1 loss_fn = nn.BCELoss() optimizer = optim.SGD(nn6.parameters(), lr=learning_rate)
Tato mnohem komplikovanější síť bude ve skutečnosti prakticky stejně nekvalitní, jako zcela první síť bez skrytých vrstev:
Obrázek 7: Účelová funkce s větším množstvím skrytých vrstev, které ve výsledku vedou k jejímu nedoučení.
Zdrojový kód tohoto příkladu vypadá následovně:
import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, hidden_dim)
self.layer_3 = nn.Linear(hidden_dim, hidden_dim)
self.layer_4 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = torch.nn.functional.relu(self.layer_1(x))
x = torch.nn.functional.sigmoid(self.layer_2(x))
x = torch.nn.functional.sigmoid(self.layer_3(x))
x = torch.nn.functional.sigmoid(self.layer_4(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
hidden_dim = 10
output_dim = 1
# konstrukce neuronové sítě
nn6 = NeuralNetwork(input_dim, hidden_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn6)
# příprava na trénink neuronové sítě
learning_rate = 0.1
loss_fn = nn.BCELoss()
optimizer = optim.SGD(nn6.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, _ = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 100
loss_values = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
last_lost_value = None
for X, y in train_dataloader:
optimizer.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn6(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values.append(loss.item())
loss.backward()
optimizer.step()
last_lost_value = loss.item()
print(".", end="")
print(last_lost_value)
print("Training completed")
step = range(len(loss_values))
# příprava na vykreslení grafu
fig, ax = plt.subplots(figsize=(6.4, 4.8))
plt.plot(step, np.array(loss_values))
plt.title("Průběh tréninku neuronové sítě")
plt.xlabel("Epocha")
plt.ylabel("Účelová funkce")
# uložení do souboru
plt.savefig("nn_6.png")
# vykreslení grafu
plt.show()
12. Sedmý demonstrační příklad: vliv parametru learning_rate na rychlosti naučení sítě
Zkusme nyní zjistit, co se stane ve chvíli, kdy sice stále budeme používat neuronovou síť s více skrytými vrstvami, ovšem zvýšíme hodnotu parametru learning rate.
Konfigurace neuronové sítě:
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, hidden_dim)
self.layer_3 = nn.Linear(hidden_dim, hidden_dim)
self.layer_4 = nn.Linear(hidden_dim, output_dim)
Parametry učení neuronové sítě:
# příprava na trénink neuronové sítě learning_rate = 0.5 loss_fn = nn.BCELoss() optimizer = optim.SGD(nn7.parameters(), lr=learning_rate)
Tato síť se bude učit rychleji a nedojde k efektu vanishing gradient, takže průběh účelové funkce bude téměř dokonalý:
Obrázek 8: Účelová funkce pro neuronovou síť s více skrytými vrstvami a zvýšenou hodnotou learning rate.
Celý zdrojový kód příkladu:
import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, hidden_dim)
self.layer_3 = nn.Linear(hidden_dim, hidden_dim)
self.layer_4 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = torch.nn.functional.relu(self.layer_1(x))
x = torch.nn.functional.sigmoid(self.layer_2(x))
x = torch.nn.functional.sigmoid(self.layer_3(x))
x = torch.nn.functional.sigmoid(self.layer_4(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
hidden_dim = 10
output_dim = 1
# konstrukce neuronové sítě
nn7 = NeuralNetwork(input_dim, hidden_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn7)
# příprava na trénink neuronové sítě
learning_rate = 0.5
loss_fn = nn.BCELoss()
optimizer = optim.SGD(nn7.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, _ = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 100
loss_values = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
last_lost_value = None
for X, y in train_dataloader:
optimizer.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn7(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values.append(loss.item())
loss.backward()
optimizer.step()
last_lost_value = loss.item()
print(".", end="")
print(last_lost_value)
print("Training completed")
step = range(len(loss_values))
# příprava na vykreslení grafu
fig, ax = plt.subplots(figsize=(6.4, 4.8))
plt.plot(step, np.array(loss_values))
plt.title("Průběh tréninku neuronové sítě")
plt.xlabel("Epocha")
plt.ylabel("Účelová funkce")
# uložení do souboru
plt.savefig("nn_7.png")
# vykreslení grafu
plt.show()
13. Porovnání účelové funkce všech tří doposud použitých neuronových sítí
Zajímavé bude porovnání účelové funkce získané při tréninku všech tří neuronových sítí, které jsme si popsali v předchozích kapitolách. Jedná se postupně o síť bez skrytých vrstev, síť s jednou skrytou vrstvou (10 neuronů) a parametrem learning rate nastaveným na hodnotu 0,1 a konečně o síť se třemi skrytými vrstvami (10→10→10 neuronů), ovšem s parametrem learning rate nastaveným na hodnotu 0,5 (rychlejší učení, menší pravděpodobnost vanishing gradientu):
Obrázek 9: Porovnání účelové funkce všech tří doposud použitých neuronových sítí.
Z tohoto průběhu je patrné, že poslední síť s mnoha skrytými vrstvami bude ve výsledku kvalitnější, ovšem musíme zajistit dostatečně dlouhý trénink (množství trénovacích dat atd.), protože je síť zpočátku tréninku horší, než jednodušší sítě. Až později dojde k žádoucímu zlomu a poklesu hodnoty účelové funkce. V tomto okamžiku by se mohlo s tréninkem skončit, aby se ušetřily zdroje a zabránilo se případnému přetrénování. Naproti tomu první síť je tak primitivní, že ani delší trénink její schopnosti nezlepší:
Obrázek 10: Porovnání v případě, že se provede dvojnásobek tréninku.
14. Ověření kvality neuronové sítě
Zjištění hodnot účelové funkce je sice užitečné (už jen proto, že naznačuje, kdy je vhodné trénink ukončit), ale stále nám nic neříká o tom, jak kvalitně dokáže neuronová síť predikovat výsledky na základě zadaných vstupů – což je vlastně jediný účel, proč jsme neuronovou síť vytvořili. Z tohoto důvodu musíme provést test sítě, a to s využitím testovacích (validačních) dat. Tato data by se neměla překrývat s trénovacími daty, protože nás příliš nezajímá, že se síť dokáže naučit nazpaměť předané výsledky (na to by stačila triviální implementace cache), ale spíše její schopnosti generalizace.
Do sítě tedy budeme posílat testovací data a porovnávat výsledky sítě s očekávanými výsledky (ty známe). Povšimněte si způsobu převodu reálného čísla na výstupu sítě (hodnoty v rozsahu 0 až 1 – jedná se o obor hodnot aktivační funkce sigmoid) na binární hodnotu říkající, zda vstupní bod [X1, X2] náleží do prvního nebo do druhého mezikruží. Zbylé programové řádky pouze slouží pro výpočet přesnosti v rozsahu 0 až 100%:
test_dataloader = DataLoader(dataset=test_data, batch_size=batch_size, shuffle=True)
correct = 0
total = 0
import itertools
with torch.no_grad():
for X, y in test_dataloader:
outputs = nn8(X)
predicted = np.where(outputs.numpy() < 0.5, 0, 1)
predicted = list(itertools.chain(*predicted))
total += y.size(0)
correct += (predicted == y.numpy()).sum().item()
print(f"Accuracy: {100 * correct // total}%")
15. Osmý demonstrační příklad: výpočet kvality neuronové sítě
V pořadí již osmém demonstračním příkladu provedeme výpočet resp. přesněji řečeno ověření kvality neuronové sítě. Máme k dispozici testovací data odlišná od trénovacích dat. Necháme tedy síť předpovědět, které body z testovacích dat patří do první skupiny (mezikruží) a které do skupiny druhé. Poté již jednoduchou statistikou zjistíme míru přesnosti neuronové sítě:
import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, hidden_dim)
self.layer_3 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = torch.nn.functional.relu(self.layer_1(x))
x = torch.nn.functional.sigmoid(self.layer_2(x))
x = torch.nn.functional.sigmoid(self.layer_3(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
hidden_dim = 10
output_dim = 1
# konstrukce neuronové sítě
nn8 = NeuralNetwork(input_dim, hidden_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn8)
# příprava na trénink neuronové sítě
learning_rate = 0.1
loss_fn = nn.BCELoss()
optimizer = optim.SGD(nn8.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, test_data = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 20
loss_values = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
last_lost_value = None
for X, y in train_dataloader:
optimizer.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn8(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values.append(loss.item())
loss.backward()
optimizer.step()
last_lost_value = loss.item()
print(".", end="")
print(last_lost_value)
print("Training completed")
test_dataloader = DataLoader(dataset=test_data, batch_size=batch_size, shuffle=True)
correct = 0
total = 0
import itertools
with torch.no_grad():
for X, y in test_dataloader:
outputs = nn8(X)
predicted = np.where(outputs.numpy() < 0.5, 0, 1)
predicted = list(itertools.chain(*predicted))
total += y.size(0)
correct += (predicted == y.numpy()).sum().item()
print(f"Accuracy: {100 * correct // total}%")
Výsledky (nejdůležitější je poslední řádek):
NeuralNetwork(
(layer_1): Linear(in_features=2, out_features=10, bias=True)
(layer_2): Linear(in_features=10, out_features=10, bias=True)
(layer_3): Linear(in_features=10, out_features=1, bias=True)
)
Batches: 21
Training started
Epoch 0: .....................0.6994423866271973
Epoch 1: .....................0.6892452836036682
Epoch 2: .....................0.6878048181533813
Epoch 3: .....................0.6901800632476807
Epoch 4: .....................0.6891487240791321
Epoch 5: .....................0.6901738047599792
Epoch 6: .....................0.6905770897865295
Epoch 7: .....................0.6840065121650696
Epoch 8: .....................0.6886505484580994
Epoch 9: .....................0.6881945133209229
Epoch 10: .....................0.6873928904533386
...
...
...
Epoch 90: .....................0.030736887827515602
Epoch 91: .....................0.033318083733320236
Epoch 92: .....................0.026814712211489677
Epoch 93: .....................0.02321838028728962
Epoch 94: .....................0.023601409047842026
Epoch 95: .....................0.026054512709379196
Epoch 96: .....................0.03182302415370941
Epoch 97: .....................0.021505670621991158
Epoch 98: .....................0.02354506216943264
Epoch 99: .....................0.024997740983963013
Training completed
Accuracy: 100%
16. Vizualizace predikce neuronové sítě: body patřící do první nebo druhé skupiny
Výsledek, který jsme získali skriptem uvedeným v deváté kapitole, nám pouze jednorozměrným číslem určuje míru úspěšnosti neuronové sítě při predikcích. Ovšem v praxi je mnohem lepší si výsledky vhodným způsobem vizualizovat, protože jen tak lze zjistit, v jakých oblastech dává síť nekorektní odpovědi atd. V našem konkrétním případě je vizualizace až triviálně snadná, protože na vstupu jsou body v rovině a výstupem sítě je hodnota říkající, zda bod patří do prvního či druhého mezikruží. To znamená, že si můžeme vykreslit vstupní body do grafu a obarvit je podle toho, jestli síť odpověděla 1 nebo 2 (ve skutečnosti je odpovědí reálné číslo z rozsahu 0 až 1, to je však snadno převoditelné na binární hodnotu). Do skriptu doplníme tento kód, který zajistí vizualizaci:
import itertools
all_predicts = []
x_coords = []
y_coords = []
with torch.no_grad():
for X, y in test_dataloader:
outputs = nn9(X)
predicted = np.where(outputs.numpy() < 0.5, 0, 1)
predicted = list(itertools.chain(*predicted))
all_predicts += predicted
coords = X.tolist()
for coord in coords:
x_coords.append(coord[0])
y_coords.append(coord[1])
# velikost obrázku s grafem
plt.subplots(figsize=(6.4, 6.4))
# vizualizace
plt.scatter(x_coords, y_coords, s=1.5, c=all_predicts, cmap=plt.cm.Set1)
# popisek grafu
plt.title("Predikované výsledky")
# uložení grafu do souboru
plt.savefig("nn_9.png")
# vykreslení na obrazovku
plt.show()
17. Devátý demonstrační příklad: vizualizace predikce neuronové sítě
Postup popsaný v šestnácté kapitole je součástí dnešního posledního demonstračního příkladu, jehož zdrojový kód vypadá následovně:
import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
# budeme provádět vykreslování de facto standardní knihovnou Matplotlib
import matplotlib.pyplot as plt
class NeuralNetwork(nn.Module):
"""Třída reprezentující neuronovou síť."""
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
# vrstvy neuronové sítě
self.layer_1 = nn.Linear(input_dim, hidden_dim)
self.layer_2 = nn.Linear(hidden_dim, hidden_dim)
self.layer_3 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# propagace hodnot přes neuronvou síť
x = torch.nn.functional.relu(self.layer_1(x))
x = torch.nn.functional.sigmoid(self.layer_2(x))
x = torch.nn.functional.sigmoid(self.layer_3(x))
return x
# konfigurace vrstev neuronové sítě
input_dim = 2
hidden_dim = 10
output_dim = 1
# konstrukce neuronové sítě
nn9 = NeuralNetwork(input_dim, hidden_dim, output_dim)
# výpis základních informací o neuronové síti
print(nn9)
# příprava na trénink neuronové sítě
learning_rate = 0.1
loss_fn = nn.BCELoss()
optimizer = optim.SGD(nn9.parameters(), lr=learning_rate)
# trénovací data
from compute_train_and_test_data import compute_train_and_test_data
train_data, test_data = compute_train_and_test_data()
# zpracovat trénovací data
batch_size = 64
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
print("Batches: ", len(train_dataloader))
# vlastní trénink
print("Training started")
num_epochs = 200
loss_values = []
for epoch in range(num_epochs):
print(f" Epoch {epoch}: ", end="")
last_lost_value = None
for X, y in train_dataloader:
optimizer.zero_grad()
# dopředný tok + zpětný tok + optimalizace
pred = nn9(X)
# výpočet účelové funkce
loss = loss_fn(pred, y.unsqueeze(-1))
loss_values.append(loss.item())
loss.backward()
optimizer.step()
last_lost_value = loss.item()
print(".", end="")
print(last_lost_value)
print("Training completed")
test_dataloader = DataLoader(dataset=test_data, batch_size=batch_size, shuffle=True)
import itertools
all_predicts = []
x_coords = []
y_coords = []
with torch.no_grad():
for X, y in test_dataloader:
outputs = nn9(X)
predicted = np.where(outputs.numpy() < 0.5, 0, 1)
predicted = list(itertools.chain(*predicted))
all_predicts += predicted
coords = X.tolist()
for coord in coords:
x_coords.append(coord[0])
y_coords.append(coord[1])
# velikost obrázku s grafem
plt.subplots(figsize=(6.4, 6.4))
# vizualizace
plt.scatter(x_coords, y_coords, s=1.5, c=all_predicts, cmap=plt.cm.Set1)
# popisek grafu
plt.title("Predikované výsledky")
# uložení grafu do souboru
plt.savefig("nn_9.png")
# vykreslení na obrazovku
plt.show()
18. Výsledky získané devátým demonstračním příkladem
Okomentované výsledky získané devátým demonstračním příkladem pro různě nastavené neuronové sítě:
Obrázek 11: Korektně naučená síť – každý bod je ohodnocen správně.
Obrázek 12: Nekorektně naučená síť – největší chyby vidíme ve spodní části grafu.
Obrázek 13: Korektně naučená síť – každý bod je ohodnocen správně (větší množství testovacích dat).
Obrázek 14: Nekorektně naučená síť; tentokrát je problematický první kvadrant.
Obrázek 15: Korektně naučená síť v případě, že se mezikruží dotýkají.
19. Repositář s demonstračními příklady
Všechny demonstrační příklady využívající knihovnu PyTorch lze nalézt v repositáři https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady:
20. Odkazy na Internetu
- Seriál Programovací jazyk Lua na Rootu:
https://www.root.cz/serialy/programovaci-jazyk-lua/ - PDM: moderní správce balíčků a virtuálních prostředí Pythonu:
https://www.root.cz/clanky/pdm-moderni-spravce-balicku-a-virtualnich-prostredi-pythonu/ - PyTorch Tutorial: Building a Simple Neural Network From Scratch
https://www.datacamp.com/tutorial/pytorch-tutorial-building-a-simple-neural-network-from-scratch - Interní reprezentace numerických hodnot: od skutečného počítačového pravěku po IEEE 754–2008:
https://www.root.cz/clanky/interni-reprezentace-numerickych-hodnot-od-skutecneho-pocitacoveho-praveku-po-ieee-754–2008/ - Interní reprezentace numerických hodnot: od skutečného počítačového pravěku po IEEE 754–2008 (dokončení):
https://www.root.cz/clanky/interni-reprezentace-numerickych-hodnot-od-skutecneho-pocitacoveho-praveku-po-ieee-754–2008-dokonceni/ - Brain Floating Point – nový formát uložení čísel pro strojové učení a chytrá čidla:
https://www.root.cz/clanky/brain-floating-point-ndash-novy-format-ulozeni-cisel-pro-strojove-uceni-a-chytra-cidla/ - Stránky projektu PyTorch:
https://pytorch.org/ - Informace o instalaci PyTorche:
https://pytorch.org/get-started/locally/ - Tenzor (Wikipedia):
https://cs.wikipedia.org/wiki/Tenzor - Introduction to Tensors:
https://www.youtube.com/watch?v=uaQeXi4E7gA - Introduction to Tensors: Transformation Rules:
https://www.youtube.com/watch?v=j6DazQDbEhQ - Tensor Attributes:
https://pytorch.org/docs/stable/tensor_attributes.html - Tensors Explained Intuitively: Covariant, Contravariant, Rank :
https://www.youtube.com/watch?v=CliW7kSxxWU - What is the relationship between PyTorch and Torch?:
https://stackoverflow.com/questions/44371560/what-is-the-relationship-between-pytorch-and-torch - What is a tensor anyway?? (from a mathematician):
https://www.youtube.com/watch?v=K7f2pCQ3p3U - Visualization of tensors – part 1 :
https://www.youtube.com/watch?v=YxXyN2ifK8A - Visualization of tensors – part 2A:
https://www.youtube.com/watch?v=A95jdIuUUW0 - Visualization of tensors – part 2B:
https://www.youtube.com/watch?v=A95jdIuUUW0 - What the HECK is a Tensor?!?:
https://www.youtube.com/watch?v=bpG3gqDM80w - Stránka projektu Torch
http://torch.ch/ - 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 - An Introduction to Tensors
https://math.stackexchange.com/questions/10282/an-introduction-to-tensors - Differences between a matrix and a tensor
https://math.stackexchange.com/questions/412423/differences-between-a-matrix-and-a-tensor - Qualitatively, what is the difference between a matrix and a tensor?
https://math.stackexchange.com/questions/1444412/qualitatively-what-is-the-difference-between-a-matrix-and-a-tensor? - Tensors for Neural Networks, Clearly Explained!!!:
https://www.youtube.com/watch?v=L35fFDpwIM4 - Tensor Processing Unit:
https://en.wikipedia.org/wiki/Tensor_Processing_Unit - Třída Storage:
http://docs.pytorch.wiki/en/storage.html - Funkce torch.dot
https://pytorch.org/docs/stable/generated/torch.dot.html#torch.dot - Funkce torch.narrow
https://pytorch.org/docs/stable/generated/torch.narrow.html - Funkce torch.matmul
https://pytorch.org/docs/stable/generated/torch.matmul.html - Funkce torch.reshape
https://pytorch.org/docs/stable/generated/torch.reshape.html - Funkce torch.arange
https://pytorch.org/docs/stable/generated/torch.arange.html - Funkce torch.range
https://pytorch.org/docs/stable/generated/torch.range.html - Třída torch.Tensor
https://pytorch.org/docs/stable/tensors.html - Atributy tenzorů
https://pytorch.org/docs/stable/tensor_attributes.html - Pohledy vytvořené nad tenzory
https://pytorch.org/docs/stable/tensor_view.html - Broadcasting v knihovně
https://numpy.org/doc/stable/user/basics.broadcasting.html - Broadcasting semantics (v knihovně PyTorch)
https://pytorch.org/docs/stable/notes/broadcasting.html - Dot Product In Physics: What Is The Physical Meaning of It?
https://profoundphysics.com/dot-product-in-physics-what-is-the-physical-meaning-of-it/ - 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/ - Data pro neuronové sítě
http://archive.ics.uci.edu/ml/index.php - 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 - 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/