Jak maszyny piszą teksty: Inne zastosowania sieci rekurencyjnych - Zeszyty Maryny
Menu Zamknij

Jak maszyny piszą teksty: Inne zastosowania sieci rekurencyjnych

sieci rekurencyjne zastosowania

Witam Was w czwartym, ostatnim już wpisie z cyklu “Jak maszyny piszą teksty”. We wpisie numer dwa poznaliśmy rekurencyjną sieć neuronową. We wpisie numer trzy zobaczyliśmy, jak można ją wykorzystać do stworzenia modelu językowego i produkcji tekstu.

Ale sieci rekurencyjne mają też bardzo wiele innych zastosowań! Tak naprawdę każdy problem badawczy, który da się potraktować jako przetwarzanie jakieś sekwencji danych, możemy spróbować rozwiązać za pomocą sieci rekurencyjnej. Kilka z nich omówimy sobie w dzisiejszym wpisie. Lista nie będzie jednak wyczerpująca; skupiłam się tutaj na zadaniach dotyczących języka, ale równie dobrze możemy wykorzystać sieć neuronową do przetwarzania muzyki (sekwencji dźwięków), łańcuchów DNA lub filmów (sekwencji obrazów).

Najpierw jednak powiedzmy sobie, jakie mamy rodzaje sieci rekurencyjnych.

Rodzaje rekurencyjnych sieci neuronowych

Być może zauważyliście, że dotychczas omawiane sieci rekurencyjne miały trochę różną architekturę. Sieć klasyfikująca emocje tekstu wyrzucała nam dane wyjściowe dopiero na końcu, a model językowy jako dane wejściowe dla każdego pudełka przyjmował to, co dostał na wyjściu od pudełka poprzedniego. Zobaczmy sobie więc, jak wygląda klasyfikacja rekurencyjnych sieci neuronowych.

Sieć wiele-do-jednego

klasyfikacja

Jak widać, jest to właśnie nasza sieć do klasyfikacji emocji. Obrazek trochę zmodyfikowałam – konkretnie to usunęłam strzałki dające dane wyjściowe, na które nie zwracamy uwagi. Sieć typu wiele-do-jednego przyjmuje dane wejściowe w wielu etapach (tutaj są nimi słowa naszego tekstu), lecz dane wyjściowe są pojedynczym wynikiem.

Sieć jeden-do-wielu

jeden-do-wielu

A to z kolei nasz model językowy. Tutaj też wprowadziłam modyfikacje: usunęłam granatową strzałkę wychodzącą z ostatniego pudełka, bo na co nam ona?

W takiej architekturze dane podajemy tylko pierwszemu pudełku, a potem sieć produkuje tekst samodzielnie w wielu etapach. Dlatego właśnie sieć tego typu nazywamy jeden-do-wielu.

Sieć wiele-do-wielu, gdzie Tx = Ty

Ok, najpierw powiedzmy sobie, czym są TxTy. Otóż są to standardowe oznaczenia odpowiednio dla długości danych wejściowych i danych wyjściowych. Czyli sieć, gdzie Tx = Ty, będzie miała tyle samo etapów podawania jej danych wejściowych, co etapów produkcji danych wyjściowych. Analogicznie, symbolami xy oznaczamy kolejne kawałki danych.

wiele-do-wielu Tx=Ty

W tego typu sieciach za każdym razem, gdy podamy kolejny element z danych wyjściowych, będziemy otrzymywać również kolejny element z danych wyjściowych. Taką sieć wykorzystamy na przykład do rozpoznawania mowy, o czym powiemy sobie w późniejszej części tego wpisu.

Sieć wiele-do-wielu, gdzie Tx ≠ Ty

Czasami jednak będziemy mieli sytuację, gdzie długość naszych danych wejściowych będzie się różniła od długości danych wyjściowych. Co wtedy robimy? Ano stosujemy tak zwaną metodę enkodera-dekodera. Została ona zaproponowana w roku 2014 na potrzeby tłumaczenia maszynowego przez dwa różne zespoły badaczy. W przypadku tumaczenia maszynowego zwykle tekst źródłowy będzie miał inną liczbę słów niż tekst docelowy, dlatego nie moglibyśmy tu zastosować zwykłej sieci typu wiele-do-wielu.

