Jak maszyny piszą teksty: Słowa zapisane w liczbach - Zeszyty Maryny
Menu Zamknij

Jak maszyny piszą teksty: Słowa zapisane w liczbach

słowa zapisane w liczbach

Czy zastanawialiście się kiedyś, jak komputery piszą teksty? Czy wpadliście pewnego dnia na link do dzieła, które wyprodukował program komputerowy po tym, jak nauczył się całej serii “Harry’ego Pottera?” Chcielibyście wiedzieć, jak to się stało? Zapraszam Was na cykl wpisów o tym, jak maszyny piszą teksty.

Słowem wstępu

Jeśli ktoś zaglądał do zakładki “O mnie“, to wie, że na co dzień zajmuję się przetwarzaniem języka naturalnego za pomocą sieci neuronowych. Są to bardzo duże pojęcia, które w skrócie oznaczają, że całymi dniami siedzę przed komputerem i staram się, żeby umiał on rozumieć, analizować lub produkować język ludzki. Tematyka moich badań jest też powiązana ze sztuczną inteligencją, czyli z tym, żeby komputer sam potrafił wyciągać wnioski na temat danych i uczył się na ich podstawie.

Jako pisarkę interesuje mnie to, czy kiedyś komputer będzie w stanie mnie zastąpić jako autor tekstu (spojler: jeszcze bardzo, bardzo długo nie, uff!). A skoro mnie interesuje, to pewnie innych pisarzy i czytelników również. Postanowiłam więc podzielić się z Wami wiedzą, którą posiadam na temat tego całego procesu.

Żeby w pełni zrozumieć, jak program komputerowy pisze tekst, trzeba mieć pewne przygotowanie matematyczne, w szczególności z algebry liniowej oraz rachunku różniczkowego. Ale przecież nie jesteśmy tu po to, żeby uczyć się matematyki. Ten cykl jest więc skierowany do osób, które takiego przygotowania nie mają. Spokojnie, nic nam przez to nie umknie! Sama idea stojąca za tym, jak tekst wychodzi spod palców (klawiszy?) maszyny jest bardzo prosta i wcale nie trzeba prześledzić dokładnie każdego kroku obliczeniowego, żeby ogarnąć, o co chodzi.

Jak będzie wyglądał cykl

W pierwszym, niniejszym wpisie powiemy sobie o tym, jak można reprezentować słowa za pomocą liczb i po co w ogóle to robić.

We wpisie drugim przedstawię Wam sieć neuronową, której najczęściej używa się do zadań takich jak produkcja tekstu.

W trzecim wpisie powiem, jak obie powyższe rzeczy się łączą, żeby można było osiągnąć cel.

We wpisie czwartym pokażę inne przykłady zastosowania tej sieci w pracy z danymi tekstowymi.

Zaczynamy!


Dlaczego liczby, a nie słowa?

Dlatego, że słowa nie można pomnożyć, podzielić ani wyciągnąć z niego pierwiastka. Proste 🙂

Program komputerowy, jak to program, wykonuje operacje liczbowe. Potrzebuje więc danych, na których będzie mógł te operacje wykonać. Niestety słowa w swojej czystej postaci mu tego nie zapewniają. Trzeba więc coś zrobić, żeby przedstawić te słowa jako liczby.

Najprostszym rozwiązaniem, które przychodzi do głowy, jest utworzenie alfabetycznej listy naszych słów i oznaczenie każdego z nich liczbą naturalną. Przykład podałam w poniższej tabeli.

słowa jako liczby

Niestety, występuje tutaj pewien problem. Otóż komputer nie rozumie słów i będzie operował na samych liczbach – co już ustaliliśmy wcześniej. A między liczbami występują zależności. Na przykład liczba 8 jest równa liczbie 4 pomnożonej dwa razy. Czy to znaczy więc, że słowo niewyspany jest równe słowu cebula pomnożonemu dwa razy? Pewnie, że nie. Jest to dla nas oczywiste. Jednak dla komputera wcale oczywiste nie będzie, ponieważ on nie widzi słów; widzi tylko liczby.

Czyli co, nie możemy po prostu wziąć kolejnych liczb naturalnych jako reprezentacji dla słów, bo komputer opacznie zrozumie panujące między nimi zależności? To co można zrobić?

