3. diel - Neurónové siete - Krokovanie, bias a viac dimenzií
V minulej lekcii, Neurónové siete - Perceptron , sme spomenuli Perceptron a ukázali si niektoré druhy algoritmov vhodných na generovanie a triedenie dát.
V dnešnej lekcii kurzu Neurónovej siete - Krok za krokom si ukážeme krokovanie algoritmu, povieme si niečo o biase a lekciu zakončíme prípadom s 10-timi dimenziami.
Krokovanie algoritmu
Teraz, keď máme algoritmus, môžeme sa naň pozrieť bližšie. Pretože som vám sľúbil množstvo grafov, poďme si každú aktualizáciu vykresliť. Najprv vytvoríme dátovú sadu. Znížil som počet dátových bodov, aby bol príklad jasnejší:
data, classes = sklearn.datasets.make_blobs( n_samples=10, n_features=2, centers=[[-1,0.4],[1,0.6]], cluster_std=0.8, random_state=82 ) plt.scatter(data[:,0], data[:,1], c=classes) plt.show()

# Tréning perceptrónu # Inicializácia váh weights = np.random.RandomState(42).uniform(size=2) # Opakovanie až do konvergencie weights_changed = True while weights_changed: weights_changed = False # pre každú inštanciu v dátach for instance, target in zip(data, classes): # predikcia výstupu perceptrónu prediction = sign(instance @ weights) # aktualizácia váh weights_new = weights + (target - prediction) * instance # vykreslenie zmeny if (weights != weights_new).any(): slope = - weights[0] / weights[1] # vypočítanie sklonu plt.figure(figsize=(8, 5)) plt.plot( [data.min(axis=0)[0], data.max(0)[0]], [slope * data.min(axis=0)[0], slope * data.max(axis=0)[0]], c='r') # vykreslenie deliacej nardoviny plt.plot([0, weights[0]],[0, weights[1]], c='black') # vykreslenie normály plt.scatter(data[:,0], data[:,1], c=classes) # vykreslenie dát plt.scatter(instance[0], instance[1], c='g') # vykreslenie chybne klasifikovanej inštancie plt.plot([0, instance[0]], [0, instance[1]], c='g', alpha=0.4) # vykreslenie inštančného vektora plt.plot( [weights[0], weights[0] + (target - prediction) * instance[0]], [weights[1], weights[1] + (target - prediction) * instance[1]], c='g', alpha=0.4) # vykreslenie inštančného vektora z normály plt.plot( [0, weights[0] + (target - prediction) * instance[0]], [0, weights[1] + (target - prediction) * instance[1]], c='c', alpha=0.4) # vykreslenie novej normály slope_new = - weights_new[0] / weights_new[1] # výpočet sklonu novej priamky plt.plot( [data.min(axis=0)[0], data.max(0)[0]], [slope_new * data.min(axis=0)[0], slope_new * data.max(axis=0)[0]], c='r', alpha=0.2) # vykreslenie deliacej nadroviny plt.axis('equal') plt.ylim(-2,4) plt.show() weights_changed = weights_changed or (weights != weights_new).any() weights = weights_new # VYKRESLENIE KONEČNÝCH VÁH slope = - weights[0] / weights[1] plt.figure(figsize=(8, 5)) plt.scatter(data[:,0], data[:,1], c=classes) plt.plot( [data.min(axis=0)[0], data.max(0)[0]], [slope * data.min(axis=0)[0], slope * data.max(axis=0)[0]], c='r') plt.show()
Bias
Zatiaľ sme nepoužili bias. Ak si pamätáte všeobecné rovnice priamky ?? + ?? + ? = 0, nastavili sme ? na nulu. Z tohto dôvodu prechádza priamka vždy súradnicou [0, 0]. Ale čo ak máme dáta, ktoré nemožno takto oddeliť? Radi by sme zaviedli posun ? (anglicky bias) a umožnili algoritmu posunúť deliacu nadrovinu z nulovej súradnice. Najprv si vygenerujeme novú dátovú sadu:
data, classes = sklearn.datasets.make_blobs( n_features=2, centers=2, random_state=44 ) plt.scatter(data[:,0], data[:,1], c=classes) plt.show()