enkoder-dekoder

Architektura enkodera-dekodera składa się właściwie z dwóch sieci. Pierwsza zakodowuje tekst do postaci pośredniej, a druga odkodowuje tę reprezentację do innego tekstu. Wspomniana postać pośrednia to te informacje, które ostatnie pudełko enkodera produkuje jako dane dla pudełka następnego; w tym wypadku będzie to pierwsze pudełko dekodera. Jak to działa dla tłumaczenia maszynowego powiemy sobie na końcu niniejszego wpisu.

No to teraz zajmijmy się tym, po co tu przyszliście. Jakie są zastosowania rekurencyjnych sieci neuronowych oprócz tworzenia modelu języka opartego na słowach?

Model języka oparty na znakach

No bo czemu nie?

W poprzednim wpisie mówiliśmy o tym, jak to sieć uczy się kolejności słów w danym języku i dzięki temu potrafi wyprodukować swój własny tekst. Nic nie stoi na przeszkodzie, żeby tę samą metodę zastosować na poziomie kolejności liter.

A po co mielibyśmy to robić? Cóż, jednym przykładowym zastosowaniem jest tworzenie nowych imion dla dinozaurów, co było naszym zadaniem na wspomnianym już przeze mnie kursie prowadzonym przez Andrew Ng. Jako pisarze moglibyśmy w ten sposób wygenerować imiona postaci albo nazwy miejscowości w świecie fantasy z zachowaniem stylu wybranego języka, na przykład arabskiego. Moglibyśmy też stworzyć sobie nowe imiona Pokemonów, co obierzemy sobie teraz za przykładowy cel 😉

Żeby cel osiągnąć, musielibyśmy mieć zbiór imion istniejących Pokemonów (im więcej, tym lepiej) i podawać je naszemu modelowi jako dane treningowe. Oczywiście w tym przypadku każdy etap pracy sieci zajmowałby się pojedynczą literą zamiast pojedynczym słowem. Model uczyłby się typowej kolejności liter w imionach Pokemonów oraz częstych zbitek głosek, podobnie jak model oparty na słowach uczył się typowej kolejności wyrazów w zdaniu. I podobnie byłby to model typu jeden-do-wielu. Element <EOS> oznaczałby zaś koniec wygenerowanego imienia.

Poniżej macie przykład, jak mogłaby wyglądać produkcja. Ponieważ nie mam pod ręką wytrenowanego modelu, to imię Pokemona wzięłam z tej strony.

imię pokemona

Rozpoznawanie mowy

Rozpoznawanie mowy ma zastosowanie w bardzo wielu sytuacjach. Jako przykład możemy podać smartfony rozpoznające komendy głosowe albo systemy typu Alexa. Kiedy mówimy coś do komputera, jego zadaniem jest odcyfrowanie szeregu dźwięków mowy na szereg wyrazów języka pisanego i po przetworzeniu tego szeregu wykonanie odpowiedniej komendy lub podanie odpowiedzi na zadane pytanie.

Jak wspomniałam, sieć do tego zadania będzie typu wiele-do-wielu, gdzie Tx = Ty. Rozwińmy sobie tę myśl.

Klipy audio stanowią ciąg dźwięków. Na potrzeby rozpoznawania mowy często przetwarzamy ten ciąg do reprezentacji w postaci spektrogramu. Jest to taki obrazek, który pokazuje nam, jakie częstotliwości występują w audio na każdym etapie, co pozwala nam określić, jakie głoski wypowiadane są w danym momencie.

spektrogramPrzykład spektrogramu. Źródło: zadanie domowe do lekcji o przetwarzaniu sekwencji dźwiękowych

