English version of the post

Z deep learningu (hlubokého učení – strojového učení pomocí neuronových sítí) se v posledních letech stal buzzword technologického světa. Můžeme číst články, co dovede umělá inteligence (vyčpělé artificial intelligence se s oblibou nahrazuje pojmem machine intelligence) – jak dovede vyřešit automatický překlad, rozpoznávání řeči nebo běží na pozadí chytrých asistentů jako Google Home nebo Amazon Echo.

V tomto příspěvku bych rád přiblížil, jak to vypadá, když se rozhodneme deep learning nasadit na nějaký aspoň trochu reálný problém. Ukážeme si, jak se jednoduchým modelem naučit, kde se v češtině píše měkké a tvrdé ‘i’ a jak se při řešení takových úloh obvykle postupuje. Pro toho, kdo se nebojí číst zdrojové kódy, může posloužit i jako tutorial.

Jak se to vlastně píše

Na základní škole se učíme poměrně dost pravidel, podle kterých se psaní měkkého a tvrdého i řídí. Pravidla, které se používají jsou:

  • měkkost/tvrdost samohlásky (s tou zákeřností, že ta slova k tomu musíme aspoň trochu znát, abychom věděli, že správně je štěstí a ne štěstý),

  • znalost kořene slova (je potřeba si pamatovat vyjmenovaná slova),

  • znalost pádové koncovky (je potřeba umět pády a vzory, podle kterých se skloňuje),

  • shoda podmětu s přísudkem (k tomu musíme umět alespoň základním způsobem umět větný rozbor a poznat, co je podmět a co je přísudek),

  • vyznat se v tom, kdy pravidla kolidují (píšeme tácy, přestože c je měkká souhláska, protože skloňujeme podle vzoru hrad).

Abychom mohli taková pravidla naprogramovat, museli bychom umět nejdřív udělat automaticky větný rozbor včetně všech pádů, rodů a čísel, abychom mohli všechna pravidla použít. Pro představu, jak může větný rozbor fungovat, si můžete vyzkoušet například Treex.

Automatické větné analyzátory obvykle spoléhají na to, že věty jsou gramaticky správně a pokud nejsou, dělá chyby. Vzhledem k tomu, že chceme věty opravovat je to poměrně nepříjemná vlastnost. Z toho začarovaného kruhu si nakonec pomůžeme tak, že se bez gramatických pravidel obejdeme úplně a necháme vše naučit se z dat pomocí neuronové sítě.

Trénovací a testovací data

Za úspěchem jakéhokoli strojového učení stojí vždy dostatek trénovacích dat. V případě této úlohy můžeme trénovací data získat velmi snadno tak, že stáhneme z Internetu větší množství českého textu a budeme doufat, že je z většiny gramaticky správně. Jednoduše dá stáhnout najednou například celá česká Wikipedie v XML formátu.

Text z Wikipedie je ještě potřeba trochu upravit a pročistit. Text automaticky rozdělíme na věty (knihovna NLTK obsahuje i modely pro češtinu). Pro jednoduchost ještě nahradíme všechny znaky, které nejsou z české abecedy nějakým speciálním symbolem (třeba _) — Wikipedie obsahuje spoustu útržků textů v jiných abecedách. Pro větší jednoduchost ještě převedeme veškerý text převedeme na malá písmena.

Nyní už zbývá jenom změnit všechna i na měkká a zapamatovat si, kde se mají změnit na tvrdá. Výsledek může vypadat nějak takto:

Vstup:

aristotelés dále určil poloměr země, kterí ale odhadl na dvojnásobek...
v aristotelovském modelu země stojí a měsíc se sluncem a hvězdami krouží...
mišlenki aristotelovi rozvinul ve 2. století našeho letopočtu klaudios...

Výstup

00001000000000000000000000000000001000000100000000000000000000001000000100000...
02000002000100000000200000100000000000000001000000000000000000000001000000000...
00000000000000000010000000000001000002000000000000000000020000000000000000000...

V tomu výstupu jednička značí měkké ‘i’, dvojka značí ‘y’ a nula všechny ostatní znaky. Můžete si prohlédnout kód pro rozdělení textu na věty a přípravu dat. V době stahování bylo na české Wikipedie přibližně 5 milionů českých vět.

Když řešíme nějaký problém pomocí strojového učení — a je jedno jestli je to dnes tak populární hluboké učení nebo jiné metody — je potřeba striktně oddělovat trénovací a testovací data. Trénovací používáme k naučení modelu. Když nějaký model vyvíjíme, mělo by nás spíše zajímat, jak si povede, až uvidí nějaká data, která při trénování neviděl. To se obvykle řeší tak, že si necháme část dat stranou, model na nich netrénujeme a tato data používáme pouze k tomu, abychom porovnali, který model je lepší a který je horší. Pro naše další experimenty si odložíme stranou tisíc vět a ty budeme používat pro testování našich metod.

