diff --git a/wyk/09_neurozoo.org b/wyk/09_neurozoo.org index d95c66c..cc72bb5 100644 --- a/wyk/09_neurozoo.org +++ b/wyk/09_neurozoo.org @@ -375,13 +375,13 @@ Definicja w PyTorchu: z_plus = torch.exp(z) return z_plus / torch.sum(z_plus) - softmax(torch.tensor([3., -1., 0., 5.])) + softmax(torch.tensor([3., 1., -1., 1.])) #+END_SRC #+RESULTS: :results: -# Out[75]: -: tensor([0.1182, 0.0022, 0.0059, 0.8737]) +# Out[3]: +: tensor([7.8678e-01, 1.0648e-01, 2.6393e-04, 1.0648e-01]) :end: #+CAPTION: Softmax diff --git a/wyk/12_bpe.ipynb b/wyk/12_bpe.ipynb new file mode 100644 index 0000000..9a04687 --- /dev/null +++ b/wyk/12_bpe.ipynb @@ -0,0 +1,834 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Podział na jednostki podwyrazowe\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Słownik nie może być za duży…\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Jeśli używamy wyuczalnych zanurzeń słów (embeddingów), wówczas musimy\n", + "je dopisać do listy parametrów całego modelu — jest to $|V|n$ wag,\n", + "gdzie $n$ to rozmiar embeddingów; w wypadku uczenia dodatkowo musimy\n", + "jeszcze pamiętać związane z embeddingami gradienty. Pamięć RAM karty\n", + "graficznej jest rzecz jasna ograniczona, słownik więc nie może być\n", + "dowolnie duży. Dla danego modelu karty graficznej dość łatwo ustalić\n", + "maksymalny rozmiar słownika — jest „twarde” ograniczenie, które musimy\n", + "spełnić.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Czy rzeczywiście słownik może być taki duży?\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ile jest różnych form fleksyjnych w języku polskim? Zobaczmy w słowniku PoliMorf…\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n", + "aa\n", + "AA\n", + "Aachen\n", + "Aalborg\n", + "Aalborgiem\n", + "Aalborgowi\n", + "Aalborgu\n", + "AAP\n", + "Aar\n", + "Aarem\n", + "Aarowi\n", + "Aaru\n", + "Aarze\n", + "Aara\n", + "Aarą\n", + "Aarę\n", + "Aaro\n", + "Aary\n", + "Aarze\n", + "uniq: błąd zapisu: Przerwany potok\n" + ] + } + ], + "source": [ + "! wget -q 'http://zil.ipipan.waw.pl/PoliMorf?action=AttachFile&do=get&target=PoliMorf-0.6.7.tab.gz' -O - | zcat | cut -f 1 | uniq | head -n 20" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3844535\r\n" + ] + } + ], + "source": [ + "! wget -q 'http://zil.ipipan.waw.pl/PoliMorf?action=AttachFile&do=get&target=PoliMorf-0.6.7.tab.gz' -O - | zcat | cut -f 1 | sort -u | wc -l" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Pytanie** W którym języku europejskim wyrazów będzie jeszcze więcej niż języku polskim?\n", + "\n", + "Tak naprawdę form jest jeszcze więcej, oczywiście PoliMorf nie wyczerpuje zbioru…\n", + "\n", + "**Pytanie** Podaj przykłady „oczywistych” wyrazów, których w PoliMorfie. Jak w sposób systematyczny szukać takich wyrazów?\n", + "\n", + "Z drugiej strony, w PoliMorfie jest dużo dziwnych, „sztucznych” wyrazów.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "niemałomieszczańskiej\r\n", + "kwatereczki\r\n", + "słowniejszej\r\n", + "oranżysta\r\n", + "myrmekofagów\r\n", + "hipokratesowego\r\n", + "rozdziałująca\r\n", + "wielosettysięczne\r\n", + "redempcyjno\r\n", + "łącznikowce\r\n", + "niesłowacyzowana\r\n", + "sosnowieckościach\r\n", + "niewschodoznawczy\r\n", + "niekłosokształtnego\r\n", + "niegenialności\r\n", + "Gierowskiego\r\n", + "nieumierzwiających\r\n", + "bezzakłóceniowości\r\n", + "niedziurkowatościach\r\n", + "Krzaklewskich\r\n" + ] + } + ], + "source": [ + "! wget -q 'http://zil.ipipan.waw.pl/PoliMorf?action=AttachFile&do=get&target=PoliMorf-0.6.7.tab.gz' -O - | zcat | cut -f 1 | shuf -n 20" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Inaczej, zobaczmy, ile różnych wyrazów jest w jakimś rzeczywistym zbiorze tekstów, rozpatrzmy\n", + "teksty zebrane na potrzeby identyfikacji płci autora tekstu:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Out[7]:" + ] + } + ], + "source": [ + "! git clone --single-branch --depth 1 git://gonito.net/petite-difference-challenge2" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "! xzcat petite-difference-challenge2/train/in.tsv.xz | perl -C -ne 'print \"$&\\n\" while/\\p{L}+/g;' | sort -u > vocab.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ˆ\r\n", + "ˇ\r\n", + "゚\r\n", + "a\r\n", + "A\r\n", + "á\r\n", + "Á\r\n", + "à\r\n", + "À\r\n", + "ă\r\n", + "Ă\r\n", + "â\r\n", + "Â\r\n", + "å\r\n", + "Å\r\n", + "ä\r\n", + "Ä\r\n", + "Ã\r\n", + "ā\r\n", + "aa\r\n", + "aA\r\n", + "Aa\r\n", + "AA\r\n", + "aĂ\r\n", + "AĂ\r\n", + "aâ\r\n", + "aÂ\r\n", + "Aâ\r\n", + "aÅ\r\n", + "aÄ\r\n", + "ª\r\n", + "aaa\r\n", + "aAa\r\n", + "Aaa\r\n", + "AaA\r\n", + "AAa\r\n", + "AAA\r\n", + "aaaa\r\n", + "aAaa\r\n", + "Aaaa\r\n", + "AaAa\r\n", + "AAaa\r\n", + "AAAa\r\n", + "AAAA\r\n", + "aaaaa\r\n", + "Aaaaa\r\n", + "AaaaA\r\n", + "AAaaa\r\n", + "AAAAA\r\n", + "aaaaaa\r\n" + ] + } + ], + "source": [ + "! head -n 50 vocab.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2974556 vocab.txt\r\n" + ] + } + ], + "source": [ + "! wc -l vocab.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Co gorsza, nawet jak weźmiemy cały taki słownik bez ograniczeń i tak\n", + "nie pokryje on sporej części tekstów przetwarzanych w czasie inferencji.\n", + "Zobaczmy, ilu wyrazów ze zbioru deweloperskiego nie będzie w słowniku.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "81380\r\n" + ] + } + ], + "source": [ + "! cat petite-difference-challenge2/dev-0/in.tsv | perl -C -ne 'print \"$&\\n\" while/\\p{L}+/g;' | sort -u | comm vocab.txt - -13 | wc -l" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Takie wyrazy nazywamy wyrazami **OOV** (*out-of-vocabulary*).\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Obcięcie słownika\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Najprostszy sposób ograniczenia słownika to po prostu obcięcie do $N$ najczęstszych słów.\n", + "\n", + "Spróbujmy zastosować do korpusu „płci”:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Out[8]:" + ] + } + ], + "source": [ + "! xzcat petite-difference-challenge2/train/in.tsv.xz | perl -C -ne 'print \"$&\\n\" while/\\p{L}+/g;' | sort | uniq -c | sort -k 1rn | head -n 50000 | sort -k 2 > vocab50000.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Daje to lepszy efekt niż można się spodziewać. Odrzucamy w ten sposób\n", + "tylko bardzo rzadkie słowa (albo takie, które wystąpiły tylko raz w\n", + "korpusie — tzw. *hapax legomena*), choć tych słów jest bardzo dużo.\n", + "\n", + "**Zagadka**: 50000 najczęstszych słów (1,9% **typów**) pokrywa jaki odsetek **wystąpień**?\n", + "\n", + "Rozkład normalny w języku nie jest… normalny — nie spotkamy się z nim\n", + "badając języki. W tekstach dominują „skrzywione” rozkłady z długimi,\n", + "„chudymi” ogonami.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "! xzcat petite-difference-challenge2/train/in.tsv.xz | perl -C -ne 'print \"$&\\n\" while/\\p{L}+/g;' | sort | uniq -c | sort -k 1rn | cut -f 1 > freqs.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'word-distribution.png'" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt\n", + "import re\n", + "from math import log\n", + "\n", + "freqs = []\n", + "\n", + "with open('freqs.txt', 'r') as fh:\n", + " for line in fh:\n", + " m = re.match(r'\\s*(\\d+)', line)\n", + " if m:\n", + " freqs.append(int(m.group(1)))\n", + "\n", + "plt.plot(range(len(freqs)), freqs)\n", + "fname = 'word-distribution.png'\n", + "plt.savefig(fname)\n", + "fname" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[[file:# Out[25]:\n", + "\n", + " 'word-distribution.png'\n", + "\n", + "![img](./obipy-resources/c0TrCn.png)]]\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lematyzacja\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lematyzacja wydaje się dobrym pomysłem, zwłaszcza dla języków dla bogatej fleksji:\n", + "\n", + "- znacznie redukujemy słownik,\n", + "- formy fleksyjne tego samego wyrazu są traktowane tak samo (co wydaje się słuszne).\n", + "\n", + "W praktyce współcześnie **nie** stosuje się lematyzacji (w połączeniu z\n", + "metodami opartymi na sieciach neuronowych):\n", + "\n", + "- lematyzacja wymaga wiedzy językowej (reguł lub słownika),\n", + " wytworzenie takiej wiedzy może być kosztowne, obecnie preferowane\n", + " są metody niezależne od języka;\n", + "- tracimy pewną informację niesioną przez formę fleksyjną (co w szczególnych\n", + " przypadkach może być niefortunne, np. *aspiracja* i *aspiracje*);\n", + "- lematyzacja nie jest trywialnym problemem ze względu na niejednoznaczności\n", + " (*Lekarzu, lecz się sam*);\n", + "- niektóre niejednoznaczności są seryjne, wybór lematu może być arbitralny,\n", + " np. czy *posiadanie*, *gotowanie*, *skakanie* to rzeczowniki czy czasowniki?\n", + " a *urządzenie*, *mieszkanie*?\n", + "- zazwyczaj sieci neuronowe (czy nawet prostsze modele typu Word2vec)\n", + " są w stanie nauczyć się rekonstruowania zależności między formami fleksyjnymi\n", + " (i więcej: błędnych form, błędów ortograficznych, form archaicznych itd.)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zejście na poziom znaków\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Skoro słownik wyrazów jest zbyt duży, to może zejść na poziom znaków?\n", + "\n", + "- pojedynczy znak alfabetu wprawdzie nic nie znaczy (co znaczy *h*?)\n", + "\n", + "- … ale rozmiar wejścia przy kodowaniu gorącą jedynką\n", + " dramatycznie się zmniejsza\n", + "\n", + "- może działać, jeśli dodać wielowarstwową sieć\n", + " neuronową\n", + "\n", + "- … ale może być bardzo kosztowne obliczeniowo\n", + "\n", + "A może coś pośredniego między znakami a wyrazami?\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### BPE\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ani znaki, ani wyrazy — coś pomiędzy: jednostki podwyrazowe (*subword\n", + "units*). Moglibyśmy np. dzielić wyraz *superkomputera* na dwie\n", + "jednostki *super/+/komputera*, a może nawet trzy: *super/+/komputer/+/a*?\n", + "\n", + "Najpopularniejszy algorytm podziału na jednostki podwyrazowe to BPE\n", + "(*byte-pair encoding*), zainspirowany algorytmami kompresji danych.\n", + "Lista jednostek jest automatycznie indukowana na podstawie tekstu (nie\n", + "potrzeba żadnej wiedzy o języku!). Ich liczba musi być natomiast z góry\n", + "określona.\n", + "\n", + "W kroku początkowym zaznaczamy końce wyrazów (tokenów), robimy to po\n", + "to, żeby jednostki podwyrazowe nie przekraczały granic wyrazów.\n", + "\n", + "Następnie wykonujemy tyle kroków iteracji, ile wynosi rozmiar zadanego\n", + "słownika. W każdym kroku szukamy najczęstszego bigramu, od tego\n", + "momentu traktujemy go jako całostkę (wkładamy go do „pudełka”).\n", + "\n", + "![img](./bpe.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Implementacja w Pythonie\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['e$', 'to', 'to$', 'be$', 't$', 'th', 'or', 'or$', 'no', 'not$']" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from collections import Counter\n", + "\n", + "def replace_bigram(l, b, r):\n", + " i = 0\n", + " while i < len(l) - 1:\n", + " if (l[i], l[i+1]) == b:\n", + " l[i:i+2] = [r]\n", + " i += 1\n", + " return l\n", + "\n", + "def learn_bpe_vocab(d, max_vocab_size):\n", + " d = list(d.replace(' ', '$') + '$')\n", + "\n", + " vocab = []\n", + "\n", + " for ix in range(0, max_vocab_size):\n", + " bigrams = [(d[i], d[i+1]) for i in range(0, len(d) - 1) if d[i][-1] != '$']\n", + " selected_bigram = Counter(bigrams).most_common(1)[0][0]\n", + "\n", + " new_subword = selected_bigram[0] + selected_bigram[1]\n", + " d = replace_bigram(d, selected_bigram, new_subword)\n", + "\n", + " vocab.append(new_subword)\n", + "\n", + " return vocab\n", + "\n", + "vocab1 = learn_bpe_vocab('to be or not to be that is the question', 10)\n", + "vocab1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Słownik jednostek podwyrazowych możemy zastosować do dowolnego tekstu, np. do tekstu,\n", + "na którym słownik był wyuczony:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'to$ b e$ or$ no t$ to$ b e$ th a t$ i s $ th e$ q u e s t i o n $'" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def apply_bpe_vocab(vocab, d):\n", + " d = list(d.replace(' ', '$') + '$')\n", + " vocab_set = set(vocab)\n", + "\n", + " ix = 0\n", + " while ix < len(d) - 1:\n", + " bigram = d[ix] + d[ix+1]\n", + " if bigram in vocab_set:\n", + " d[ix:ix+2] = [bigram]\n", + " else:\n", + " ix += 1\n", + "\n", + " return d\n", + "\n", + "' '.join(apply_bpe_vocab(vocab1, 'to be or not to be that is the question'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Zauważmy, że oprócz jednostek podwyrazowych zostały izolowane litery,\n", + "zazwyczaj dodajemy je do słownika. (I zazwyczaj, słownik jest trochę\n", + "większy niż wartość podana jako parametr przy uczeniu BPE — jest\n", + "większy o znaki i specjalne tokeny typu `UNK`, `BOS`, `EOS`, `PAD`.)\n", + "\n", + "**Pytanie**: Jaki problem może pojawić przy zastosowaniu BPE dla tekstu,\n", + "gdzie pojawiają się chińskie znaki? Jak można sobie z nim poradzić?\n", + "\n", + "Słownik jednostek podwyrazowych można stosować dla dowolnego tekstu:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'to m $ w i l l $ b e$ th e$ b e s t$'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "' '.join(apply_bpe_vocab(vocab1, 'tom will be the best'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Jak można zauważyć algorytm BPE daje dwa rodzaje jednostek podwyrazowych:\n", + "\n", + "- jednostki, które mogą doklejane na początku wyrazu;\n", + "- jednostki, które stanowią koniec wyrazu, w szczególności są całym wyrazem.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Gotowa implementacja\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Po raz pierwszy BPE użyto do neuronowego tłumaczenia maszynowego.\n", + "Użyjmy modułu autorstwa Rica Sennricha ([https://github.com/rsennrich/subword-nmt](https://github.com/rsennrich/subword-nmt)).\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "! pip install subword-nmt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wyindukujmy słownik dla zbioru uczącego zadania identyfikacji płci\n", + "autora tekstu:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "! xzcat petite-difference-challenge2/train/in.tsv.xz | perl -C -ne 'print \"$&\\n\" while/\\p{L}+/g;' | python -m subword_nmt.learn_bpe -s 50000 -v > bpe_vocab.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Procedura trwa kilka minut, trzeba uzbroić się w cierpliwość (ale wypisywanie bigramów przyspieszy!).\n", + "\n", + " pair 0: n i -> ni (frequency 17625075)\n", + " pair 1: i e -> ie (frequency 11471590)\n", + " pair 2: c z -> cz (frequency 9143490)\n", + " pair 3: ni e -> nie (frequency 7901783)\n", + " pair 4: p o -> po (frequency 7790826)\n", + " pair 5: r z -> rz (frequency 7542046)\n", + " pair 6: s t -> st (frequency 7269069)\n", + " pair 7: e m -> em (frequency 7207280)\n", + " pair 8: d z -> dz (frequency 6860931)\n", + " pair 9: s z -> sz (frequency 6609907)\n", + " pair 10: r a -> ra (frequency 6601618)\n", + " pair 11: o w -> ow (frequency 6395963)\n", + " pair 12: i e -> ie (frequency 5906869)\n", + " pair 13: n a -> na (frequency 5300380)\n", + " pair 14: r o -> ro (frequency 5181363)\n", + " pair 15: n a -> na (frequency 5125807)\n", + " pair 16: a ł -> ał (frequency 4786696)\n", + " pair 17: j e -> je (frequency 4599579)\n", + " pair 18: s i -> si (frequency 4300984)\n", + " pair 19: a l -> al (frequency 4276823)\n", + " pair 20: t e -> te (frequency 4033344)\n", + " pair 21: w i -> wi (frequency 3939063)\n", + " pair 22: c h -> ch (frequency 3919410)\n", + " pair 23: c h -> ch (frequency 3661410)\n", + " pair 24: k o -> ko (frequency 3629840)\n", + " pair 25: z a -> za (frequency 3625424)\n", + " pair 26: t a -> ta (frequency 3570094)\n", + " pair 27: p rz -> prz (frequency 3494551)\n", + " pair 28: g o -> go (frequency 3279997)\n", + " pair 29: a r -> ar (frequency 3081492)\n", + " pair 30: si ę -> się (frequency 2973681)\n", + " ...\n", + " pair 49970: brz mieniu -> brzmieniu (frequency 483)\n", + " pair 49971: bieżą cych -> bieżących (frequency 483)\n", + " pair 49972: biegu nkę -> biegunkę (frequency 483)\n", + " pair 49973: ban kowości -> bankowości (frequency 483)\n", + " pair 49974: ba ku -> baku (frequency 483)\n", + " pair 49975: ba cznie -> bacznie (frequency 483)\n", + " pair 49976: Przypad kowo -> Przypadkowo (frequency 483)\n", + " pair 49977: MA Ł -> MAŁ (frequency 483)\n", + " pair 49978: Lep pera -> Leppera (frequency 483)\n", + " pair 49979: Ko za -> Koza (frequency 483)\n", + " pair 49980: Jak byś -> Jakbyś (frequency 483)\n", + " pair 49981: Geni alne -> Genialne (frequency 483)\n", + " pair 49982: Że nada -> Żenada (frequency 482)\n", + " pair 49983: ń czykiem -> ńczykiem (frequency 482)\n", + " pair 49984: zwie ń -> zwień (frequency 482)\n", + " pair 49985: zost ałaś -> zostałaś (frequency 482)\n", + " pair 49986: zni szczona -> zniszczona (frequency 482)\n", + " pair 49987: ze stawi -> zestawi (frequency 482)\n", + " pair 49988: za sób -> zasób (frequency 482)\n", + " pair 49989: węd rówkę -> wędrówkę (frequency 482)\n", + " pair 49990: wysko czyła -> wyskoczyła (frequency 482)\n", + " pair 49991: wyle czenia -> wyleczenia (frequency 482)\n", + " pair 49992: wychowaw cze -> wychowawcze (frequency 482)\n", + " pair 49993: w t -> wt (frequency 482)\n", + " pair 49994: un da -> unda (frequency 482)\n", + " pair 49995: udzie lałem -> udzielałem (frequency 482)\n", + " pair 49996: tę czy -> tęczy (frequency 482)\n", + " pair 49997: tro sce -> trosce (frequency 482)\n", + " pair 49998: słusz ności -> słuszności (frequency 482)\n", + " pair 49999: su me -> sume (frequency 482\n", + "\n", + "Zastosujmy teraz wyindukowany słownik BPE dla jakiegoś rzeczywistego tekstu.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cier@@ piałem na straszne la@@ gi kilkanaście sekund lub dłużej czarnego ekranu przy próbie przełą@@ czenia się uruchomienia prawie każdej aplikacji Dodatkowo telefon mi się wyłą@@ czał czasem bez powodu sam z siebie albo rese@@ tował Ostatnio nawet przeglądarka zaczęła się często zawie@@ szać i Android proponował wymu@@ szone zamknięcie Do tego te problemy z połączeniem do komputera przez USB " + ] + } + ], + "source": [ + "! echo 'Cierpiałem na straszne lagi – kilkanaście sekund lub dłużej czarnego ekranu przy próbie przełączenia się / uruchomienia prawie każdej aplikacji. Dodatkowo telefon mi się wyłączał czasem bez powodu – sam z siebie, albo resetował. Ostatnio nawet przeglądarka zaczęła się często zawieszać i Android proponował wymuszone zamknięcie. Do tego te problemy z połączeniem do komputera przez USB.' | perl -C -ne 'print \"$& \" while/\\p{L}+/g;' | python -m subword_nmt.apply_bpe -c bpe_vocab.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ta konkretna implementacja zaznacza za pomocą sekwencji ~@@ ~ koniec jednostki podwyrazowej.\n", + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + }, + "org": null + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/wyk/12_bpe.org b/wyk/12_bpe.org index 9829c85..17adf4e 100644 --- a/wyk/12_bpe.org +++ b/wyk/12_bpe.org @@ -88,7 +88,7 @@ nie pokryje on sporej części tekstów przetwarzanych w czasie inferencji. Zobaczmy, ilu wyrazów ze zbioru deweloperskiego nie będzie w słowniku. #+BEGIN_SRC ipython :session mysession :exports both :results raw drawer -! cat petite-difference-challenge2/dev-0/in.tsv.xz | perl -C -ne 'print "$&\n" while/\p{L}+/g;' | sort -u | comm vocab.txt - -13 | wc -l +! cat petite-difference-challenge2/dev-0/in.tsv | perl -C -ne 'print "$&\n" while/\p{L}+/g;' | sort -u | comm vocab.txt - -13 | wc -l #+END_SRC Takie wyrazy nazywamy wyrazami *OOV* (/out-of-vocabulary/). @@ -112,7 +112,7 @@ Daje to lepszy efekt niż można się spodziewać. Odrzucamy w ten sposób tylko bardzo rzadkie słowa (albo takie, które wystąpiły tylko raz w korpusie — tzw. /hapax legomena/), choć tych słów jest bardzo dużo. -*Zagadka*: 50000 najczęstszych słów (1,9\% *typów*) pokrywa jaki odsetek *wystąpień*? +*Zagadka*: 50000 najczęstszych słów (1,9% *typów*) pokrywa jaki odsetek *wystąpień*? Rozkład normalny w języku nie jest… normalny — nie spotkamy się z nim badając języki. W tekstach dominują „skrzywione” rozkłady z długimi, diff --git a/wyk/13_generative_approach.ipynb b/wyk/13_generative_approach.ipynb new file mode 100644 index 0000000..11c1953 --- /dev/null +++ b/wyk/13_generative_approach.ipynb @@ -0,0 +1 @@ +{"cells":[{"cell_type":"markdown","metadata":{},"source":["## Ekstrakcja informacji a podejście generatywne\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Podejście generatywne\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Do tej pory zadanie ekstrakcji informacji traktowaliśmy jako zadanie etykietowania sekwencji, tzn. uczyliśmy system zaznaczać tokeny składające się na ekstrahowane informacje.\n\n![img](./ie-seqlab.png)\n\nMożliwe jest inne podeście, **generatywne**, w którym podchodzimy do problemu ekstrakcji informacji jak do swego rodzaju **tłumaczenia maszynowego** — „tłumaczymy” tekst (wraz z pytaniem lub etykietą) na informację.\n\n![img](./ie-gener.png)\n\nTo podejście może się wydawać trudniejsze niż etykietowanie sekwencji, ale wystarczająco zaawansowanej architekturze sieci, jest wykonalne.\n\nZalety:\n\n- informacja nie musi być dosłownie zapisana w tekście, ekstraktor może nauczyć się również normalizacji czy parafrazowania,\n- nie wprowadzamy wielu kroków przetwarzania (gdzie błędy mogą się\n namnażać), system działa na zasadzie *end-to-end*.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### Atencja\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Pierwsze systemu neuronowego tłumaczenia maszynowego używały siecie LSTM. Dopiero jednak dodanie tzw. atencji (*attention*) umożliwiło duży przeskok jakościowy. Najpierw atencję dodano do sieci rekurencyjnych, później powstały sieci oparte *wyłącznie* na atencji — modele Transformer.\n\nIdea atencji polega na tym, że sieć może kierować selektywnie „snop” uwagi na wyrazy na wejściu lub do tej pory wygenerowane wyrazy.\n\nMechanizm atencji korzysta z:\n\n- z poprzedniego stanu sieci $\\vec{s^{k-1}}$ (to jest „miejsce”, z którego „kierujemy” atencję),\n- z wektora reprezentującego słowo $\\vec{v}(t_i)$ (to jest „miejsce”, na które kierujemy atencję), gdzie\n $\\vec{v}(t_i)$ to reprezentacja wektorowa wyrazu $t_i$ (statyczny embedding lub reprezentacja wektorowa\n z poprzedniej warstwy dla sieci wielowarstwowej),\n\naby wytworzyć wektor kontekstu $\\vec{\\xi^k}$ (który z kolei będzie w jakiś sposób wnosił wkład do wyliczenia nowej wartości stanu $\\vec{s^k}$ lub wyjścia $y^k$.\n\nNajpierw wyliczymy skalarne wartości atencji, tzn. liczby, które będą sygnalizowały, jak bardzo wektor $\\vec{v}(t_i)$ „pasuje” do $\\vec{s^{k-1}}$, w najprostszej wersji można po prostu skorzystać z iloczynu skalarnego (o ile $n=m$),\n\n$$a(\\vec{s^{k-1}}, \\vec{v}(t_i)) = \\vec{s^{k-1}}\\vec{v}(t_i).$$\n\n**Pytanie**: co jeśli $n$ nie jest równe $m$, tzn. rozmiar embeddingu nie jest równy rozmiarowi wektora stanu?\n\nW przypadku sieci LSTM korzysta się częściej z bardziej skomplikowanego wzoru zawierającego dodatkowe wyuczalne wagi:\n\n$$a(\\vec{s^{k-1}}, \\vec{v}(t_i)) = \\vec{w_a}\\operatorname{tanh}(W_a\\vec{s^{k-1}} + U_a\\vec{v}(t_i))$$\n\n**Pytanie**: jakie rozmiary mają macierze $W_a$, $U_a$ i wektor $w_a$?\n\nPowtórzmy, że wartości $a$ są wartościami skalarnymi, natomiast nie są one znormalizowane (nie sumują się do jedynki), normalizujemy je używając schematu podobnego do softmaxa:\n\n$$\\alpha_{i} = \\frac{e^{a(\\vec{s^{k-1}}, \\vec{v}(t_i))}}{\\sum_j e^{a(\\vec{s^{k-1}}, \\vec{v}(t_j))}}$$\n\nWektor kontekstu $\\vec{\\xi^k}$ będzie po prostu średnią ważoną wektorowych reprezentacji słów:\n\n$$\\vec{\\xi^k} = \\sum_i \\alpha_i\\vec{v}(t_i)$$\n\n**Pytanie**: zasadniczo atencja jest środkiem do celu (żeby sieć się sprawniej uczyła), czy można atencja sama w sobie może być do czegoś przydatna?\n\n"]}],"metadata":{"org":null,"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.5.2"}},"nbformat":4,"nbformat_minor":0} \ No newline at end of file diff --git a/wyk/13_generative_approach.org b/wyk/13_generative_approach.org new file mode 100644 index 0000000..3d0885b --- /dev/null +++ b/wyk/13_generative_approach.org @@ -0,0 +1,55 @@ +* Ekstrakcja informacji a podejście generatywne +** Podejście generatywne + +Do tej pory zadanie ekstrakcji informacji traktowaliśmy jako zadanie etykietowania sekwencji, tzn. uczyliśmy system zaznaczać tokeny składające się na ekstrahowane informacje. + +[[./ie-seqlab.png]] + +Możliwe jest inne podeście, *generatywne*, w którym podchodzimy do problemu ekstrakcji informacji jak do swego rodzaju *tłumaczenia maszynowego* — „tłumaczymy” tekst (wraz z pytaniem lub etykietą) na informację. + +[[./ie-gener.png]] + +To podejście może się wydawać trudniejsze niż etykietowanie sekwencji, ale wystarczająco zaawansowanej architekturze sieci, jest wykonalne. + +Zalety: + +- informacja nie musi być dosłownie zapisana w tekście, ekstraktor może nauczyć się również normalizacji czy parafrazowania, +- nie wprowadzamy wielu kroków przetwarzania (gdzie błędy mogą się + namnażać), system działa na zasadzie /end-to-end/. + +** Atencja + +Pierwsze systemu neuronowego tłumaczenia maszynowego używały siecie LSTM. Dopiero jednak dodanie tzw. atencji (/attention/) umożliwiło duży przeskok jakościowy. Najpierw atencję dodano do sieci rekurencyjnych, później powstały sieci oparte /wyłącznie/ na atencji — modele Transformer. + +Idea atencji polega na tym, że sieć może kierować selektywnie „snop” uwagi na wyrazy na wejściu lub do tej pory wygenerowane wyrazy. + +Mechanizm atencji korzysta z: + +- z poprzedniego stanu sieci $\vec{s^{k-1}}$ (to jest „miejsce”, z którego „kierujemy” atencję), +- z wektora reprezentującego słowo $\vec{v}(t_i)$ (to jest „miejsce”, na które kierujemy atencję), gdzie + $\vec{v}(t_i)$ to reprezentacja wektorowa wyrazu $t_i$ (statyczny embedding lub reprezentacja wektorowa + z poprzedniej warstwy dla sieci wielowarstwowej), + +aby wytworzyć wektor kontekstu $\vec{\xi^k}$ (który z kolei będzie w jakiś sposób wnosił wkład do wyliczenia nowej wartości stanu $\vec{s^k}$ lub wyjścia $y^k$. + +Najpierw wyliczymy skalarne wartości atencji, tzn. liczby, które będą sygnalizowały, jak bardzo wektor $\vec{v}(t_i)$ „pasuje” do $\vec{s^{k-1}}$, w najprostszej wersji można po prostu skorzystać z iloczynu skalarnego (o ile $n=m$), + +$$a(\vec{s^{k-1}}, \vec{v}(t_i)) = \vec{s^{k-1}}\vec{v}(t_i).$$ + +*Pytanie*: co jeśli $n$ nie jest równe $m$, tzn. rozmiar embeddingu nie jest równy rozmiarowi wektora stanu? + +W przypadku sieci LSTM korzysta się częściej z bardziej skomplikowanego wzoru zawierającego dodatkowe wyuczalne wagi: + +$$a(\vec{s^{k-1}}, \vec{v}(t_i)) = \vec{w_a}\operatorname{tanh}(W_a\vec{s^{k-1}} + U_a\vec{v}(t_i))$$ + +*Pytanie*: jakie rozmiary mają macierze $W_a$, $U_a$ i wektor $w_a$? + +Powtórzmy, że wartości $a$ są wartościami skalarnymi, natomiast nie są one znormalizowane (nie sumują się do jedynki), normalizujemy je używając schematu podobnego do softmaxa: + +$$\alpha_{i} = \frac{e^{a(\vec{s^{k-1}}, \vec{v}(t_i))}}{\sum_j e^{a(\vec{s^{k-1}}, \vec{v}(t_j))}}$$ + +Wektor kontekstu $\vec{\xi^k}$ będzie po prostu średnią ważoną wektorowych reprezentacji słów: + +$$\vec{\xi^k} = \sum_i \alpha_i\vec{v}(t_i)$$ + +*Pytanie*: zasadniczo atencja jest środkiem do celu (żeby sieć się sprawniej uczyła), czy można atencja sama w sobie może być do czegoś przydatna? diff --git a/wyk/bpe.png b/wyk/bpe.png new file mode 100644 index 0000000..5e0e835 Binary files /dev/null and b/wyk/bpe.png differ diff --git a/wyk/ie-gener.drawio b/wyk/ie-gener.drawio new file mode 100644 index 0000000..7e34f99 --- /dev/null +++ b/wyk/ie-gener.drawio @@ -0,0 +1 @@ +3Vjbbts4EP0aAe2DF9bNiR9jO9lisVekQLF9Y8SxRJsSVYqKrHz9Di+SJctF0m6TtvGDRB2RM+QcnhnKXrjOD79KUmZ/CArcC+b04IUbLwiWkY9XDbQWiMPQAqlk1EL+EbhlD+DAuUNrRqEadVRCcMXKMZiIooBEjTAipWjG3baCj72WJIUJcJsQPkU/MKoyi14GF0f8HbA06zz7i6V9k5Ous1tJlREqmgEUXnvhWgqhbCs/rIHr2HVxseNuPvO2n5iEQj1lgPgrjt7/+du/G76THw8f5Wyxv545K/eE127BXrDgaG+V4atFqlsdUpWk0OtQrQvO4lOtJ7+6I8k+laIu6CwRXEgvvMJ+Mr17E8Sxp6e1xutJ++1xfOfoHRDKirTzh0uxLsfTQHg6t/LFJ/u7kJDr8JZVre/UGEOPTOmtl4Oyo3FjVrgxQdX6LS6wZBVLzDLnwJnrVQE1NjTI6ioX+lFBXhqbrEgYZbQutOlaXzi5Q/+6t+p8g9l0aUG0G84+1eSXxyM5iFswCleg4GC2gco5Aj42t4zztQ3ZphAF2CibpYSb+Pj0XpQIzDB84arJmIJbxLXVBjMEYuIe5JYbKWSMUigQM4SA3ql6VKWk2EPnywvCufn100QDOL3P6sDv1YVZCQRSIVvs0g24dIJ0GclfuufmqO8gclg20rYDicspaW/7KDtsOOV9gQqDiQoV7CvNbAM7bx17y1XCRNM+gaRx6BxNZ5jDHZJi4DcJRg0QX+mYMsx7V+5FjtRoN2cpHNP1LUjxHyflHCfBc1ESnkmMJ8HHhF7q5pbD4UqXGgwFFNQ1NwknFSp9TI81AnRSdB4N1CAQ8ZlAdJgEThS7H5s/Fx3n4W/BTFZxPERRPOIBpTc2UYlaJuBGDavNiaHYf8SQIjIFNTFkyOqX/fX8RRP+tKIk2Sc7nSBNlnwgFaEPDEymtymRdfkQiZwpMcPbIFuyL8iWP6kQo8WJEC++sxCXEyK7SquLXV19XeH6llF/1moVh2M++kAP+Fi+JB9doh4Q0rR9kYJOLXey08qbprXSy0RDCjDHma2QOUl28Pb1Cik+PWYspsT1Ve9lmDtX0yxblN13dP1Tm7MnVP3B0gtvpqwOsuJg8P8TI4et+oGlODk4Rk88OD4fo9MqV7aKFFqGN6DaPQNFXq/E/PkJIeF3rlXdmWeUGwfJrzUfdfZkb0ia53XF9A0f1pF3eWE84PLb5KHAoz9GQ1QKv6rsV+KO7PXqrJVByn2tBMfLk+J3+Xw5FB+P/8XYU+jxD63w+j8= \ No newline at end of file diff --git a/wyk/ie-gener.png b/wyk/ie-gener.png new file mode 100644 index 0000000..8b2dc9f Binary files /dev/null and b/wyk/ie-gener.png differ diff --git a/wyk/ie-seqlab.drawio b/wyk/ie-seqlab.drawio new file mode 100644 index 0000000..68b1b48 --- /dev/null +++ b/wyk/ie-seqlab.drawio @@ -0,0 +1 @@ +7Vhtk5MwEP41zOiHOhQKd/14bc+3Uet4zjj6LSVbyDUQDOEo/no3EEp5uempd+qc9kMbHpLd7PNkl6WWu4z3LyRJo7eCArccm+4td2U5znw2xW8NlDXguW4NhJLRGpq2wBX7Bga0DZozCllnohKCK5Z2wUAkCQSqgxEpRdGdthW86zUlIQyAq4DwIfqJURXV6Llz1uIvgYVR43nqz+s7MWkmm0iyiFBRHEHupeUupRCqHsX7JXDNXcNLve75LXcPG5OQqLssEGtv9vHd688rfi2/7L/Iib+7nBgrN4TnJmDL8TnaW0R4yw/1qEGylCQ6DlUacvyvud78YkOCXShFntBJILiQlnuB82S4eeJ4nqW3tcTv3vhpu75x9BIIZUnY+MNQapfdbSA83Fv62zf7RkiINb1plutfWhlDj0zpoxeDqlfjwczwYILK9V0MMGUZC6owbeDMzMqAVjY0yPIsFvpSQZxWNlkSMMponmjTuf7iZIP+9WzV+Ibq0IUJ0W44+5qTZ6eZPOLN6dDlKNhXx0DFHIEpDreM82VN2SoRCdQsV6G4K6+9+ihSBCZIn7soIqbgCnFttcAKgZi4AbnlVSpEjFJIEKsEAX1S9apMSbGDxpfluHb1OWwTDeD2bs2D6SG7sCqBQClkiVOaBecmIU1Fmvrmumjz25kZLOrktgGJqSnhwXabdjgwmfcDWegMslDBLtPKFnBtLT1rvgiYKMo7iNSlzsg0ohyekBCJXwXIGiC+0JwyrHsX5kaM0mg3oxJ25boPUaY9Uc6Gooxp4jyUJO5IYeyRjwU91cMth/2FftQgFZBQM1wFnGSY6V15aiNABw+dk0QdEeGNENFgEjhR7KZrfowd4+G9YFVVMTrMvK4OA4IzkcsAzKrjp03PkOecMKSIDEENDFViHcL+ef1mA/1AlTsGShQkYfB4M2nm/2WZ5P1vMR5Bi/EAQXvTkZj7rcwtOvU7nI3sq7MVVSjbOttaR0ssYAx0yO+gGPrHXxLrxEw2WTp6ba9Pz7nLmtswezFZrd+sP+Do1WG0PmKijqwb7TD+/z3fUVH0vDv0fP5Yzzd7qLLo/5sNxrl7Tw3G3P6zDcbZQL9Uikzp0lWUVGzKQHcZdtXI54+33Tif/WXtxnygS/+R8jNF7z5Zf9BKN+/nl+0N9Jj/Tj2aF7sjQYry8FILwwfYk6LUOSNJpFt1qHqTrZAxCa7h6eNNpPnZ6UfU4S35F5XDy/Z/x7ogtn/eupffAQ== \ No newline at end of file diff --git a/wyk/ie-seqlab.png b/wyk/ie-seqlab.png new file mode 100644 index 0000000..79bd0fe Binary files /dev/null and b/wyk/ie-seqlab.png differ diff --git a/wyk/rnn-seq.drawio b/wyk/rnn-seq.drawio new file mode 100644 index 0000000..431f885 --- /dev/null +++ b/wyk/rnn-seq.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/wyk/rnn-seq.png b/wyk/rnn-seq.png new file mode 100644 index 0000000..1d2c06d Binary files /dev/null and b/wyk/rnn-seq.png differ diff --git a/wyk/rnn.drawio b/wyk/rnn.drawio new file mode 100644 index 0000000..826eb1a --- /dev/null +++ b/wyk/rnn.drawio @@ -0,0 +1 @@ +5Vltj5s4EP41SO2HXcUYwuZjQ3J3H1pdpb3TtffNBRfcAI6M88L++hsH8w45qk2W7FbarDyPX7Bn5pkZjIHd+Pi7INvwE/dpZJgz/2jglWGaCwvBfwVkOYDmjpkjgWC+xirgkT1RDc40umM+TRsDJeeRZNsm6PEkoZ5sYEQIfmgO+86j5lO3JKAd4NEjURf9h/kyzNEH06nwPygLwuLJaL7Ie2JSDNZLpCHx+SGHTofDawO7gnOZt+KjSyOlvEIvuQZ+G+gtNyZoIsdM+Fu6u39ttrGyB2edrZxPf338cadX2ZNopw+sNyuzQgOC7xKfqkVmBl4eQibp45Z4qvcANgcslHEEEoKmXo4KSY+D+0Tl6cFtKI+pFBkM0ROwpU1fuAzW8qHSP9JnnYV13TsaJNrmQbl2pRZoaM38hJbmHaVQH7xEi1zIkAc8IdG6QpdNtVVjPnK+1cr6QaXMtMuTneRNVdIjk1/U9HtbS1/1Yqq9OtaFrBASOG5tkhK/FuspoZp2kop5+fnUoc4bDXTAd8KjZ3SlHUgSEVB5ZhzudwJBIyLZvrmPixvU7HF7C/6kYa83ebNjcvBo2bRQKgXfUJdHXACS8ETZ/TuLohZEIhYkIHqgTAr4UvGDQYz5oDti5vsnp+ljV9ORLkGwhybB8KJLMKuHX/ha9LJfC70uSBM8kiZoPiVPcIcnNP5GfZ8lAcCG7b6D3556hrPcG87q3Yk/7wF7fyaNoJdJIwjdm3bT0a2eTOI49/YL+nqRuKZxdlR39dLx/y+X1DNJLbFcP5c4r4IkzkAySYEMQIwNFFnO6q0nlaL6LLhmWvaopGJei2jIPmOWN5/jbXxj5ig5f/NJ/gZqaDQfG/icKQNfsc0axQ5EpPJADHMeKSJ9E9AKVCtiCeOqY+qywG7WBGZPTbB4yeIXLV4fMSYrCNDoisCekhgmfn02nS7YjbVpfjc1WbAbKvPgbSdlQUwGSorJA9xsXIC7Xubv6uRGyXBBp362r+qpnzmDR5fGtWatu9FZy2o5ifSsluHKbTzDlkMXZ3/eqPejken9et4/9BqS/QqvIe2rRmfcTePVrIFHfO/wdmJfeixN/A/qK5JSaUTSlHnPDzM+ScPyAUr4TCQYKzkh5gxdOL0OVEI1E9g9JiiwZwYsu/Uxp2PafP+dgNVZyGwvZI2LfGA9ktWGbdWA9MyGF/0bHtqX3YrId/b58e1z3KHGeGjkO75o2MbdsJ1uxZPhWsZiYbi2sXRpwiiMeIJfQlKZd22TLAZgA7GHUdXynkjKDwp8sxEL99uncWd8oZgFYvX5N7d19REdr/8D \ No newline at end of file diff --git a/wyk/rnn.png b/wyk/rnn.png new file mode 100644 index 0000000..c082f76 Binary files /dev/null and b/wyk/rnn.png differ diff --git a/wyk/word-distribution.png b/wyk/word-distribution.png new file mode 100644 index 0000000..413a646 Binary files /dev/null and b/wyk/word-distribution.png differ