Wspomniałam we wpisie numer dwa, że obrazki najlepiej przetwarza się za pomocą sieci konwolucyjnych. Nie będziemy sobie o nich tutaj mówić. Jedyną istotną rzeczą jest to, że ten spektrogram to nasze dane wejściowe, a zatem pierwsza warstwa sieci będzie konwolucyjna. Z tej warstwy dane wyjściowe stanowią już przetworzoną sekwencję i właśnie tę sekwencję podajemy naszej sieci rekurencyjnej. Także Tx rzeczywiście równa się Ty… jeśli chodzi o rekurencyjną część naszej sieci 😉 Na obrazku poniżej x oznacza dane wejściowe do części rekurencyjnej, a s to dane wejściowe ze spektrogramu przetwarzane przez warstwę konwolucyjną.

rozpoznawanie mowy

Jak widać, czasem ciąg danych ze spektrogramu będzie dłuższy niż ciąg danych przekazywany dalej do części rekurencyjnej. Warto też powiedzieć, że zarówno Tx, jak i Ty będą reprezentowały interwał dużo mniejszy niż sekunda nagrania. Może to być na przykład kilka tysięcznych części sekundy. Dlatego na 10 czy 15 sekund nagrania mogą przypadać na przykład 2 lub 3 tysiące etapów pracy sieci!

Oczywiście w piętnastosekundowych danych wyjściowych nie będziemy mieli 3,000 głosek. Raczej będzie to wyglądało tak, że wiele sąsiadujących ze sobą etapów poda nam na wyjściu tę samą głoskę. Dlatego na końcu, gdy już otrzymamy wszystkie dane wyjściowe, po prostu sprowadzany sąsiadujące, powtarzające się głoski do jednej. Na przykład jeśli 20 sąsiednich etapów wskaże nam głoskę t, to w postaci ostatecznej danych wyjściowych zareprezentujemy ten fragmencik nagrania po prostu jedną literką t. A jak już wszystko skleimy i zredukujemy, to otrzymamy transkrypt naszego klipu audio.

Rozpoznawanie komend

W taki sam sposób możemy zbudować model, który będzie rozpoznawał słowa wyzwalające określone zachowania u komputera. Takimi słowami są na przykład Alexa, Hey Google czy też chińskie Ni hao Baidu, po których usłyszeniu komputer rozpoczyna wykonywanie określonej komendy. Model służący do rozpoznawania, czy takie słowo zostało wypowiedziane przez użytkownika czy nie (a więc czy komputer ma coś zrobić, czy może sobie odpoczywać dalej) będzie taki sam jak wskazany powyżej model do rozpoznawania mowy. Danymi wejściowymi również będzie ciąg dźwięków. Jedyna różnica jest taka, że w danych wyjściowych zamiast określonej głoski będziemy rozpoznawać, czy dane słowo jest właśnie wypowiadane, czy nie. Jeśli słowo-komenda zostanie wykryte, sieć wyrzuci nam jedynkę; jeśli tej komendy nie wykryje, to wyrzuci nam zero. Jedynka będzie więc oznaczała, że komputer nadstawia ucha i czeka na rozkazy.

Tłumaczenie maszynowe

Ach, tłumaczenie maszynowe. Jeden z moich ulubionych tematów 🙂 Chcę Wam o nim powiedzieć, bo po pierwsze jest to jedno z najważniejszych zastosowań sieci rekurencyjnych, a po drugie, możemy przy okazji wspomnieć o kilku fajnych siecioneuronowych trikach, dzięki którym to tłumaczenie staje się coraz lepsze.

W sumie sieci neuronowe w tłumaczeniu maszynowym zaczęto wykorzystywać stosunkowo niedawno. Na przykład Google Translate przerzuciło się na tę metodę dopiero pod koniec 2016 roku. Ale że jest skuteczna, to pewnie na razie już przy niej zostaną 😉

Proces tłumaczenia

Jak pisałam wyżej, tłumaczenie maszynowe najczęściej odbywa się za pomocą metody enkodera-dekodera. To oznacza, że właściwie mamy tu dwie sieci: jedna służy do zakodowania tekstu, a druga do odkodowania go. Jedna przyjmuje nasze dane wejściowe, ale nie produkuje wyjściowych – za wyjątkiem reprezentacji pośredniej, czyli tej zakodowanej. Druga sieć na odwrót – przyjmuje reprezentację pośrednią, ale nic poza tym, i produkuje słowa tekstu wyjściowego.