Jednoduchá řešení

Triviálním řešením by bylo všude nechat měkká i. Tímto přístupem se na našich testovacích dostaneme na krásných 76.4 %. V počítačové lingvistice (a umělé inteligenci obecně) se tomu obvykle říká stanovení baseline. Aby řešení nějaké úlohy bylo vůbec nějak zajímavé, je potřeba, aby bylo výrazně lepší, než nějaké triviální řešení.

Zkusíme se ještě na chvíli u těchto jednoduchých řešení zastavit. Můžeme například zkusit dávat tvrdé y po tvrdých souhláskách h, ch (tedy zase vlastně h), k a r. U hlásek d, t a n ale nemáme možnost jednoduše poznat, jestli se mají vyslovovat měkce a má za nimi následovat i nebo tvrdě.

Další pozorování, které můžeme udělat je, že pokud slovo začíná na vi/vy, většinou se jedná o předponu vy (Vikingové a lama vikuňa prominou).

  přesnost
všechna měkká 76.4 %
+ tvrdé souhlásky 77.5 %
+ předpona vy 80.0 %

S řešením, které se dá napsat na jeden řádek pomocí dvou regulárních výrazů, jsme se dostali na úspěšnost 80.0 %. Kdybychom se nad skupinami hlásek zamysleli důkladněji a pomohli bychom si důkladnější statistickou analýzou, zvládli bychom se dostat ještě o několik procent výše.

Místo toho se zastavíme u jiného velmi jednoduchého řešení. Z předchozí části víme, že máme k dispozici celou Wikipedii jako trénovací data. Můžeme si zkusit pro každé slovo zaznamenat, kolikrát se vyskytlo s jakým pravopisem. Později, při testování, použijeme pro každé slovo jeho nejčastější pravopis. Následující tabulka ukazuje, jaké přesnosti dosáhneme po zpracování určitého množství vět.

počet přečtených vět přesnost
500 77.9 %
5 000 85.3 %
50 000 88.6 %
500 000 90.4 %
5 000 000 90.8 %

Vidíme, že s rostoucím množstvím zpracovaného textu roste i úspěšnost modelu. Není to nic překvapivého. Čím více textu vidíme, tím menší pravděpodobnost je, že v něm uvidíme nějaká slova, která jsme ještě neviděli. Můžete si prohlédnou zdrojový kód.

Nyní už víme, co můžeme chtít od našeho modelu. Cokoli nad 91 % můžeme považovat za úspěch, jakýkoli horší výsledek bude znamenat, že se neuronová síť nenaučila si ani zapamatovat, jak se které slovo nejčastěji píše. Z těchto předběžných experimentů také víme, že aby náš model překonal 91 %, bude se muset naučit něco z větné skladby, aby byl schopen dodržovat shodu podmětu s přísudkem.

Model

Na naši úlohu použijeme rekurentní neuronovou síť. Rekurentní neuronová síť funguje tak, že pokaždé, když dostane nějaký vstup, provede update svého vnitřního stavu a vydá nějaký výstup. Schéma kousku sítě rozvinuté v čase vidíme na následujícím obrázku.

sequence-labeling

V našem případě čte rekurentní síť svůj vstup písmenko po písmenku. V každém kroku pak změní svůj uložený vnitřní stav a vydá nějaký výstup – s každým písmenkem provede tutéž operaci. To se může zdát na první pohled zvláštní, ale je to přesně to, co naší síti chceme. Každé písmeno má jinou naučenou reprezentaci, a když ji síť obdrží, rozhodne se, co udělá. Vnitřní stav rekurentní sítě je vlastně paměť, kde si ukládá relevantní informace o tom, co viděla v minulosti a co to znamená pro vstupy, které mají teprve přijít.

Síť se učí především reprezentovat vstupní písmena a už viděný text takovým způsobem, aby dokázala dobře plnit svůj úkol. Učení vhodné reprezentace se často zdůrazňuje jako jedna z nejdůležitějších vlastností hlubokého učení (ostatně z nejvýznamnějších věděckých konferencích v oboru se jmenuje International Conference on Represenation Learning). V trénovacích datech nejsou nijak vyznačené lingvistické koncepty, které nám pomáhají pravopis nějakým způsobem pojmově uchopit. Dokonce i mezery mezi slovy jsou znaky jako všechny ostatní. Je to prostě proud znaků a neuronová síť s ním musí nějakým způsobem poradit.

