AI kezdőknek · Természetes nyelvfeldolgozás · Lecke 16

Rekurrens neurális hálók

Az eddig tárgyalt embedding alapú modellek egy mondat szavainak jelentését összesítik, de a szavak sorrendjét figyelmen kívül hagyják. A rekurrens neurális háló ezt a hiányosságot oldja meg, mivel a szöveget szimbólumról szimbólumra dolgozza fel, és közben egy belső állapotban tartja számon, mi történt eddig a mondatban.

Vissza a tananyaghoz


Miért nem elég az egyszerű embedding

Ez a lecke a Microsoft nyílt forráskódú "AI kezdőknek" (AI For Beginners) tananyagának egyik leckéjének magyar adaptációja. A korábbi leckékben olyan modelleket építettünk, amelyek gazdag szemantikai reprezentációt adtak a szavaknak, majd egy egyszerű lineáris osztályozót helyeztünk az embeddingek fölé. Ez az architektúra a mondatban szereplő szavak összesített jelentését ragadja meg, de nem veszi figyelembe a szavak sorrendjét, mert az embeddingek összegzése vagy átlagolása pontosan ezt az információt dobja el az eredeti szövegből.

Ennek a következménye komoly. Ha a modell nem tudja megkülönböztetni, hogy egy mondatban mi történt korábban és mi később, akkor nem képes megoldani az összetettebb, sorrendfüggő feladatokat, mint amilyen a szöveg generálása vagy a kérdés-válasz típusú feladatok. Ehhez egy olyan architektúra kell, amely magát a sorrendet is modellezi.


A rekurrens háló alapötlete

A szövegszekvencia jelentésének megragadásához egy másik neurális háló architektúrát érdemes használni, ezt hívjuk rekurrens neurális hálónak, röviden RNN-nek. A módszer lényege, hogy a mondatot nem egyben, hanem szimbólumonként (jellemzően szavanként vagy tokenenként) adjuk át a hálózatnak. A háló minden egyes lépésben előállít egy úgynevezett állapotot, amelyet a következő szimbólummal együtt visszaad saját magának a következő lépésben.

Formálisan, ha a bemeneti tokenek sorozata X0, X1, egészen Xn-ig tart, az RNN egy hálózati blokkok sorozatát hozza létre, és ezt a sorozatot végponttól végpontig tanítja a visszaterjesztés módszerével. Minden blokk egy adott bemeneti token és az előző állapot párosát kapja bemenetként, és előállítja a következő állapotot. A végső állapot, vagy a hozzá tartozó kimenet kerül át egy lineáris osztályozóba, amely előállítja a végeredményt. Fontos, hogy minden blokk ugyanazokat a súlyokat használja, tehát valójában egyetlen, önmagára visszacsatolt hálózati egységről van szó, amit csak könnyebb elképzelni kiterített formában.

Mivel az egymást követő állapotvektorok mind áthaladnak a hálón, a modell képes megtanulni a szavak közötti szekvenciális összefüggéseket. Ha például a mondatban valahol megjelenik a "nem" tagadószó, a háló megtanulhatja, hogy ez az állapot bizonyos elemeit módosítsa, és ezzel a mondat jelentését a megfelelő irányba tolja el.


Egy RNN cella belseje

Egy egyszerű RNN cella két bemenetet fogad, az előző állapotot és az aktuális szimbólumot, és ezekből állítja elő a következő állapotot. Néhány feladatnál, például generatív hálóknál, egy külön kimenetre is szükség van az adott lépésben, nem csak az állapot továbbadására.

A cella belsejében két súlymátrix dolgozik. Az egyik a bemeneti szimbólumot alakítja át, a másik az érkező állapotot. A kettő összegéből, plusz egy bias tagból és egy aktivációs függvényből áll elő az új állapot. A gyakorlatban a bemeneti tokeneket gyakran előbb egy embedding rétegen vezetik át, hogy csökkentsék a dimenziószámot, mielőtt a rekurrens rétegbe kerülnének. Ez számítási szempontból hatékonyabbá teszi a hálót, mert a súlymátrixok mérete így az embedding méretétől és az állapotvektor méretétől függ, nem pedig a szókincs teljes méretétől.


Az eltűnő gradiens és az LSTM

A klasszikus RNN egyik legnagyobb problémája az úgynevezett eltűnő gradiens jelenség. Mivel a hálót egyetlen visszaterjesztési lépésben tanítjuk végponttól végpontig, a hiba egyre nehezebben jut vissza a szekvencia korábbi lépéseihez. Ennek eredményeként a modell nehezen tanul meg összefüggést két, egymástól távol álló token között, például egy mondat elején és végén szereplő szavak között.