Jeśli dobrze się przyjrzycie schematowi, który umieściłam wyżej w poście, to zauważycie, że dekoder tak naprawdę jest taką samą siecią, jak ta produkująca tekst z poprzedniego postu! Samodzielnie generuje on tłumaczenie, a potem porównuje je z tłumaczeniem podanym mu przez człowieka. Różnica jest jedynie taka, że zamiast niby-danych podajemy sieci reprezentację wygenerowaną przed enkoder. Zamiast drugich niby-danych, tych “od dołu”, możemy podać reprezentację elementu <EOS>. Będzie to sygnał dla naszej sieci, że ma zacząć działać i produkować tłumaczenie. Ilustrację dekodera znajdziecie poniżej.

Powiedzmy sobie jeszcze o danych treningowych. Podobnie jak inne metody tłumaczenia, sieci neuronowe wykorzystują do tego celu (ogromne!) korpusy dwujęzyczne. Korpus dwujęzyczny to po prostu zbiór tekstów w dwóch językach, gdzie każdy tekst w języku numer jeden jest tłumaczeniem tekstu w języku numer dwa (lub na odwrót). Czyli jest to taki zbiór tekstowych par. Podczas trenowania sieci danymi wejściowymi będzie tekst do tłumaczenia, czyli jeden tekst z pary. Ten tekst wsadzamy do enkodera, żeby uzyskać jego reprezentację pośrednią. Tekstem wyjściowym – tym do porównywania i obliczania błędu sieci – będzie ten sam tekst, tylko napisany w języku numer dwa (a więc drugi z pary). Na jego podstawie obliczamy stopień błędu sieci, dostosowujemy obliczenia i kontynuujemy trening.

dekoder

Oczywiście, ta metoda nie jest pozbawiona wad. Na przykład problemem jest to, że wektor reprezentacji pośredniej zawsze ma taką samą długość dla każdego zdania, czy to składającego się z 5 wyrazów, czy z 15. Jednak powstają różne fajne sposoby rozwiązywania tych problemów. A w dodatku w tłumaczeniu maszynowym implementuje się inne ciekawe pomysły, o których poniżej.

Pomysł numer 1: Zwiększamy promień rażenia, czyli Beam Search

Wrócmy sobie na chwilę do tego, co działo się w poprzednim poście. Pamiętacie, jak przy generowaniu tekstu mówiliśmy sobie o prawdopodobieństwach? O tym, że sieć oblicza prawdopodobieństwo, że dane słowo będzie następne w ciągu wyrazów? W tamtym modelu na każdym etapie losowaliśmy kolejne słowo według prawdopodobieństwa obliczonego tylko dla niego. Jednak w tłumaczeniu maszynowym postąpimy trochę inaczej. Możliwości przetłumaczenia dowolnego tekstu jest bardzo wiele i nie zawsze kolejne słowo powinno być tym, które akurat ma największe prawdopodobieństwo wystąpienia. Co więc możemy zrobić, żeby wygenerować jak najlepszy przekład?

Ano możemy obliczać prawdopodobieństwo z uwzględnieniem wielu sąsiadujących słów. Ta metoda nazywa się właśnie Beam Search.

Wyobraźmy sobie, że nasz softmaxowy wektor prawdopodobieństw ma kolor niebieski. Do tej pory wybieraliśmy z niego jeden element o najwyższym wyniku i dodawaliśmy go do generowanego szeregu. Potem obliczaliśmy kolejne prawdopodobieństwa i braliśmy kolejny najlepszy element. Powiedzmy jednak, że teraz na każdym etapie chcemy brać pod uwagę 4 słowa zamiast jednego. W takim wypadku na pierwszym etapie, zamiast wziąć jedno słowo, to bierzemy 4 o największym prawdopodobieństwie – na schemacie zaznaczyłam je na czerwono. Na etapie numer dwa dla każdego z nich bierzemy znowu 4 kolejne słowa, idąc w dół tworzonego drzewa. Ten proces powtarzamy aż do końca zdania. Poniżej macie ilustrację, jak to działa, kiedy chcemy wygenerować tłumaczenie składające się z trzech wyrazów. Na poziomie pierwszym mamy tylko jeden wektor, z którego wybieramy 4 elementy. Na poziomie drugim są więc 4 wektory, po jednym dla każdego wybrańca. Na poziomie trzecim mamy już 16, ale zilustrowałam tylko 4, żeby schemat wyglądał jaśniej.