Otóż można zrobić dwie rzeczy:

  1. Przedstawić słowa tak, żeby ich reprezentacje były od siebie niezależne.
  2. Przedstawić słowa tak, żeby ich reprezentacje wykazywały wzajemne zależności, ale w sensowny sposób.

Poniżej pokażę, jak można to fajnie zrobić. Ale najpierw powiedzmy sobie, co to jest wektor.

Odkrycie doktoratu, czyli wektor wcale nie jest straszny

Pojęcie “wektor” pamiętam tylko z fizyki w szkole i wtedy oznaczało ono tajemniczą strzałkę na wykresach, które przedstawiały pracę, masę czy tam inne przyspieszenie. Nie rozumiałam z tego nic a nic, głównie dlatego, że nauczyciel był wybitnie kiepski. I tak oto po skończeniu liceum przeżyłam kolejną dekadę uważając, że wektory to jest jakaś sprawa dla nawiedzonych fizyków i po co to komu w ogóle potrzebne, bo na pewno nie mnie.

A potem na drugim doktoracie zapisałam się na kurs z uczenia maszynowego prowadzony na Youtubie przez profesora Andrew Ng, który w prostych słowach opowiedział o wektorach, macierzach i o tym, co się z nimi robi, żeby były przydatne. #ThanksAndrew

Ja Wam to powiem jeszcze prościej. Bo możemy wziąć sobie wektor o długości 14 i spędzić mnóstwo czasu starając się wyobrazić sobie, jak wygląda 14 wymiarów naszej wektorowej strzałki, a możemy sobie też odpuścić i po prostu uznać, że wektor to jest lista liczb.

Tylko tyle.

Wektor o długości 14 to po prostu lista czternastu liczb. I wygląda na przykład tak:

wektor

Wektory podlegają różnym operacjom matematycznym, takim jak dodawanie czy mnożenie, więc można je podać naszemu komputerowi, żeby sobie coś na nich liczył. I właśnie wektorów będziemy używać, żeby reprezentować nasze słowa.

Ale jakich wektorów?

Gorąco tylko tutaj, czyli kod 1 z n

Punkt pierwszy, czyli przedstawiamy słowa tak, żeby ich reprezentacje były od siebie niezależne.

Od tytułu powiało grozą i sztywniactwem. Co to niby jest ten “kod 1 z n”?

Otóż “kod 1 z n”, po angielsku nazywany “one-hot vector”, to wektor, którego liczby to jedna jedynka i poza tym same zera. Na przykład taki wektor o długości 5 będzie wyglądał tak:

one hot vector 1

Albo tak:

one hot vector 2

Albo w dowolny inny sposób, który daje nam jedną jedynkę i cztery zera. Proste, nie?

Ale po co?

Wróćmy na chwilę do naszej listy słów, którą będziemy nazywać “słownikiem”. Wyobraźmy sobie, że jest to bardzo długa lista, zawierająca wszystkie słowa znajdujące się w tekście, który chcemy dać komputerowi. Możemy sobie te słowa uporządkować alfabetycznie, bo przecież czemu nie. No więc mamy taką alfabetyczną listę i teraz chcemy reprezentować pojedyncze słowa z tej listy za pomocą wektorów.

Nic prostszego!

wektor a słownik

Wyobraźmy sobie, że nasza lista ma długość 8. Stwórzmy sobie więc wektor o długości 8 i zapełnijmy go samymi zerami. I teraz, jeśli chcemy przedstawić siódme słowo na naszej liście, wystarczy na siódmym miejscu naszego wektora postawić jedynkę zamiast zera. I gotowe!

Innymi słowy, komputer potrafi zestawić sobie naszą słownikową listę z naszym wektorem. Jeśli w wektorze widzi zero, to jest to dla niego informacja, że nie tego słowa szuka. Jedynka natomiast oznacza: “Bingo! To tutaj!”

I co nam to daje?

One-hot wektory nie wykazują wzajemnych zależności w taki sposób, jak liczby naturalne. Dwa razy trzy równa się sześć. Ale jeśli weźmiemy one-hot wektor z jedynką na trzecim miejscu i pomnożymy go przez dwa, to nie otrzymamy one-hot wektora z jedynką na miejscu szóstym. Miejsca, gdzie jedynki stoją w każdym wektorze, są od siebie całkowicie niezależne, więc nie ma pola do nieporozumień.

