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.
Embedding és összegzés
- A szóvektorok összegzése vagy átlagolása eldobja a sorrendet
- A "kutya harapta meg a postást" és a "postás harapta meg a kutyát" ugyanaz a zsák
- Osztályozásra jó, generálásra és kérdés-válaszra nem
Rekurrens háló
- Tokenenként dolgozza fel a szöveget
- Az állapot lépésről lépésre viszi tovább, hogy mi történt korábban
- Sorrendfüggő feladatokra is alkalmas
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.
- Felejtő kapuEldönti, hogy a memóriaállapot mely részét kell elfelejteni, és mi megy tovább.
- Bemeneti kapuAz aktuális tokenből érkező új információt illeszti be a memóriaállapotba.
- Kimeneti kapuA frissített állapotból kiválasztja, mi megy tovább rejtett vektorként a következő lépésbe.
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.
Egyirányú RNN
- Elejétől a végéig olvassa a szöveget, ahogy egy ember
- Egy rejtett állapotvektor
- Élő, folyamatosan érkező adatnál ez az egyetlen lehetőség
Kétirányú RNN
- Előre és visszafelé is végigfut a szekvencián
- Két állapotvektor, a végén összefűzve
- Akkor használható, ha a teljes szöveg előre rendelkezésre áll
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.
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 →