Jako tłumaczenie wybierzemy tę wersję – czyli tę gałąź schematu – która ma największe skumulowane prawdopodobieństwo dla ciągu słów, a jednocześnie daje najmniejszy błąd w porównaniu z tłumaczeniem z korpusu. Na schemacie to zdanie jest reprezentowane przez kolor zielony.

beam search

Pomysł numer 2: Droga dwukierunkowa, czyli BiRNN

Sieci rekurencyjne, jak już sobie mówiliśmy, doskonale potrafią rozpracować kolejność słów w tekście. To dlatego, że przyjmują dane w uporządkowanych liniowo etapach. Czasami jednak warto byłoby zerknąć nie tylko na to, co mamy za nami, ale też na to, co jeszcze przed nami.

Dwukierunkowe sieci rekurencyjne (bidirectional recurrent neural networks) właśnie tak działają. Dzięki nim w tłumaczeniu możemy podejrzeć cały ciąg wyrazów do przetłumaczenia, a nie tylko jego lewą część. A nuż na końcu będzie coś ważnego akurat dla bieżącego etapu generowania przekładu!

Sieci dwukierunkowe są jakby połączeniem dwóch sieci jednokierunkowych. Z tym tylko, że jedna sieć jednokierunkowa działa w drugą stronę. Obie przyjmują te same dane wejściowe (jedna z nich od początku, a druga od końca) i obie produkują dane wyjściowe, które zostają sklejone razem, aby utworzyć ostateczny wynik.

sieć dwukierunkowa

Pomysł numer 3: Uwaga, czyli Attention Mechanism

Jednym z najważniejszych trendów w badaniach z wykorzystaniem sieci neuronowych jest implementowanie mechanizmu atencyjnego. Ten mechanizm pozwala nam nie tylko spojrzeć na całość tekstu wejściowego – na przykład zdania do tłumaczenia – ale również wybrać z niego najważniejsze elementy. Dzięki niemu sieć skupia się głównie na słowach kluczowych dla przekładu, co podnosi jakość samego tłumaczenia, bo pozwala lepiej dobierać ciąg wyrazów w języku docelowym.

Mechanizm atencyjny implementujemy jakby w środku sieci: między momentem, gdy produkuje ona dane wyjściowe z pudełek, a momentem, w którym te dane wyjściowe są zamieniane na kolejne słowa. Czyli patrząc na nasze schematy, jest po poziom, na którym znajdują się jasnoniebieskie strzałki.

Mechanizm atencyjny polega na tym, że na każdym etapie bierzemy pośrednie dane wyjściowe ze wszystkich pudełek i na tej podstawie obliczamy tak zwany wektor kontekstu. Jest to nic innego, jak tylko reprezentacja słowa z danego etapu osadzona w – nomen omen – kontekście wszystkich pozostałych słów w zdaniu. Potem te reprezentacje kontekstowe stają się danymi wejściowymi dla kolejnej warstwy naszej sieci, która już produkuje słowa wyjściowe.

Jak już sobie powiedzieliśmy, w tłumaczeniu maszynowym często dane wyjściowe mają inną długość niż dane wejściowe. Na przykład na (uproszczonym!) obrazku poniżej widać, że Tx jest dłuższe niż Ty. W takim wypadku pudełek atencyjnych powinniśmy mieć tyle, ile mamy etapów danych wyjściowych. Dlaczego? Ano dlatego, że górna warstwa sieci przyjmuje je na wejściu i z nich od razu produkuje ostateczne rezultaty. Górna warstwa sieci ma bowiem postać wiele-do-wielu, gdzie Tx = Ty.