One-hot wektory można jednak dodawać. Na przykład wyobraźmy sobie, że mamy słownik o długości 500. W zdaniu Ala ma kota występują trzy słowa z tego słownika. Ala jest na miejscu pierwszym, ma na miejscu 348, a kot na miejscu 135. Tworzymy one-hot wektory dla każdego z tych słów, a potem dodajemy je do siebie. Co otrzymamy? Wektor o długości 500, który ma jedynki na miejscu 1, 135 i 348. Czyli skutecznie przekazuje informacje o tym, że w zdaniu występują trzy słowa (bo mamy trzy jedynki) oraz jakie to słowa są! Przydatne!

dodawanie one hot wektorów

W tym miejscu powiem jeszcze, że wszystkie powyższe przykłady nie obrazują skali operacji na one-hot wektorach. Zwykle słowniki są o wiele dłuższe niż 8 czy 500 słów; standardowo mają około 10 tysięcy elementów. W konsekwencji każdy wektor reprezentujący jakieś słowo z tego słownika również ma długość 10 tysięcy, więc prowadzenie na nich obliczeń wcale nie jest trywialne!

Przejdźmy teraz do innej metody reprezentacji wektorowej.

Słowo w wektor, czyli Google atakuje

Punkt drugi, czyli przedstawiamy słowa tak, żeby ich reprezentacje wykazywały wzajemne zależności, ale w sensowny sposób.

W 2013 roku opublikowano artykuł, w którym zaproponowano interesującą metodę tworzenia takich reprezentacji. Otóż autorzy artykułu uznali, że znaczenie każdego słowa można zaprezentować jako informację o tym, jakie słowa zwykle występują dookoła niego. Tak narodził się pomysł na algorytm word2vec, który zamienia słowa na wektory.

Ale… jak?

To jest najlepsza część. Otóż program robi to sam. Automatycznie. My tylko dajemy mu zbiór tekstów, a potem siadamy i czekamy, aż obliczenia się skończą. I nawet nie musimy szczegółów tych obliczeń pisać w kodzie; możemy po prostu powiedzieć komputerowi: “Masz tu teksty i policz sobie metodą word2vec”.

Jak odbywają się obliczenia? Otóż program bierze każde słowo z naszego słownika i, na podstawie tekstów, które mu podaliśmy do nauki, próbuje jednej z dwóch rzeczy:

  • Uznaje to słowo za dane wejściowe i stara się, żeby jako wynik obliczeń wyszedł mu zbiór słów, które najczęściej występują w pobliżu tego słowa (metoda Skip-gram).
  • Uznaje to słowo za prawidłowy wynik i stara się, żeby ten wynik wyszedł mu na końcu obliczeń, jeśli danymi wejściowymi będzie zbiór słów najczęściej występujących wokół niego (metoda CBOW).

Poniższy obrazek jest wzięty ze wspomnianego artykułu i obrazuje, jak działają obie metody.

cbow skip gram

W trakcie obliczeń program uczy się, jak reprezentować słowa w taki sposób, żeby wyniki mu się zgadzały. Najpierw tworzy wektor dla każdego słowa i wsadza w ten wektor całkowicie losowe liczby. Wektor może mieć dowolną długość; obecnie najczęściej jest to 300 lub 500. Program wykonuje pierwszą próbę obliczeń, sprawdza wynik, kalkuluje poziom błędu i na tej podstawie troszeczkę zmienia liczby w każdym wektorze. Potem próbuje znowu. I tak w kółko, aż spróbuje określoną liczbę razy (na przykład 20 tysięcy) albo aż wyniki zaczną mu się zgadzać na przyzwoitym poziomie.

W wyniku tego procesu powstaje baza danych, z której możemy sobie wyciągać słowa i ich reprezentacje wektorowe. Długość każdego wektora jest jedną z rzeczy, które trzeba ustalić na początku. Tak samo ustalamy, ile sąsiednich słów nasz program będzie brał pod uwagę. Ze względów obliczeniowych każdy wektor będzie zawierał liczby w przedziale od -1 do 1, mniej więcej o tak:

word2vec przykład

No i co z tego wynika?

Wektory, które otrzymujemy, zawierają w sobie wiele przydatnych informacji. Przede wszystkim, w wyniku opisanego powyżej procesu wektory dla słów, które występują w sąsiedztwie tych samych wyrazów, będą bardzo podobne. Powiedzmy, że staramy się stworzyć wektor dla słowa czerwony, obok którego mogą występować takie słowa jak szminka, zachód słońca czy też zwyczajnie kolor. W podobnym otoczeniu wystąpi słowo karminowy, więc wartości liczb w jego wektorze będą bardzo podobne do tych w wektorze dla słowa czerwony! Dzięki tej zależności możemy na przykład wziąć jakieś słowo i poprzez wyszukanie wektorów najbardziej podobnych do jego wektora znaleźć jego synonimy.

W dodatku wektory odzwierciedlają również inne znaczeniowe zależności. Autorzy algorytmu word2vec odkryli, że jeśli wezmą wektor słowa Paryż i odejmą go od wektora słowa Francja, to uzyskany wynik będzie podobny temu, który stanowi różnicę wektorów słów RzymWłochy! Poniżej macie więcej przykładów zależności.

word2vec zależności

Skąd wziąć takie wektory?

Żeby odpowiednio wyuczyć program, potrzebujemy bardzo dużej ilości tekstów. Żeby zobrazować skalę, to powiem, że mój osobisty model trenowałam na całości angielskiej Wikipedii (fun fact: można sobie ściągnąć z internetów całą Wikipedię!). Więc niestety nie może to być jedno opowiadanie albo kilkanaście fejsbukowych postów.

Oczywiście, nie każdy z nas ma takie ilości tekstu pod ręką albo odpowiednio mocny komputer, żeby udźwignął kilka dni obliczeń. W takich sytuacjach możemy jednak skorzystać z gotowych wektorów wytrenowanych przez duże firmy z dostępem do danych i zasobów obliczeniowych. Przykładami są wspomniane już Google’owe word2vec, Numberbatch, Glove, FastText albo coraz popularniejsze ostatnio ELMoBERT (tak, ci z Ulicy Sezamkowej).

I to już wszystko w temacie wektorów!

Czego się dzisiaj dowiedzieliśmy

  1. Żeby podać komputerowi tekst, musimy przedstawić słowa jako wektory.
  2. Wektor jest listą liczb. Długość wektora to długość tej listy.
  3. Wektory mogą być rodzaju kod 1 z n (one-hot) albo być stworzone przez algorytm taki jak word2vec.
  4. Wektory typu kod 1 z n (one-hot) zawsze mają długość naszego słownika i składają się z zer i jednej jedynki.
  5. Wektory word2vec mają taką długość, jaką ustalimy, i składają się z małych liczb między -1 i 1.
  6. Wektory word2vec lepiej reprezentują zależności między słowami niż wektory typu kod 1 z n (one-hot).

Jeśli masz jakieś pytania, zadaj je w komentarzu!

kolejnym wpisie opowiemy sobie o tym, co to jest sieć rekurencyjna.

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

Powiązane wpisy

Powiadamiaj o
Powiadom o
guest

3 komentarzy
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments
trackback

[…] W poprzednim wpisie rozmawialiśmy o tym, że słowa można przedstawić za pomocą wektorów. W taki sam sposób można przedstawić też całe teksty. Na przykład wyobraźmy sobie, że mamy tekst składający się z 453 słów. Możemy dla każdego z tych słów wziąć jego wektor, powiedzmy o długości 300, a potem obliczyć średnią z tych wektorów jako reprezentację całego tekstu. W efekcie mamy jeden wektor o trzystu elementach, który zawiera informacje o wszystkich słowach składowych tekstu. […]

trackback

[…] poście z serii “Jak maszyny piszą teksty”. Rozmawialiśmy już o wektorach i o sieciach neuronowych. Jeśli ktoś nie jest w temacie, […]

trackback

[…] wpis z cyklu “Jak maszyny piszą teksty” (link do pierwszego wpisu tutaj, jakby ktoś jeszcze nie czytał). Rozmawialiśmy o tym, co to są […]