Ennek a problémának a kezelésére terjedt el az explicit állapotkezelés elve, úgynevezett kapuk (gate-ek) segítségével. A két legismertebb ilyen architektúra a hosszú-rövid távú memória, közismertebb nevén LSTM, valamint a kapuzott rekurrens egység, azaz a GRU. Az LSTM hálózat alapfelépítése hasonló a klasszikus RNN-hez, de két állapotot ad tovább rétegről rétegre, egy tényleges memóriaállapotot és egy rejtett vektort. A rejtett vektor és az aktuális bemenet együtt szabályozza, hogy mi történik a memóriaállapottal a kapukon keresztül.

Az LSTM három fő kapuval dolgozik. A felejtő kapu eldönti, hogy a memóriaállapot mely részét kell elfelejteni, és melyiket kell tovább vinni. A bemeneti kapu az új információt illeszti be a memóriaállapotba. A kimeneti kapu pedig a frissített állapotból választja ki azt a részt, amely a következő rejtett vektorként továbbmegy. Mindegyik kapu tulajdonképpen egy szigmoid aktivációjú kis hálózat, amelynek kimenete 0 és 1 közé esik, így egyfajta bitmaszkként viselkedik, amikor megszorozzuk vele az állapotvektort.

A memóriaállapot komponensei úgy is felfoghatók, mint be- és kikapcsolható jelzők. Ha a szövegben megjelenik például egy "Éva" névmás, a háló bekapcsolhat egy jelzőt, amely azt jelzi, hogy a mondatban egy nőnemű főnévről van szó. Amikor később egy hasonló, mondjuk többes számú kifejezés következik, a háló ennek megfelelően állíthatja a nyelvtani jelzőket. Így az állapot manipulálásával a hálózat gyakorlatilag nyomon tudja követni a mondatrészek nyelvtani tulajdonságait, anélkül, hogy ezt explicit módon megtanítanánk neki.


Kétirányú és többrétegű hálók

Az eddig bemutatott rekurrens hálók egy irányban dolgozzák fel a szöveget, az elejétől a végéig, ahogy egy ember is olvas vagy hallgat egy szöveget. Sok gyakorlati feladatban azonban a teljes bemeneti szekvencia rendelkezésre áll már a feldolgozás kezdetekor, ezért érdemes lehet mindkét irányban futtatni a rekurrens számítást. Az ilyen hálókat kétirányú, vagyis bidirekcionális RNN-nek nevezzük. Ebben az esetben két rejtett állapotvektorra van szükség, egy-egy az adott irányhoz, amelyeket a végén jellemzően összefűznek. A kétirányú felépítés mellett a rekurrens hálókat egymásra is lehet rétegezni. Egy rekurrens réteg, akár egyirányú, akár kétirányú, bizonyos mintázatokat képes megragadni a szekvenciában, ezeket vagy egy állapotvektorba menti, vagy a kimenetre továbbítja. Hasonlóan a konvolúciós hálókhoz, egy második rekurrens réteget is felépíthetünk az első fölé, hogy magasabb szintű mintázatokat ismerjen fel az első réteg által kinyert alacsonyabb szintű jellemzőkből. Ez vezet el a többrétegű RNN fogalmához, amelyben két vagy több rekurrens réteg egymás után következik, és az előző réteg kimenete adja a következő réteg bemenetét.


Hol hasznosak a rekurrens hálók

A rekurrens hálók legegyszerűbb alkalmazása a szekvenciák osztályozása, például annak eldöntése, hogy egy szöveg pozitív vagy negatív hangvételű-e. Ezen túl azonban jóval szélesebb feladatkört is le tudnak fedni, amennyiben az architektúrát kiegészítjük egy generatív résszel. Ilyen feladat a szöveg generálása, a gépi fordítás, vagy a kérdés-válasz rendszerek. Ma már a gyakorlatban a legtöbb ilyen feladatra transzformer alapú architektúrákat használnak, de az RNN és az LSTM megértése azért fontos, mert ezek a fogalmak, az állapot fenntartása, a kapuk és a szekvenciális feldolgozás gondolata, alapját adják a modern szekvenciamodellezés megértésének.


Gyakorlati kód. Ha szeretnél saját kezűleg is kipróbálni egy RNN implementációt PyTorch-ban, nézd meg a Microsoft eredeti notebookját. RNNPyTorch.ipynb megnyitása GitHubon.


Forrás

Ez a lecke a Microsoft nyílt forráskódú, MIT licenc alatt elérhető "AI For Beginners" tananyagának magyar adaptációja. Eredeti angol lecke. GitHub. Felhasznált magyar gépi fordítás. GitHub.


← Előző lecke Következő lecke →

Workshop

AI Transformation Day

Egésznapos, vezetőknek szóló program. Feltérképezzük, hol tart a szervezet, mi az első reális lépés, és milyen belső feltételek szükségesek a sikerhez. A nap végén konkrét, prioritizált cselekvési lista.

Érdekel a program →