Előző, nyelvi modellekről szóló posztomban a helyesírás-ellenőrző, az internetes kereső és a gépi fordítás közös pontjait kezdtem el keresni, és egy python kódot is közzétettem. Most a kód kommentálása következik, és egy XVIII. századi angol matematikus is felbukkan.
Nem túl elegáns és lassú programunk előállította az ÖSSZES adott szóval kezdődő mondatot egy 8 megabájtos korpusz alapján, majd azokat “valószínűség” alapján sorba állítja. Tehát, a végén ki tudjuk választani a legvalószínűbb mondatot, esetleg a legvalószínűbb tízet, húszat, százat... Rendben, a mondat kifejezés is túlzás, beszéljünk inkább N szóból álló szófüzérről – a programnak ugyanis fogalma sincs a szintaxisról – ennek ellenére időnként mégis értelmesnek tünű mondatokat kapunk.
Minek köszönhető ez, miért kapunk valamennyire is használható szövegeket? Világos, hogy ha találomra dobálnánk egymás után a szavakat, az nem vezetne sehova. Ezért azt érdemes csinálni, hogy összefüggő darabokra vagdaljuk fel a korpuszunk szövegét, azután ezeket a darabokat úgy helyezzük egymáshoz, hogy illeszkedjenek – mint egy puzzle. Ha például bigramokat használunk, akkor az első bigram második eleme megegyező kell legyen a második bigram első elemével, a második bigram második eleme megegyező kell legyen a harmadik bigram első elemével és így tovább... A bigram-model azonban nem ad jó eredményeket (egy két elemű kombináció is túl kicsi), ezért trigramokat (3-gramokat, háromelemű darabokat használunk), és két első/utolsó elem alapján illesztünk. A trigram-model már jó, de nagyságrendekkel nagyobb korpuszt igényel (exponenciális növekedés!)
A programunk magja a general nevű függvény – ez előállítja a kiinduló két szóval kezdődő összes elképzelhető kombinációt. A trg tömbben kapja meg azokat a trigramokat, amelyekből majd dolgozni fog. A mondatok tömb fogja tárolni majd a kész mondatokat, ezekkel is tér vissza a függvény. Az első while ciklus annyiszor fog végigfutni, amilyen hosszú mondatokat szeretnénk (ez a szamlalo változó). Semmi mást nem csinál, csak kiválasztja az aktuális mondat végére illeszkedő újabb trigramot és odailleszti, vagyis: meghosszabítja egy szóval. Így hát olyan hosszú lesz a mondatunk, ahányszor ez a ciklus végigfut. A második for ciklus a következőért felel: mivel egy adott mondat végére több elem illeszkedik, minden egyes bővítéskor egyre több mondatunk lesz – mint egy szétágazó fa. Ezeket a változatokat is mind a mondatok tömbben tároljuk; a for ciklus minden egyes elemen végigfuttatja az aktuális bővítést. A bővítés úgy történik, hogy kikeressük a trigramjaink közül (trg) az illeszkedő elemeket (a jotrigrammok tömb), ezeket hozzáillesztjük az aktuális mondatunkhoz és visszaírjuk a mondat tömbbe. És: nem felejtjük el a törölni a régi, kiinduló mondatot, hiszen az még csak egy csonk, a végén arra már nem lesz szükségünk.
Minek köszönhető ez, miért kapunk valamennyire is használható szövegeket? Világos, hogy ha találomra dobálnánk egymás után a szavakat, az nem vezetne sehova. Ezért azt érdemes csinálni, hogy összefüggő darabokra vagdaljuk fel a korpuszunk szövegét, azután ezeket a darabokat úgy helyezzük egymáshoz, hogy illeszkedjenek – mint egy puzzle. Ha például bigramokat használunk, akkor az első bigram második eleme megegyező kell legyen a második bigram első elemével, a második bigram második eleme megegyező kell legyen a harmadik bigram első elemével és így tovább... A bigram-model azonban nem ad jó eredményeket (egy két elemű kombináció is túl kicsi), ezért trigramokat (3-gramokat, háromelemű darabokat használunk), és két első/utolsó elem alapján illesztünk. A trigram-model már jó, de nagyságrendekkel nagyobb korpuszt igényel (exponenciális növekedés!)
A programunk magja a general nevű függvény – ez előállítja a kiinduló két szóval kezdődő összes elképzelhető kombinációt. A trg tömbben kapja meg azokat a trigramokat, amelyekből majd dolgozni fog. A mondatok tömb fogja tárolni majd a kész mondatokat, ezekkel is tér vissza a függvény. Az első while ciklus annyiszor fog végigfutni, amilyen hosszú mondatokat szeretnénk (ez a szamlalo változó). Semmi mást nem csinál, csak kiválasztja az aktuális mondat végére illeszkedő újabb trigramot és odailleszti, vagyis: meghosszabítja egy szóval. Így hát olyan hosszú lesz a mondatunk, ahányszor ez a ciklus végigfut. A második for ciklus a következőért felel: mivel egy adott mondat végére több elem illeszkedik, minden egyes bővítéskor egyre több mondatunk lesz – mint egy szétágazó fa. Ezeket a változatokat is mind a mondatok tömbben tároljuk; a for ciklus minden egyes elemen végigfuttatja az aktuális bővítést. A bővítés úgy történik, hogy kikeressük a trigramjaink közül (trg) az illeszkedő elemeket (a jotrigrammok tömb), ezeket hozzáillesztjük az aktuális mondatunkhoz és visszaírjuk a mondat tömbbe. És: nem felejtjük el a törölni a régi, kiinduló mondatot, hiszen az még csak egy csonk, a végén arra már nem lesz szükségünk.
A program másik érdemi része az eredményeket értékeli. A mondatok tömb már tartalmazza az összes lehetséges mondatot, azonban össze-vissza. Ezért minden mondathoz számolunk egy értéket, az alapján, hogy a mondat trigramjai egyenként menyire gyakran fordulnak elő. Ezeket a számokat a program elején számoltuk ki a train nevű függvénnyel és a model nevű tömbben tároljuk (egyszerűen megszámoljuk, hányszor fordul elő minden egyes trigram). Így a legmagasabb értéket az a mondat kapja, amelyik a korpusz leggyakoribb elemeiből épül fel (az értékeket összeszorozzuk, így gyakorlatilag az esemény valószínűségét kapjuk, az összes elemek számával csupán azért nem osztunk, mert az úgyis mindig ugyanannyi, és nem akarunk törteket). Végül, az eredmenyek tömböt rendezzük az értékek szerint. Ezzel meg is vannak a kiírásra kész adataink. A program többi része valójában csak gyorsítás (pl. a trigramoknál szavak helyett számokat használunk a gyorsabb futás érdekében). A teljes kód az előző posztban olvasható.
* * *
OK, de mire jó mégis ez az egész..?
A nyelvfeldolgozás számomra egyik legizgalmasabb és legtitokzatosabb területe a statisztikai gépi fordítás. Sajnálatos módon egyelőre akadályokba ütközik olyan fordító-algoritmus írása, amelyik tökéletes fordítást készít (kétséges, lehetséges-e ilyet készíteni). Könnyebb olyat írni, amelyik többé-kevésbé jó fordításokat készít.
És egyáltalán, biztos, hogy egy szövegnek csak egyetlen jó fordítása létezik? Valószínűleg nem, inkább csak jobb és rosszabb fordítások. Ezért a fordítás problémája megfogalmazható, mint egy feltételes valószínűség: egy adott EN szöveg minden HU fordításához tartozik egy P(HU | EN) valószínűség – ez a szám annál nagyobb, minél “jobb a fordítás”.
De ki dönti el, hogy mennyire jó a fordításunk? A lektor, persze, de minden fordítóalgoritmus mellé lektort ültetni talán túlzás lenne. Ugyanebbe a problémába szalad bele Peter Norwig is a helyesírás-ellenőrzőjével, amikor el kell döntenie, a sok kínálkozó lehetőség közül melyik “helyeset” válasza. Ő a következőt javasolja:
P(helyes | elgépelt) = P(helyes) x P(elgépelt | helyes)
És ugyanez érvényes a fordításra is:
P( HU | EN) = P(HU) x P(EN | HU)
Arról van szó, hogy a számos lehetséges magyar változat közül azt érdemes kiválasztani, amelyik a legvalószínűbb! Ha már egyszer nem tudunk tökéletes fordítóalgoritmust készíteni, csinálhatjuk azt is, hogy generálunk sok tökéletlen fordítást, majd azt választjuk ki, amelyik a legvalószínűbb, hogy előfordul a természetes nyelvben.
A fent bemutatott n-gram modell is jó arra, hogy meghatározzuk: melyik fordítás a legrealisztikusabb. A legrealisztikusabbnak ugyanis az fog ítéltetni, amelyikben a leggyakoribb szavak, szófordulatok, mondatdarabok, vagyis n-gramok fordulnak elő. Így ha van egy jó nagy és jó minőségű korpuszunk, meg tudjuk mondani egy adott fordításról, mennyire valószínű, mennyire “hangzik jól”.
A fordítási problémát tehát két egyszerűbb problémára lehet bontani: A fordítás realisztikusságát ellenőrző nyelvi modellre (ezt jelöli a P(HU) ) és a sok “nem teljesen jó” fordításért felelős P(EN | HU) részre, aminek a neve fordítási modell. Róla majd egy későbbi posztban lesz szó.
Végül, a bevezetőben beharangozott angol matematikus. Arról van szó, hogy ez a formula nem Peter Norwig találmánya, hanem a XVIII. századi Thomas Bayes angol matematikusé. Gyakorlatilag nem más, mint a Bayes-tétel: ez a feltételes valószínűség és annak fordítottja közti összefüggést adja meg.
OK, de mire jó mégis ez az egész..?
A nyelvfeldolgozás számomra egyik legizgalmasabb és legtitokzatosabb területe a statisztikai gépi fordítás. Sajnálatos módon egyelőre akadályokba ütközik olyan fordító-algoritmus írása, amelyik tökéletes fordítást készít (kétséges, lehetséges-e ilyet készíteni). Könnyebb olyat írni, amelyik többé-kevésbé jó fordításokat készít.
És egyáltalán, biztos, hogy egy szövegnek csak egyetlen jó fordítása létezik? Valószínűleg nem, inkább csak jobb és rosszabb fordítások. Ezért a fordítás problémája megfogalmazható, mint egy feltételes valószínűség: egy adott EN szöveg minden HU fordításához tartozik egy P(HU | EN) valószínűség – ez a szám annál nagyobb, minél “jobb a fordítás”.
De ki dönti el, hogy mennyire jó a fordításunk? A lektor, persze, de minden fordítóalgoritmus mellé lektort ültetni talán túlzás lenne. Ugyanebbe a problémába szalad bele Peter Norwig is a helyesírás-ellenőrzőjével, amikor el kell döntenie, a sok kínálkozó lehetőség közül melyik “helyeset” válasza. Ő a következőt javasolja:
P(helyes | elgépelt) = P(helyes) x P(elgépelt | helyes)
És ugyanez érvényes a fordításra is:
P( HU | EN) = P(HU) x P(EN | HU)
Arról van szó, hogy a számos lehetséges magyar változat közül azt érdemes kiválasztani, amelyik a legvalószínűbb! Ha már egyszer nem tudunk tökéletes fordítóalgoritmust készíteni, csinálhatjuk azt is, hogy generálunk sok tökéletlen fordítást, majd azt választjuk ki, amelyik a legvalószínűbb, hogy előfordul a természetes nyelvben.
A fent bemutatott n-gram modell is jó arra, hogy meghatározzuk: melyik fordítás a legrealisztikusabb. A legrealisztikusabbnak ugyanis az fog ítéltetni, amelyikben a leggyakoribb szavak, szófordulatok, mondatdarabok, vagyis n-gramok fordulnak elő. Így ha van egy jó nagy és jó minőségű korpuszunk, meg tudjuk mondani egy adott fordításról, mennyire valószínű, mennyire “hangzik jól”.
A fordítási problémát tehát két egyszerűbb problémára lehet bontani: A fordítás realisztikusságát ellenőrző nyelvi modellre (ezt jelöli a P(HU) ) és a sok “nem teljesen jó” fordításért felelős P(EN | HU) részre, aminek a neve fordítási modell. Róla majd egy későbbi posztban lesz szó.
Végül, a bevezetőben beharangozott angol matematikus. Arról van szó, hogy ez a formula nem Peter Norwig találmánya, hanem a XVIII. századi Thomas Bayes angol matematikusé. Gyakorlatilag nem más, mint a Bayes-tétel: ez a feltételes valószínűség és annak fordítottja közti összefüggést adja meg.
Részletek legközelebb.
Nincsenek megjegyzések:
Megjegyzés küldése