Na rysunku czerwonym kolorem zaznaczyłam informacje przechodzące przez pierwsze pudełko atencyjne. Jak widać, to pudełko zbiera informacje ze wszystkich pudełek sieci w niższej warstwie i przekazuje swoje dane wyjściowe do warstwy górnej, produkując pierwszy wyraz tłumaczenia. Reprezentacje kontekstowe natomiast zaznaczyłam na żółto.

mechanizm atencyjny

Czego się dzisiaj dowiedzieliśmy

  1. Rekurencyjne sieci neuronowe mogą mieć różną architekturę w zależności od długości danych wejściowych i wyjściowych. Każda architektura sieci ma inne zastosowanie.
  2. Sieci rekurencyjne możemy wykorzystać nie tylko do tworzenia modeli językowych, ale też do zadań takich jak rozpoznawanie mowy albo tłumaczenie maszynowe.
  3. W tłumaczeniu maszynowym zwykle wykorzystywana jest sieć typu enkoder-dekoder.
  4. W modelu enkodera-dekodera pierwsza sieć służy do zakodowania danych wejściowych do reprezentacji pośredniej. Druga sieć służy do odkodowania tej reprezentacji do postaci danych wyjściowych.
  5. Właściwie każde zadanie, jakie damy rekurencyjnej sieci neuronowej, wymaga ogromnych ilości danych treningowych.
  6. W tłumaczeniu maszynowym jako dane treningowe wykorzystujemy korpusy dwujęzyczne.
  7. Beam Search, sieci dwukierunkowe oraz przede wszystkim mechanizm atencyjny pozwalają nam podnieść jakość tłumaczenia.

Triki z punktu siódmego można też ze sobą łączyć. Na przykład możemy zbudować sieć, której dolna warstwa będzie dwukierunkowa, potem nałożymy na nią mechanizm atencyjny, a na koniec wynik będziemy wybierać metodą Beam Search 😉 Ponadto wszystkie trzy techniki znajdują zastosowanie również poza tłumaczeniem maszynowym. Ostatnio koncepcja atencji została wykorzystana do stworzenia ogromnych modeli obliczeniowych, tak zwanych transformerów. Ale o nich może powiemy sobie kiedy indziej 😉

Pytania? Czekam na nie w komentarzach!


Podsumowanie cyklu

I to już wszystko, co dla Was przygotowałam w cyklu “Jak maszyny piszą teksty”. Powiem szczerze, że dobrze bawiłam się przy tych postach. Szczególnie tworzenie kolorowych rysunków sprawiało mi wiele radości 🙂

Mam nadzieję, że dzięki tej serii macie teraz lepsze pojęcie o tym, jak komputer produkuje tekst. Jak widać, głównie polega to na suchych obliczeniach i wykorzystywaniu technik statystycznych. Dlatego odpowiadając na pytanie, które zadaliśmy sobie na początku: nie, komputer jeszcze długo nie zastąpi człowieka jako pisarza. Może on co najwyżej odtworzyć ciąg wyrazów napisany przez człowieka. Mimo naszych (mówię teraz o badaczach) najlepszych chęci, nie potrafimy na razie sprawić, żeby komputer faktycznie rozumiał podawane mu teksty. Jest to cel, do którego konsekwentnie dążymy, ale jeszcze trochę nam to zajmie, więc na razie śpijcie spokojnie 😉

Podziel się tym wpisem w mediach społecznościowych

Powiązane wpisy

Powiadamiaj o
Powiadom o
guest

2 komentarzy
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments
trackback

[…] tworzenie tłumaczeń albo transkrypcja mowy. Te kwestie omówimy sobie w kolejnym, ostatnim już wpisie z tego […]

trackback

[…] poprzednich publikacji. Ta konkretna sieć wykorzystała omawiany już przeze mnie model enkodera-dekodera, który został zapożyczony z innych badań. Wiemy więc, […]