Bias sa učí rovnakým spôsobom ako váhy. Keď algoritmus nesprávne klasifikuje pozitívnu inštanciu, zvýši bias o 1. Keď je chybne klasifikovaná negatívna inštancia, zníži ho o 1:
# Tréning perceptrónu # Inicializácia váh weights = np.random.RandomState(42).uniform(-2, 2, 2) bias = 0 # Opakovanie až do konvergencie old_weights = None old_bias = None while (weights != old_weights).any() or bias != old_bias: old_weights = weights old_bias = bias # pre každú inštanciu v dátach for instance, target in zip(data, classes): # predikcia výstupu perceptrónu prediction = sign(instance @ weights + bias) # aktualizácia váh weights = weights + (target - prediction) * instance bias = bias + (target - prediction) # vykreslenie slope = - weights[0] / weights[1] plt.scatter(data[:,0], data[:,1], c=classes) plt.plot( [data.min(axis=0)[0], data.max(0)[0]], [slope * data.min(axis=0)[0] - bias / weights[1], slope * data.max(axis=0)[0] - bias / weights[1]], c='r') plt.show()

data = np.array([[1],[2],[3],[4],[5],[6]]) classes = np.array([0,0,0,1,1,1]) plt.scatter(data, np.zeros((6,)), c=classes) plt.scatter(0,0,c='r') plt.show()

data = np.array([[1],[2],[3],[4],[5],[6]]) classes = np.array([0,0,0,1,1,1]) plt.scatter(data, np.ones((6,)), c=classes) plt.scatter(0,0,c='r') plt.plot([0, 6],[0, 1.75], c='r') plt.show()

# GENEROVANIE DÁT data, classes = sklearn.datasets.make_blobs( n_features=2, centers=2, random_state=44 ) data = np.hstack([data, np.ones((data.shape[0],1))]) # Tréning perceptrónu # Inicializácia váh weights = np.random.RandomState(42).uniform(-2, 2, 3) # Opakovanie až do konvergencie old_weights = None while (weights != old_weights).any(): old_weights = weights # pre každú inštanciu v dátach for instance, target in zip(data, classes): # predikcia výstupu perceptrónu prediction = sign(instance @ weights) # aktualizácia váh weights = weights + (target - prediction) * instance # vykreslenie slope = - weights[0] / weights[1] bias = weights[2] / weights[1] plt.scatter(data[:,0], data[:,1], c=classes) plt.plot( [data.min(axis=0)[0], data.max(0)[0]], [slope * data.min(axis=0)[0] - bias, slope * data.max(axis=0)[0] - bias], c='r') plt.show()

Viacdimenzionálny prípad
Zatiaľ sme si ukázali iba dvojrozmerné prípady. Nie je nič, čo by bránilo použitiu viacerých dimenzionálnych dát, okrem toho, že ich nebudeme môcť vykresliť. Skúsme napríklad 10 dimenzií, ale bez vykresľovania, pretože vizualizáciu 10D dát by nebolo ľahké urobiť:
# GENEROVANIE DÁT data, classes = sklearn.datasets.make_blobs( n_samples=1000, n_features=10, centers=2, random_state=42 ) data = np.hstack([data, np.ones((data.shape[0],1))]) train_data, test_data, train_classes, test_classes = sklearn.model_selection.train_test_split(data, classes, test_size=0.15) # Tréning perceptrónu weights = np.random.RandomState(42).uniform(-2, 2, 11) old_weights = None while (weights != old_weights).any(): old_weights = weights for instance, target in zip(train_data, train_classes): prediction = sign(instance @ weights) weights = weights + (target - prediction) * instance # TEST predictions = [sign(instance @ weights) for instance in test_data] print(f'Presnosť: {sklearn.metrics.accuracy_score(test_classes, predictions)}')
Výstup
Presnosť: 1.0
Ako vidíme, algoritmus dosiahol 100% presnosť. Správne oddelil dáta, pretože sú lineárne separované.
V budúcej lekcii, Neurónové siete - Normalizácia , sa zameriame na normalizáciu alebo štandardizáciu dátových bodov.