A Hosszú Munkamemóriájú Neurális Hálózat

Nem olyan régen szó volt a Mesterséges Neurális Hálózatok egy sorozatokra kifejlesztett változatáról, az Ismétlődő Neurális Hálózatról. Amint említettük, ez a típus hatványozottan szenved az Eltűnő Gradiens Problémától. Ennek a nehézségnek a megoldására született meg a “Hosszú Munkamemóriájú” (HMM, angolul: Long short-term memory) Neurális Hálózat. Mai bejegyzésünkben ezt megvizsgáljuk meg.


A HMM mai formája 1997 és 2000 között született meg Sepp Hochreiter, Jürgen Schmidhuber és Felix Gers munkája során. Érdemes megemlíteni, hogy Hochreiter volt az aki először definiálta az Eltűnő Gradiens Problémát.1

A 2010-es évek végére az HMM igazi sikersztori lett. Sajnos csak 2016-os adatokat találtam, de ezek szerint 3 évvel ezelőtt olyan jól ismert és használt alkalmazásokban használták, mint a Google Translate, az iPhone „Quicktype” funkciója, a Siri vagy az Amazon Alexa.

A HMM szoros rokonságban áll az Ismétlődő Neurális Hálózattal, sokszor annak egy altípusának tekintik. Itt is egyesével dolgozzuk fel a megfigyeléseket:2

Ami eltérő: az a hálózat felépítése; a zöld dobozok sora. Ez nem egy egyszerű Feed Forward Hálózat, hanem egy sokkal összetettebb rendszer:

Amint látható, az egy tanh aktivációs függvény helyett itt két tanh és három sigmoid függvényünk is van. A rendszert négy részre oszthatjuk:

Nézzük mit is csinálnak ezek a részek részletesebben.

Cella állapot

In medias res, kezdjük a cella állapottal! Ez a rész kicsit olyan, mint egy futószalag, ami az információt kis módosítással szállítja az egyik megfigyeléstől a másik felé. Szerintem ez a legérdekesebb része a koncepciónak. Vegyük észre, hogy itt úgy tudunk információt továbbítani a különféle megfigyelések között, hogy azokat nem küldjük többszörösen át az aktivációs függvényen. Ez az, aminek a segítségével a HMM megoldja az Eltűnő Gradiens Problémát. A Felejtés kapuja és a Bemeneti kapuk arra szolgálnak, hogy az adatokat helyezzenek fel vagy vegyenek le erről a futószalagról:

Valamelyest előreszaladva a cella állapot végső értékét így számoljuk:

(1)   C_t = f_t  \circ  C_{t-1} + i_t  \circ \tilde{C}_t

Ahol:

  • C_t  — az új cella állapot
  • f_t — a felejtés kapujának kimenete, lsd. Felejtés kapuja
  • C_{t-1} — a korábbi cella állapot
  • i_t — a bemeneti kapu eredménye, lsd. Bemeneti kapu
  • \tilde{C}_t — a tangh aktivációs függvény eredménye, lsd: Bemeneti kapu
  • \circ — a Hadamard-szorzat jele

Felejtés kapuja

Ennek a misztikusan hangzó nevű résznek a dolga eldönteni, hogy korábbi cella állapotok közül mennyi információt őrzünk meg, illetve felejtünk el. Mivel ez egy sigmoid függvény, a kimeneti értéke 0 és 1 között van, azaz minél kisebb a kimenet annál kevésbé fogjuk a későbbiekben figyelembe venni az adott információt:

A számítása ennek megfelelőn:

(2)   f_t = \sigma(W_f\cdot[h_{t-1},x_t]+b_f)

Ahol:

  • f_t — a felejtés kapujának eredménye
  • W_f — a felejtés kapujának súlyai
  • h_{t-1} — a korábbi rejtett állapot
  • x_t — a jelenlegi megfigyelés
  • b_f — a felejtés kapujának eltolása

Bemeneti kapu

