Bevezetés a neurális hálózatok világába 4. rész

Miért használjunk NumPy-t?

Az előző részekben tiszta Python kóddal építettünk mesterséges neuront és egy egyszerű réteget. Láttuk, hogy a logika nem bonyolult: súlyozott összeadás, eltolás hozzáadása, majd esetleg aktivációs függvény alkalmazása.  
De ahogy nő a hálózat mérete – több réteg, több száz vagy ezer neuron –, a tiszta Python megoldás:  

  • lassú lesz,  
  • áttekinthetetlenné válik,  
  • és rengeteg hibalehetőséget hordoz.  

Ezért használjuk a NumPy könyvtárat, amely:  

  • nagyon gyors (C nyelven írták),  
  • megbízható (alaposan tesztelt),  
  • és egyszerűvé teszi a vektorokkal, mátrixokkal végzett műveleteket.  

Vektorok, tömbök, mátrixok és tenzorok

Mielőtt konkrét példákon keresztül megnéznénk a NumPy használatát, fontos tisztázni néhány fogalmat.

Kezdjük a legegyszerűbb Python adattárolóval, a listával. A Python lista vesszővel elválasztott számokat tartalmaz szögletes zárójelek között. A korábbi részekben a tiszta Python megoldásainkban listákat használtunk az adatok tárolására.

Példa egy listára:

list = [1, 5, 6, 2]

Listák listája:

list_of_lists = [[1, 5, 6, 2],
				         [3, 2, 1, 3]]

Listák listáinak listája:

list_of_lists_of_lists = [[[1, 5, 6, 2],
                           [3, 2, 1, 3]],
                          [[5, 2, 1, 2],
                           [6, 4, 8, 4]],
                          [[2, 8, 5, 3],
                           [1, 1, 9, 4]]]

A fenti példák mindegyike nevezhető tömbnek is. Azonban nem minden lista lehet tömb.

Például:

 [[1, 2, 3],
   [4, 5],
   [6, 7, 8, 9]]

Ez a lista nem lehet tömb, mert nem „homológ”. Egy „listák listája” akkor homológ, ha minden sor pontosan ugyanannyi adatot tartalmaz és ez igaz valamennyi dimenzióra. A fenti példa nem homológ, mert az első lista 3 elemből, a második 2-ből, a harmadik pedig 4-ből.

A mátrix definíciója egyszerű: ez egy kétdimenziós tömb. Vannak sorai és oszlopai. Tehát egy mátrix lehet egy tömb. Vajon minden tömb lehet mátrix? Nem. Egy tömb sokkal több lehet, mint sorok és oszlopok. Lehet 3, 5 vagy akár 20 dimenziós is.

Végül mi az a tenzor? A tenzorok és a tömbök pontos definíciójáról oldalak százain keresztül vitáznak szakemberek. Ezt a vitát nagyrészt az okozza, hogy a résztvevők teljesen eltérő területek felől közelítik meg a témát. Ha a mélytanulás és a neurális hálózatok felől akarjuk megközelíteni a tenzor fogalmát, akkor talán a legpontosabb leírás: „A tenzorobjektum olyan objektum, amely tömbként ábrázolható.”

Összefoglalva: A lineáris, vagy 1-dimenziós tömb a legegyszerűbb tömb, Pythonban ennek a lista felel meg. A tömbök többdimenziós adatokat is tartalmazhatnak, ennek legismertebb példája a mátrix, amely egy 2-dimenziós tömb.

Még egy fogalmat fontos tisztázni, ez a vektor. Egyszerűen fogalmazva a matematikában használt vektor megegyezik a Python listával, vagy az 1-dimenziós tömbbel.

Két fontos művelet: dot product és vektorösszeadás

A dot product művelet elvégzésekor két vektort szorzunk össze. Ezt úgy tesszük, hogy sorra vesszük a vektorok elemeit és az azonos indexű elemeket összeszorozzuk, majd ezeket a szorzatokat összeadjuk. Matematikailag leírva ez így néz ki:

\vec{a}\cdot\vec{b} = \sum_{i=1}^n a_ib_i = a_1\cdot b_1+a_2\cdot b_2+...+a_n\cdot b_n

Fontos, hogy mindkét vektornak azonos méretűnek kell lennie. Ha Python kódban akarjuk ugyanezt leírni, akkor az így nézne ki:

# Első vektor
a = [1, 2, 3]

# Második vektor
b = [2, 3, 4]

# Dot product kiszámítása
dot_product = a[0]*b[0] + a[1]*b[1] + a[2]*b[2]

print(dot_product)

>>> 20

Látható, hogy ugyanazt a műveletet végeztük el, mint mikor egy neuron kimeneti értékét számoltuk ki, csak itt nem adtuk hozzá az eltolást. Mivel a Python nyelv alapesetben nem tartalmaz sem utasítást, sem funkciót a dot product kiszámolására, ezért használjuk a NumPy könyvtárat.

Vektorok összeadásánál az egyes vektorok azonos indexű elemeit adjuk össze. Matematikailag leírva ez így néz ki:

\vec{a}+\vec{b} = [a_1+b_1, a_2+b_2,...,a_n+b_n]

Itt is fontos, hogy a vektoroknak azonos méretűnek kell lennie. Az eredmény egy ugyanilyen méretű vektor lesz. A NumPy ezt a műveletet is könnyen kezeli.

NumPy használata

Egy neuron

Most kódoljuk le a korábban látott neuront NumPy használatával.

import numpy as np

# Bemenetek és súlyok
inputs = np.array([0.5, 0.8, 0.3, 0.1])

weights = np.array([0.2, 0.7, -0.5, 0.9])

bias = 0.5

# Neuron kimenete (dot product + bias)
output = np.dot(inputs, weights) + bias

print("Neuron kimenete:", output)

Itt a np.dot(inputs, weights) kiszámolja a skaláris szorzatot, majd egyszerűen hozzáadjuk a bias-t.  

Egy réteg

Most építsünk egy teljes réteget 3 neuronból, amelynek mindegyik neuron 4 bemenetet kap.  

import numpy as np

# Példa bemenet (4 elem)
inputs = np.array([1.0, 2.0, 3.0, 2.5])

# 3 neuron súlyai (mátrix: 3 sor, 4 oszlop)
weights = np.array([
                [0.2, 0.8, -0.5, 1.0],       # Neuron 1
                [0.5, -0.91, 0.26, -0.5],    # Neuron 2
                [-0.26, -0.27, 0.17, 0.87]   # Neuron 3
])

# Bias értékek (3 elem)
biases = np.array([2.0, 3.0, 0.5])

# Réteg kimenete (mátrix-szorzás + vektor összeadás)
output = np.dot(weights, inputs) + biases

print("Réteg kimenete:", output)

>>> Réteg kimenete: [4.8   1.21  2.385]

Itt a np.dot(weights, inputs) a mátrix (weights) és a vektor (inputs) szorzatát adja vissza, ami pont a neuronok súlyozott összege. Ehhez adjuk hozzá egyszerűen a bias vektort.  

Következő rész

A következő cikkben megismerkedünk az aktivációs függvényekkel, és megnézzük, hogyan adnak „nemlineáris erőt” a hálózatnak. Ezek nélkül a hálózatunk csak egyszerűen lineáris összefüggéseket tudna modellezni.  

hu_HU