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.
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 →