Ez a kapu annak eldöntésére szolgál, hogy menyi információt őrizzünk meg a jelenlegi megfigyelésből. A sigmoid eldönti: mi fontos, mi nem, míg a tanh kiszámítja a cella állapot frissítésének értékét:

A fentieknek megfelelően a bementi kapu eredményének számítása:

(3)   i_t = \sigma(W_i\cdot[h_{t-1},x_t]+b_i)

Ahol:

  • i_t  — a bementi kapu eredménye
  • W_i — a bemeneti kapu súlyai
  • b_i — a bemeneti kapu eltolása

Az aktivációs függvény pedig a szokásos:

(4)   \tilde{C}_t = \text{tanh}(W_c\cdot[h_{t-1},x_t]+b_c)

Ahol:

  • \tilde{C}_t — a javasolt állapot a C_t-re
  • W_c — az aktivációs függvény súlyai
  • b_c — az aktivációs függvény eltolása

Kimenti kapu

Ez a réteg dönti el, hogy a következő megfigyelés esetén mi legyen a Rejtett állapot. Ezt az állapotot használjuk előrejelzésre is.

A kimeneti kapu eredményének számítása:

(5)   o_t = \sigma(W_o\cdot[h_{t-1},x_t]+b_o)

Ahol:

  • o_t  — a kimeneti kapu eredménye
  • W_o — a kimeneti kapu súlyai
  • b_o — a kimeneti kapu eltolása

Végül pedig a végső Rejtett állapot:

(6)   h_t = o_t \circ \text{tanh}(C_t)

Naiv Python Lejátszás

Végezetül nézzünk meg egy egyszerű Python implementációt a HMM lejátszás szakaszára:

import numpy as np
# kezdeti sulyok
wf = np.array([0,0])
bf = -100
wi=np.array([0,100])
bi = 100
wo=np.array([0,100])
bo = 0
wc = np.array([-100,50])
bc = 0
# sigmoid függvény
def sigmoid(x):
    return 1/(1+np.exp(-x))
# LSTM cella
#   attr:
#       x -- igazából [ h_{t-1}, x]
def lstmcell(x, ct):
    # felejtés kapuja
    ft = sigmoid(np.dot(wf, x)+bf)
    # bemeneti kapu
    it = sigmoid(np.dot(wi, x)+bi)
    # kimeneti kapu
    ot = sigmoid(np.dot(wo, x)+bo)
    # cella állapot
    ct = ft*ct+it * np.tanh(np.dot(wc, x)+bc)
    # rejtett állapot
    ht = ot*np.tanh(ct)
    return ht, ct
# megfigyelések
xs = np.array([0, 0, 1, 1, 1, 0])
# kezdeti rejtett állapot
htx = [0]
# kezdeti cella állapot
ctx = np.array([0])
# eredmény
result = []
# végiglépkedünk a megfigyeléseken
for i in xs:
    htx.append(i)
    htx, ctx =  lstmcell(np.array(htx), ctx)
    htx = htx.tolist()
    htx[0] = htx[0]
    result.append(htx[0])
# eredmény
print(result)

Végszó

A fentiekben megnéztük, hogyan működik egy tipikus HMM, de mint mindennek a Mesterséges Neurális Hálózatok területén, ennek is több változata alakult ki. A konkrét könyvtárak alkalmazása során érdemes átolvasni a dokumentációt, hogy lássuk, mennyiben tipikus az adott megvalósítás.

Lábjegyzet

  1. S. Hochreiter: Untersuchungen zu dynamischen neuronalen Netzen. Diploma thesis, Institut f. Informatik, Technische Univ. Munich, 1991.
  2. Mint a Ismétlődő Neurális Hálózat esetén ebben a bejegyzésben is Michael Nguyen Illustrated Guide to LSTM’s and GRU’s munkájának ábráit használom.

Irodalom

Hírdetés

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés /  Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés /  Módosítás )

Kapcsolódás: %s