Síť ještě vylepšíme jednoduchým trikem. Použijeme nezávisle dvě rekurentní neuronové sítě. Jedna bude číst text odpředu a bude se snažit odhadnout pravopis podle toho, co bylo ve větě nalevo od posledního písmene, druhá síť bude používat to, co bylo napravo od něj.

Pokud vás zajímají detaily sítě (třeba počet neuronů), můžete si prohlédnout zdrojový kód modelu.

Trénování

Rekurentní síť vydává nějaký výstup po přečtení každého z písmen, ale nás zde zajímají jenom, kde je na vstupu i a máme rozhodnout, jestli je měkké nebo tvrdé. Výstupy na ostatních místech sítě můžeme ignorovat a zjednodušit si tím práci.

Na začátku trénování jsou váhy spojů mezi neurony v síti náhodné. V průběhu učení síť vždy přečte větu, provede svůj odhad a ten porovnáme s tím, co by měla síť vydat do opravdu a váhy sítě se drobně upraví tak, aby byly blíže tomu, co by síť měla skutečně vydat.

Pouze z této základní informace se neuronová síť postupně naučí reprezentovat vstupní věty tak, aby snadno mohla rozhodovat. Při trénování se nikdy výslovně neobjevuje pojem slova, souhlásky a samohlásky. Síti nikdo neříká: „Toto je podmět, protože je v prvním pádě,‟ nepracuje se slovesným rodem, s pády, čísly a skloňovacími vzory. Všechno to, k čemu jako lidé potřebují složitá explicitní pravidla, je schopna během trénování odvodit ze samotných dat.

Naše síť trénovaná na ne příliš výkonné grafické kartě zpracovala 5 milionů vět za 5 hodin a nakonec dosáhla úspěšnosti 98 % a výrazně překonala jednoduché metody, jak můžete vidět v následující tabulce.

metoda přesnost
všechna měkká 70.4 %
jednoduchá pravidla 80.0 %
nejčastější pravopis 90.8 %
neuronová síť 98.3 %

Můžete se podívat i na zdrojový kód trénování.

Co se síť naučila

Nevýhodou hlubokého učení je to, že nemáme možnost nějak jednoduše zjistit, co se neuronová síť vlastně naučila. Jakousi základní představu si můžeme udělat z takzvaných učících křivek. To je graf, který má na ose x počet použitých trénovacích dat a na ose y úspěšnost modelu. Říká tedy, jak rychle se model učil.

sequence-labeling

Z grafu na první pohled vidíme, že neuronová síť potřebovala poměrně dost trénovacích příkladů na to, aby se naučila dělat něco lepšího, než všude dávat měkké i. Potřebovala k tomu 13 tisíc vět. Můžeme se domnívat, že v tento okamžik se síť začíná učit něco jako pojem znaku.

Zatímco algoritmus, který si pamatuje nejčastější pravopis každého slova potřeboval 1 500 vět k tomu, aby byl úspěšnější, než naše jednoduchá pravidla, neuronová síť k tomu potřebovala 33 000 trénovacích vět – to je 2 200 normostran textu, více než trojnásobek délky Dostojevského Zločinu a trestu. V tento okamžik má síť pravděpodobně naučeno, že za určitých okolností za některými samohláskami následuje ‘y’.

Ze začátku má algoritmus, který si pamatuje nejčastější pravopis značnou výhodu. Na rozdíl od neuronové sítě, je v něm od začátku explicitně naprogramováno, že slova jsou od sebe oddělena mezerami. Neuronová síť se to musí naučit z dat za pomocí slabé zpětné vazby z udělaných chyb. Síť nakonec překonala pamatování si nejčastějšího pravopisu až po 300 000 větách. Ty by při průměrné rychlosti čtení 200 slov za minutu trvalo přečíst 17 dní bez přestávky (29 Zločinů a trestů).

To mimo jiné ukazuje, jak silná je abstrakce, kterou jako lidé běžně používáme a jak to, čemu se dnes říká umělá inteligence se principiálně liší od lidské inteligence. Vysvětlit někomu pravidla psaní měkkého a tvrdého ‘i’ bude určitě rychlejší, než nechat ho číst 29 Zločinů a trestů. Jak už jsem psal v úvodu, počítači tato pravidla nelze jednoduše sdělit. Naopak odvozování pravidel pravopisu z mnoha objemný svazků by nejspíš bylo vcelku náročné intelektuální cvičení pro libovolného člověka.

Další možností, jak zjistit, co se naše síť naučila, je provést ručně rozbor chyb na nějakých zajímavých příkladech. My se podíváme na několik vět z televizního diktátu Zdeňka Svěráka z roku 2008.

  • Děti se jako vždycky nejvíc těšily na slavnou velrybí kostru.
pravidla Děti se jako vždicky nejvíc těšili na slavnou velrybí kostru.
nejčastější Děti se jako vždycky nejvíc těšili na slavnou velrybí kostru.
neuronová síť (83 %) Děti se jako vždicky nejvíc těšili na slavnou velribý kostru.
neuronová síť (92 %) Děty se jako vždicky nejvíc těšily na slavnou velribý kostru.
neuronová síť (96 %) Děti se jako vždicky nejvíc těšily na slavnou velrybí kostru.
  • Rodiče zase lákaly archeologické nálezy kostěných nástrojů starých kultur.
pravidla Rodiče zase lákali archeologické nálezi kostěních nástrojů starých kultur.
nejčastější Rodiče zase lákaly archeologické nálezy kostěných nástrojů starých kultur.
neuronová síť (83 %) Rodiče zase lákali archeologické nálezi kostěních nástrojů starích kultur.
neuronová síť (92 %) Rodiče zase lákaly archeologické nálezi kostěných nástrojů starých kultur.
neuronová síť (96 %) Rodiče zase lákaly archeologické nálezy kostěných nástrojů starých kultur.
  • V oddělení nerostů pak byli zaujati třpytivými drahokamy, hýřícími kouzelnými barvami.
pravidla V oddělení nerostů pak bili zaujati třpitivími drahokami, hýřícími kouzelními barvami.
nejčastější V oddělení nerostů pak byly zaujati třpytivými drahokamy, hýřícími kouzelnými barvami.
neuronová síť (83 %) V oddělení nerostů pak byli zaujati třpitivími drahokami, hířícími kouzelními barvami.
neuronová síť (92 %) V oddělení nerostů pak byly zaujati třpitivými drahokami, hýřícími kouzelnými barvami.
neuronová síť (96 %) V oddělení nerostů pak byly zaujaty třpitivými drahokami, hířícími kouzelnými barvami.
  • Mezi plazy vás určitě zaujmou krokodýli.
pravidla Mezi plazi vás určitě zaujmou krokodíli.
nejčastější Mezi plazy vás určitě zaujmou krokodýli.
neuronová síť (83 %) Mezi plazi vás určitě zaujmou krokodíli.
neuronová síť (92 %) Mezi plazy vás určitě zaujmou krokodíli.
neuronová síť (96 %) Mezi plazy vás určitě zaujmou krokodíly.

Na těchto pár příkladech vidíme, že pravidla, která fungují na 80 % dobře, stále produkují text, který vypadá jako by ho psal téměř analfabet. Deset procent, které od sebe dělí jednoduchá pravidla a používání nejčastějšího pravopisu na druhou stranu vytváří dojem, že je text téměř bez chyby. Chyby jsou na místech, kde je skutečně potřeba využít pravidel o gramatické shodě.

Zkusit nějak interpretovat chování neuronové sítě je podstatně náročnější. V době, kdy dosahovala úspěšnosti okolo 83 %, dávala na skoro všechna místa měkké i, kromě dvou případů (byli a velribý). Za situace, kdy model na větách z Wikipedie dosahoval úspěšnosti 92 %, vypadají jeho výstupy na našich ukázkových větách poněkud zmateně. Přestože se jedná o kvantitativně lepší výsledek, než pamatovat si pro každé slovo nejčastější pravopis, příklady působí jako, že si model počíná dost náhodně.

Znatelně lepší je situace ve stavu, kdy model dosahoval úspěšnosti 96 %. Vidíme, že v tento okamžik zvládá shodu podmětu s přísudkem a první dvě věty jsou bez chyby. V třetí větě je hned několik chyb, které je nejspíš možné přisoudit tomu, že slova třpytivý a hýřivý a jim příbuzná se vyskytují poměrně řídce a model neměl možnost se je dobře naučit. Potom může chybně reprezentovat celou větu a dělat chyby i na jiných místech. Z chyby ve slově hýřivý můžeme usuzovat také na to, že spíš než, že by se model naučil seznam tvrdých souhlásek, spíše bude sám pro sebe učit něco jako vyjmenovaná slova. Naznačuje to i krokodíly, které se v tomto případě tváří podobně jako třeba slovo světadíly.

A to je všechno. S pomocí celkem jednoduché neuronové sítě se nám podařilo naučit se obstojně doplňovat i/y. Samozřejmě existují způsoby jak síť vylepšit (přidat více skrytých vrstev, opatřit si více trénovacích, atd.), ale o tom třeba někdy příště.