From c33599c719d50100cc34ccd8f2e2be7ab648907c Mon Sep 17 00:00:00 2001 From: Filip Gralinski Date: Wed, 6 Jul 2022 09:07:35 +0200 Subject: [PATCH] Fix 05 --- wyk/04_Ngramowy_model.ipynb | 877 ------------------ wyk/05_Ngramowy_model.ipynb | 19 + ...ramowy_model.org => 05_Ngramowy_model.org} | 4 +- .../tabelka.pdf | Bin .../tabelka.png | Bin 5 files changed, 21 insertions(+), 879 deletions(-) delete mode 100644 wyk/04_Ngramowy_model.ipynb create mode 100644 wyk/05_Ngramowy_model.ipynb rename wyk/{04_Ngramowy_model.org => 05_Ngramowy_model.org} (98%) rename wyk/{04_Ngramowy_model => 05_Ngramowy_model}/tabelka.pdf (100%) rename wyk/{04_Ngramowy_model => 05_Ngramowy_model}/tabelka.png (100%) diff --git a/wyk/04_Ngramowy_model.ipynb b/wyk/04_Ngramowy_model.ipynb deleted file mode 100644 index 2c5f4f8..0000000 --- a/wyk/04_Ngramowy_model.ipynb +++ /dev/null @@ -1,877 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Modele języka i ich zastosowania\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Przypomnienie\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Przypomnijmy, że model języka zwraca prawdopodobieństwo dla danego\n", - "ciągu symboli (tokenów, wyrazów itp.) $w_1\\ldots w_N$ (o długości $N$):\n", - "\n", - "$$P_M(w_1\\ldots w_N) = ?$$\n", - "\n", - "W dalszym ciągu będziemy zakładali, że będziemy operować na wyrazach.\n", - "Zbiór wszystkich wyrazów nazywa się **słownikiem** (ang. *vocabulary*,\n", - "nie *dictionary!*), w literaturze dotyczącej modelowania języka\n", - "zazwyczaj oznacza się go literą $V$ (częściej niż $\\Sigma$).\n", - "Dale zakładamy, że słownik jest skończony.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Co jeszcze potrafi model języka?\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Przewidywanie kolejnego słowa\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "$$P_M(w_N|w_1\\ldots w_{N-1}) = \\frac{P_M(w_1\\dots w_{N-1}w_N*)}{P_M(w_1\\dots w_{n-1}*)} = \\frac{\\sum_{\\alpha \\in\n", - " \\Sigma^*}P_M(w_1\\dots w_N\\alpha)}{\\sum_{\\alpha\\in\\Sigma^*}P(w_1\\dots w_{n-1}\\alpha)}$$\n", - "\n", - "$P_M(w_N|w_1\\ldots w_{N-1})$ to właściwie skrót notacyjny, pełny zapis powinien mieć następujący kształt:\n", - "\n", - "$$P_M(X_N=w_N|X_1=w_1,\\ldots,X_{N-1}=w_{N-1}),$$\n", - "\n", - "gdzie $P_M(X_i=w)$ oznacza prawdopodobieństwo, że na $i$-tej pozycji wystąpi słowo $w$.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Odgadywanie słowa w luce\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "$$P_M(w_1\\dots w_{i-1}?w_{i+1}\\dots w_N) = \\operatorname{argmax}_w P_M(w_1\\ldots w_{i-1}ww_{i+1}\\dots w_N)$$\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Przykład dla autentycznego modelu języku\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Zobaczmy przykładowe zastosowania i wyniki dla modelu języku\n", - "wyuczonego na tekstach z II poł. XX w.\n", - "\n", - "![img](./04_Ngramowy_model/tabelka.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Do czego stosujemy model języka?\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Model języka sam w sobie nie jest zbyt użyteczny. To raczej środek do celu\n", - "niż cel sam w sobie.\n", - "\n", - "Model języka:\n", - "\n", - "- ma zastosowanie w kryptoanalizie\n", - " - Oxmynsxq mkx lo kmrsofon li cdenisxq sdc kvzrklodsm mrkbkmdobc kxn bozvkmsxq okmr yxo li dro 13dr voddob zvkmon pebdrob kvyxq sx dro kvzrklod.\n", - "- pomaga(ł) wybrać właściwe tłumaczenie w tłumaczeniu maszynowym\n", - " czy transkrypcję w systemach rozpoznawania mowy (ASR)\n", - " (zanim zaczęto używać do tego sieci neuronowych, gdzie nie\n", - " ma już wyraźnego rozróżnienia między modelem tłumaczenia\n", - " czy modelem akustycznym a modelem języka),\n", - "- pomaga znaleźć „podejrzane” miejsca w tekście\n", - " (korekta pisowni/gramatyki),\n", - "- może być stosowany jako klasyfikator (potrzeba wtedy więcej niż jednego modelu,\n", - " np. model języka spamów kontra model języka niespamów),\n", - "- może być stosowany w kompresji danych,\n", - "- bardzo dobry model języka **musi** mieć **w środku** bardzo dobrą **wiedzę**\n", - " o języku i o świecie, można wziąć **„wnętrzności”** modelu, nie dbając o prawdopodobieństwa\n", - " i użyć modelu w zupełnie innym celu.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### N-gramowy model języka\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Zawsze prawdziwe:\n", - "\n", - "$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)\\dots P_M(w_N|w_1\\dots w_{N-1}).$$\n", - "\n", - "Można aproksymować prawdopodobieństwa używając $n$-gramów:\n", - "\n", - "$$P_M(w_1\\dots w_N) \\approx P_M(w_1)\\dots P_M(w_i|w_{i-n+1}\\dots w_{i-1})\\dots P_M(w_N|w_{N-n+1}\\dots w_{N-1}).$$\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Model trigramowy\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dla $n=3$:\n", - "\n", - "$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_1w_2)\\dots P_M(w_i|w_{i-2}w_{i-1})\\dots P_M(w_N|w_{N-2}w_{N-1}).$$\n", - "\n", - "Zauważmy, że model trigramowy oznacza modelowanie kolejnego wyrazu przy znajomości\n", - "2 (nie 3!) poprzedzających wyrazów (**razem** mamy 3 wyrazy).\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Model digramowy/bigramowy\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dla $n=2$:\n", - "\n", - "$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_2)\\dots P_M(w_i|w_{i-1})\\dots P_M(w_N|w_{N-1})$$\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Model unigramowy\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dla $n=1$ uzyskujemy przypadek szczególny:\n", - "\n", - "$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2)P_M(w_3)\\dots P_M(w_N) = \\prod_{i=1}^N P_M(w_i)$$\n", - "\n", - "Zauważmy, że w modelu unigramowym w ogóle nie bierzemy pod uwagę kolejności wyrazów.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Estymacja prawdopodobieństw\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dla $n$-gramowego modelu potrzebujmy estymować wartości:\n", - "\n", - "$$P_M(w_i|w_{i-n+1}\\dots w_{i-1}).$$\n", - "\n", - "Prawdopodobieństwa te estymujemy na podstawie jakiegoś **korpusu tekstów**\n", - "(możemy nazywać go również **zbiorem uczącym**).\n", - "\n", - "Najprostszy sposób:\n", - "\n", - "$$P_M(w_i|w_{i-n+1}\\dots w_{i-1}) = \\frac{\\# w_{i-n+1}\\dots w_{i-1}w_i}{\\# w_{i-n+1}\\dots w_{i-1}},$$\n", - "\n", - "gdzie $\\# w_1\\dots w_k$ oznacza liczbę wystąpień w korpusie.\n", - "\n", - "Na przykład, jeśli model $M$ zostanie wyuczony na tekście *do be do be do do*, wówczas\n", - "$P_M(\\mathit{be}|\\mathit{do})=\\frac{2}{3}$.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Ewaluacja modeli języka\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Jak już widzimy, możemy mieć różne modele języka. Nawet jeśli\n", - "pozostajemy tylko na gruncie najprostszych, $n$-gramowych modeli\n", - "języka, inne prawdopodobieństwa uzyskamy dla modelu digramowego, a\n", - "inny dla trigramowego. Jedne modele będą lepsze, inne — gorsze. Jak\n", - "obiektywnie odróżnić dobry model od złego? Innymi słowy, jak ewaluować\n", - "modele języka?\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Ewaluacja zewnętrzna i wewnętrzna\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "W ewaluacji zewnętrznej (ang. *extrinsic*) ewaluację modelu języka sprowadzamy\n", - "do ewaluacji większego systemu, którego częścią jest model języka, na przykład\n", - "systemu tłumaczenia maszynowego albo systemu ASR.\n", - "\n", - "Ewaluacja wewnętrzna (ang. *intrinsic*) polega na ewaluacji modelu języka jako takiego.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Podział zbioru\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Po pierwsze, jak zazwyczaj bywa w uczeniu maszynowym, powinniśmy\n", - "podzielić nasz zbiór danych. W modelowaniu języka zbiorem danych jest\n", - "zbiór tekstów w danym języku, czyli korpus języka.\n", - "Powinniśmy podzielić nasz korpus na część uczącą (*training set*) $C = \\{w_1\\ldots w_N\\}$ i testową\n", - "(*test set*) $C' = \\{w_1'\\ldots w_{N'}'\\}$.\n", - "\n", - "Warto też wydzielić osobny „deweloperski” zbiór testowy (*dev set*) —\n", - "do testowania na bieżąco, optymalizacji hiperparametrów itd. Zbiory\n", - "testowe nie muszą być bardzo duże, np. kilka tysięcy zdań może w zupełności wystarczyć.\n", - "\n", - "Tak podzielony korpus możemy traktować jako **wyzwanie modelowania języka**.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Przykład wyzwania modelowania języka\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Wyzwanie\n", - "[https://gonito.net/challenge/challenging-america-word-gap-prediction|Challenging America word-gap prediction](https://gonito.net/challenge/challenging-america-word-gap-prediction|Challenging America word-gap prediction)\n", - "to wyzwanie modelowania amerykańskiej odmiany języka angielskiego, używanej w gazetach w XIX w. i I poł. XX w.\n", - "\n", - " $ git clone git://gonito.net/challenging-america-word-gap-prediction\n", - " $ cd challenging-america-word-gap-prediction\n", - " $ xzcat train/in.tsv.xz | wc\n", - " 432022 123677147 836787912\n", - " $ xzcat dev-0/in.tsv.xz | wc\n", - " 10519 3076536 20650825\n", - " $ xzcat test-A/in.tsv.xz | wc\n", - " 7414 2105734 14268877\n", - "\n", - "Dodajmy, że poszczególne zbiory zawierają teksty z różnych gazet. Jest\n", - "to właściwe podejście, jeśli chcemy mierzyć rzeczywistą skuteczność modeli języka.\n", - "(Teksty z jednej gazety mogłyby być zbyt proste).\n", - "\n", - "Oto przykład tekstu z wyzwania:\n", - "\n", - " $ xzcat train/in.tsv.xz | head -n 1 | fold\n", - " 4e04702da929c78c52baf09c1851d3ff\tST\tChronAm\t1919.6041095573314\n", - " 30.47547\t-90.100911\tcame fiom the last place to this\\nplace, and thi\n", - " s place is Where We\\nWere, this is the first road I ever\\nwas on where you can r\n", - " ide elsewhere\\nfrom anywhere and be nowhere.\\nHe says, while this train stops ev\n", - " ery-\\nwhere, it never stops anywhere un-\\nless its somewhere. Well, I says,\\nI'm\n", - " glad to hear that, but, accord-\\ning to your figures, I left myself\\nwhere 1 wa\n", - " s, which is five miles near-\\ner to myself than I was when we\\nwere where we are\n", - " now.\\nWe have now reached Slidell.\\nThat's a fine place. The people\\ndown there\n", - " remind me of bananas-\\nthey come and go in bunches. 811-\\ndell used to be noted\n", - " for her tough\\npeople. Now she is noted for be,\\ntough steaks. Well, I certainl\n", - " y got\\none there. When the waiter brought\\nit in it was so small I thought. It\\n\n", - " was a crack in the plate. I skid,\\nwaiter what else have you got? +He\\nbrought m\n", - " e in two codfish and one\\nsmelt. I said, waiter have you got\\npigs feet? He said\n", - " no, rheumatism\\nmakes me walk that way. I sald,\\nhow is the pumpkin pie?\n", - " said\\nit's all squash. The best I could get\\nin that hotel was a soup sandwich.\\\n", - " nAfter the table battle the waiter and\\nI signed an armistice. I then went\\nover\n", - " to the hotel clerk and asked for\\na room. He said with or without a\\nbed? I sai\n", - " d, with a bed. He said,\\nI don't think I 'have' a bed long\\nenough for you. I sa\n", - " id, well, I'll\\naddtwo feettoitwhenIgetinit.\\nHe gave me a lovely room on the\\nt\n", - " op floor. It was one of those rooms\\nthat stands on each side. If you\\nhappen to\n", - " get up in the middle of\\nthe night you want to be sure and\\nget up in the middl\n", - " e of the room.\\nThat night I dreamt I was eating\\nflannel cakes. When I woke up\n", - " half\\nof the blanket was gone. I must\\nhave got up on the wrong side of the\\nbed\n", - " , for next morning I had an awful\\nheadache. I told the manager about\\nit. He sa\n", - " id, you have rheumatic\\npains. I said, no, I think it is on,\\nof those attic roo\n", - " m pains. I nad to\\ngetupat5a.m.inthemorningso\\nthey could use the sheet to set t\n", - " he\\nbreakfast table.\n", - "\n", - "Zauważmy, że mamy nie tylko tekst, lecz również metadane (czas i\n", - "współrzędne geograficzne). W modelowaniu języka można uwzględnić\n", - "również takie dodatkowe parametry (np. prawdopodobieństwa wystąpienia\n", - "słowa *koronawirus* wzrasta po roku 2019).\n", - "\n", - "Zauważmy również, że tekst zawiera błędy OCR-owe (np. *nad* zamiast\n", - "*had*). Czy w takim razie jest to sensowne wyzwanie modelowania\n", - "języka? Tak, w niektórych przypadkach możemy chcieć modelować tekst z\n", - "uwzględnieniem „zaszumień” wprowadzanych przez ludzi bądź komputery\n", - "(czy II prawo termodynamiki!).\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Co podlega ocenie?\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Ogólnie ocenie powinno podlegać prawdopodobieństwo $P_M(C')$, czyli\n", - "prawdopodobieństwo przypisane zbiorowi testowemu $C'$ przez model\n", - "(wyuczony na zbiorze $C$).\n", - "\n", - "Jeśli oceniamy przewidywania, które człowiek lub komputer czynią, to\n", - "im większe prawdopodobieństwo przypisane do tego, co miało miejsce,\n", - "tym lepiej. Zatem im wyższe $P_M(C')$, tym lepiej.\n", - "\n", - "Zazwyczaj będziemy rozbijali $P_M(C')$ na prawdopodobieństwa\n", - "przypisane do poszczególnych słów:\n", - "\n", - "$$P_M(w_1'\\dots w_{N'}') = P_M(w'_1)P_M(w'_2|w'_1)\\dots P_M(w'_{N'}|w'_1\\dots w'_{N'-1}) = \\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1}).$$\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Entropia krzyżowa\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Można powiedzieć, że dobry model języka „wnosi” informację o języku. Jeśli zarówno\n", - "nadawca i odbiorca tekstu mają do dyspozycji ten sam model języka…\n", - "\n", - "![img](./04_Ngramowy_model/lm-communication.drawio.png)\n", - "\n", - "… powinni być w stanie zaoszczędzić na długości komunikatu.\n", - "\n", - "W skrajnym przypadku, jeśli model jest pewny kolejnego słowa, tj.\n", - "$P_M(w'_i|w'_1\\ldots w'_{i-1}) = 1$, wówczas w $i$-tym kroku w ogóle\n", - "nic nie trzeba przesyłać przez kanał komunikacji. Taka sytuacja może\n", - "realnie wystąpić, na przykład: z prawdopodobieństwem zbliżonym do 1 po wyrazie\n", - "*Hong* wystąpi słowo *Kong*, a po wyrazie *przede* — wyraz *wszystkim*.\n", - "\n", - "Model języka może pomóc również w mniej skrajnym przypadkach, np.\n", - "jeżeli na danej pozycji w tekście model redukuje cały słownik do dwóch\n", - "wyrazów z prawdopodobieństwem 1/2, wówczas nadawca może zakodować tę\n", - "pozycję za pomocą jednego bitu.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Wzór na entropię krzyżową\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Przypomnijmy, że symbol o prawdopodobieństwie $p$ można zakodować za\n", - "pomocą (średnio) $-\\log_2(p)$ bitów, tak więc jeśli nadawca i odbiorca dysponują\n", - "modelem $M$, wówczas można przesłać cały zbiór testowy $C$ za pomocą następującej liczby bitów:\n", - "\n", - "$$-\\sum_{i=1}^{N'} log P_M(w'_i|w'_1\\ldots w'_{i-1}).$$\n", - "\n", - "Aby móc porównywać wyniki dla korpusów dla różnej długości, warto znormalizować\n", - "tę wartość, tzn. podzielić przez długość tekstu:\n", - "\n", - "$$H(M) = -\\frac{\\sum_{i=1}^{N'} log P_M(w'_i|w'_1\\ldots w'_{i-1})}{N'}.$$\n", - "\n", - "Tę wartość nazywamy **entropią krzyżową** modelu $M$. Entropia krzyżowa\n", - "mierzy naszą niewiedzę przy założeniu, że dysponujemy modelem $M$. Im niższa wartość\n", - "entropii krzyżowej, tym lepiej, im bowiem mniejsza nasza niewiedza,\n", - "tym lepiej.\n", - "\n", - "Entropią krzyżową jest często nazywaną funkcją **log loss**, zwłaszcza w\n", - "kontekście jej użycia jako funkcji straty przy uczeniu neuronowych modeli języka\n", - "(o których dowiemy się później).\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Wiarygodność\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Innym sposobem mierzenia jakości modelu języka jest odwołanie się do\n", - "**wiarygodności** (ang. *likelihood*). Wiarygodność to\n", - "prawdopodobieństwo przypisane zdarzeniom niejako „po fakcie”. Jak już\n", - "wspomnieliśmy, im wyższe prawdopodobieństwo (wiarygodność) przypisane\n", - "testowej części korpusu, tym lepiej. Innymi słowy, jako metrykę ewaluacji\n", - "używać będziemy prawdopodobieństwa:\n", - "\n", - "$$P_M(w_1'\\dots w_{N'}') = P_M(w'_1)P_M(w'_2|w'_1)\\dots P_M(w'_{N'}|w'_1\\dots w'_{N'-1}) = \\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1}),$$\n", - "\n", - "z tym, że znowu warto znormalizować to prawdopodobieństwo względem rozmiaru korpusu.\n", - "Ze względu na to, że prawdopodobieństwa przemnażamy, zamiast średniej arytmetycznej\n", - "lepiej użyć **średniej geometrycznej**:\n", - "\n", - "$$\\sqrt[N']{P_M(w_1'\\dots w_{N'}')} = \\sqrt[N']{\\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1})}.$$\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Interpretacja wiarygodności\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Co ciekawe, wiarygodność jest używana jako metryka ewaluacji modeli\n", - "języka rzadziej niż entropia krzyżowa (log loss), mimo tego, że wydaje\n", - "się nieco łatwiejsza do interpretacji dla człowieka. Otóż wiarygodność\n", - "to **średnia geometryczna prawdopodobieństw przypisanych przez model języka do słów, które rzeczywiście wystąpiły**.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Związek między wiarygodnością a entropią krzyżową\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Istnieje bardzo prosty związek między entropią krzyżową a wiarygodnością.\n", - "Otóż entropia krzyżowa to po prostu logarytm wiarygodności (z minusem):\n", - "\n", - "-$$\\log_2\\sqrt[N']{P_M(w_1'\\dots w_N')} = -\\frac{\\log_2\\prod_{i=1}^{N'} P_M(w'_i|w'_1\\ldots w'_{i-1})}{N'} = -\\frac{\\sum_{i=1}^{N'} \\log_2 P_M(w'_i|w'_1\\ldots w'_{i-1})}{N'}.$$\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### „log-proby”\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "W modelowaniu języka bardzo często używa się logarytmów prawdopodobieństw (z angielskiego skrótowo *log probs*),\n", - "zamiast wprost operować na prawdopodobieństwach:\n", - "\n", - "- dodawanie log probów jest tańsze obliczeniowo niż mnożenie prawdopodobieństw,\n", - "- bardzo małe prawdopodobieństwa znajdują się na granicy dokładności reprezentacji\n", - " liczb zmiennopozycyjnych, log proby są liczbami ujemnymi o „poręczniejszych”\n", - " rzędach wielkości.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Perplexity\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Tak naprawdę w literaturze przedmiotu na ogół używa się jeszcze innej metryki ewaluacji —\n", - "**perplexity**. Perplexity jest definiowane jako:\n", - "\n", - "$$\\operatorname{PP}(M) = 2^{H(M)}.$$\n", - "\n", - "Intuicyjnie można sobie wyobrazić, że perplexity to liczba możliwości\n", - "prognozowanych przez model z równym prawdopodobieństwem. Na przykład,\n", - "jeśli model przewiduje, że w danym miejscu tekstu może wystąpić z\n", - "równym prawdopodobieństwem jedno z 32 słów, wówczas (jeśli\n", - "rzeczywiście któreś z tych słów wystąpiło) entropia wynosi 5 bitów, a\n", - "perplexity — 32.\n", - "\n", - "Inaczej: perplexity to po prostu odwrotność wiarygodności:\n", - "\n", - "$$\\operatorname{PP}(M) = \\sqrt[N']{P_M(w_1'\\dots w_N')}.$$\n", - "\n", - "Perplexity zależy oczywiście od języka i modelu, ale typowe wartości\n", - "zazwyczaj zawierają się w przedziale 20-400.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Perplexity — przykład\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Wyuczmy model języka przy użyciu gotowego narzędzia [https://github.com/kpu/kenlm|KenLM](https://github.com/kpu/kenlm|KenLM).\n", - "KenLM to zaawansowane narzędzie do tworzenia n-gramowych modeli języka\n", - "(zaimplementowano w nim techniki wygładzania, które omówimy na kolejnym wykładzie).\n", - "\n", - "Wyuczmy na zbiorze uczącym wspomnianego wyzwania *Challenging America word-gap prediction*\n", - "dwa modele, jeden 3-gramowy, drugi 4-gramowy.\n", - "\n", - "Z powodu, który za chwilę stanie się jasny, teksty w zbiorze uczącym musimy sobie „poskładać” z kilku „kawałków”.\n", - "\n", - " $ cd train\n", - " $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | lmplz -o 3 --skip-symbols > model3.arpa\n", - " $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | lmplz -o 4 --skip-symbols > model4.arpa\n", - " $ cd ../dev-0\n", - " $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | query ../train/model3.arpa\n", - " Perplexity including OOVs:\t976.9905056314793\n", - " Perplexity excluding OOVs:\t616.5864921901557\n", - " OOVs:\t125276\n", - " Tokens:\t3452929\n", - " $ xzcat in.tsv.xz | paste expected.tsv - | perl -ne 'chomp;s/\\\\n/ /g;s// /g;@f=split/\\t/;print \"$f[7] $f[0] $f[8]\\n\"' | query ../train/model4.arpa\n", - " Perplexity including OOVs:\t888.698932611321\n", - " Perplexity excluding OOVs:\t559.1231510292068\n", - " OOVs:\t125276\n", - " Tokens:\t3452929\n", - "\n", - "Jak widać model 4-gramowy jest lepszy (ma niższe perplexity) niż model 3-gramowy, przynajmniej\n", - "jeśli wierzyć raportowi programu KenLM.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Entropia krzyżowa, wiarygodność i perplexity — podsumowanie\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Trzy omawiane metryki ewaluacji modeli języka (entropia krzyżowa,\n", - "wiarygodność i perplexity) są ze sobą ściśle związane, w gruncie\n", - "rzeczy to po prostu jedna miara.\n", - "\n", - "| Metryka|Kierunek|Najlepsza wartość|Najgorsza wartość|\n", - "|---|---|---|---|\n", - "| entropia krzyżowa|im mniej, tym lepiej|0|$\\infty$|\n", - "| wiarygodność|im więcej, tym lepiej|1|0|\n", - "| perplexity|im mniej, tym lepiej|1|$\\infty$|\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Uwaga na zerowe prawdopodobieństwa\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Entropia krzyżowa, wiarygodność czy perplexity są bardzo czułe na zbyt\n", - "dużą pewność siebie. Wystarczy, że dla **jednej** pozycji w zbiorze\n", - "przypiszemy zerowe prawdopodobieństwo, wówczas wszystko „eksploduje”.\n", - "Perplexity i entropia krzyżowa „wybuchają” do nieskończoności,\n", - "wiarygodność spada do zera — bez względu na to, jak dobre są\n", - "przewidywania dotyczące innych pozycji w tekście!\n", - "\n", - "W przypadku wiarygodności wiąże się to z tym, że wiarygodność\n", - "definiujemy jako iloczyn prawdopodobieństwa, oczywiście wystarczy, że\n", - "jedna liczba w iloczynie była zerem, żeby iloczyn przyjął wartość\n", - "zero. Co więcej, nawet jeśli pominiemy taki skrajny przypadek, to\n", - "średnia geometryczna „ciągnie” w dół, bardzo niska wartość\n", - "prawdopodobieństwa przypisana do rzeczywistego słowa może drastycznie obniżyć\n", - "wartość wiarygodności (i podwyższyć perplexity).\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Słowa spoza słownika\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Prostym sposobem przeciwdziałania zerowaniu/wybuchaniu metryk jest\n", - "przypisywanie każdemu możliwemu słowu przynajmniej niskiego\n", - "prawdopodobieństwa $\\epsilon$. Niestety, zawsze może pojawić się\n", - "słowa, którego nie było w zbiorze uczącym — **słowo spoza słownika**\n", - "(*out-of-vocabulary word*, *OOV*). W takim przypadku znowu może\n", - "pojawić się zerowy/nieskończony wynik.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Ewaluacja modeli języka w warunkach konkursu\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Jeśli używać tradycyjnych metryk ewaluacji modeli języka (perplexity\n", - "czy wiarygodność), bardzo łatwo można „oszukać” — wystarczy\n", - "zaraportować prawdopodobieństwo 1! Oczywiście to absurd, bo albo\n", - "wszystkim innym tekstom przypisujemy prawdopodobieństwo 0, albo —\n", - "jeśli „oszukańczy” system każdemu innemu tekstowi przypisze\n", - "prawdopodobieństwo 1 — nie mamy do czynienia z poprawnym rozkładem\n", - "prawdopodobieństwa.\n", - "\n", - "Co gorsza, nawet jeśli wykluczymy scenariusz świadomego oszustwa,\n", - "łatwo *samego siebie* wprowadzić w błąd. Na przykład przez pomyłkę\n", - "można zwracać zawyżone prawdopodobieństwo (powiedzmy przemnożone przez 2).\n", - "\n", - "Te problemy stają się szczególnie dokuczliwe, jeśli organizujemy\n", - "wyzwanie, *konkurs* modelowania języka, gdzie chcemy w sposób\n", - "obiektywny porównywać różne modele języka, tak aby uniknąć celowego\n", - "bądź nieświadomego zawyżania wyników.\n", - "\n", - "Przedstawimy teraz, w jaki sposób poradzono sobie z tym problemem\n", - "w wyzwaniu *Challenging America word-gap prediction*\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Odgadywanie słowa w luce\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Po pierwsze, jaka sama nazwa wskazuje, w wyzwaniu *Challenging America\n", - "word-gap prediction* zamiast zwracania prawdopodobieństwa dla całego\n", - "tekstu oczekuje się podania rozkładu prawdopodobieństwa dla brakującego słowa.\n", - "\n", - "Mianowicie, w każdym wierszu wejściu (plik `in.tsv.xz`) w 7. i 8. polu\n", - "podany jest, odpowiednio, lewy i prawy kontekst słowa do odgadnięcia.\n", - "(W pozostałych polach znajdują się metadane, o których już wspomnieliśmy,\n", - "na razie nie będziemy ich wykorzystywać).\n", - "W pliku z oczekiwanym wyjściem (`expected.tsv`), w odpowiadającym\n", - "wierszu, podawane jest brakujące słowo. Oczywiście w ostatecznym\n", - "teście `test-A` plik `expected.tsv` jest niedostępny, ukryty przed uczestnikami konkursu.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Zapis rozkładu prawdopodobieństwa\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dla każdego wiersza wejścia podajemy rozkład prawdopodobieństwa dla\n", - "słowa w luce w formacie:\n", - "\n", - " wyraz1:prob1 wyraz2:prob2 ... wyrazN:probN :prob0\n", - "\n", - "gdzie wyraz1, …, wyrazN to konkretne wyrazy, prob1, …, probN ich prawdopodobieństwa.\n", - "Można podać dowolną liczbę wyrazów.\n", - "Z kolei prob0 to „resztowe” prawdopodobieństwo przypisane do wszystkich pozostałych wyrazów,\n", - "prawdopodobieństwo to pozwala uniknąć problemów związanych ze słowami OOV, trzeba jeszcze tylko dokonać\n", - "modyfikacji metryki\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Metryka LikelihoodHashed\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Metryka LikelihoodHashed jest wariantem metryki Likelihood\n", - "(wiarygodności) opracowanym z myślą o wyzwaniach czy konkursach\n", - "modelowania języka. W tej metryce każde słowo wpada pseudolosowo do\n", - "jednego z $2^{10}=1024$ „kubełków”. Numer kubełka jest wyznaczony na\n", - "podstawie funkcji haszującej MurmurHash.\n", - "\n", - "Prawdopodobieństwa zwrócone przez ewaluowany model są sumowane w\n", - "każdym kubełku, następnie ewaluator zagląda do pliku \\`expected.tsv\\` i\n", - "uwzględnia prawdopodobieństwo z kubełka, do którego „wpada” oczekiwane\n", - "słowo. Oczywiście czasami więcej niż jedno słowo może wpaść do\n", - "kubełka, model mógł też „wrzucić” do kubełka tak naprawdę inne słowo\n", - "niż oczekiwane (przypadkiem oba słowa wpadają do jednego kubełka).\n", - "Tak więc LikelihoodHashed będzie nieco zawyżone w stosunku do Likelihood.\n", - "\n", - "Dlaczego więc taka komplikacja? Otóż LikelihoodHashed nie zakłada\n", - "żadnego słownika, znika problem słów OOV — prawdopodobieństwa resztowe prob0\n", - "są rozkładane równomiernie między wszystkie 1024 kubełki.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##### Alternatywne metryki\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "LikelihoodHashed została zaimplementowana w narzędziu ewaluacyjnym\n", - "[https://gitlab.com/filipg/geval|GEval](https://gitlab.com/filipg/geval|GEval). Są tam również dostępne\n", - "analogiczne warianty entropii krzyżowej (log loss) i perplexity\n", - "(LogLossHashed i PerplexityHashed).\n", - "\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.10.2" - }, - "org": null - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/wyk/05_Ngramowy_model.ipynb b/wyk/05_Ngramowy_model.ipynb new file mode 100644 index 0000000..2eb2875 --- /dev/null +++ b/wyk/05_Ngramowy_model.ipynb @@ -0,0 +1,19 @@ + +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", + "
\n", + "

Modelowanie języka

\n", + "

05. N-gramowe modele języka i ich zastosowania [wykład]

\n", + "

Filip Graliński (2022)

\n", + "
\n", + "\n", + "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n", + "\n" + ] + }, +{"cell_type":"markdown","metadata":{},"source":["## N-gramowe modele języka i ich zastosowania\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Przypomnienie\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Przypomnijmy, że model języka zwraca prawdopodobieństwo dla danego\nciągu symboli (tokenów, wyrazów itp.) $w_1\\ldots w_N$ (o długości $N$):\n\n$$P_M(w_1\\ldots w_N) = ?$$\n\nW dalszym ciągu będziemy zakładali, że będziemy operować na wyrazach.\nZbiór wszystkich wyrazów nazywa się **słownikiem** (ang. *vocabulary*,\nnie *dictionary!*), w literaturze dotyczącej modelowania języka\nzazwyczaj oznacza się go literą $V$ (częściej niż $\\Sigma$).\nDale zakładamy, że słownik jest skończony.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Co jeszcze potrafi model języka?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["##### Przewidywanie kolejnego słowa\n\n"]},{"cell_type":"markdown","metadata":{},"source":["$$P_M(w_N|w_1\\ldots w_{N-1}) = \\frac{P_M(w_1\\dots w_{N-1}w_N*)}{P_M(w_1\\dots w_{n-1}*)} = \\frac{\\sum_{\\alpha \\in\n \\Sigma^*}P_M(w_1\\dots w_N\\alpha)}{\\sum_{\\alpha\\in\\Sigma^*}P(w_1\\dots w_{n-1}\\alpha)}$$\n\n$P_M(w_N|w_1\\ldots w_{N-1})$ to właściwie skrót notacyjny, pełny zapis powinien mieć następujący kształt:\n\n$$P_M(X_N=w_N|X_1=w_1,\\ldots,X_{N-1}=w_{N-1}),$$\n\ngdzie $P_M(X_i=w)$ oznacza prawdopodobieństwo, że na $i$-tej pozycji wystąpi słowo $w$.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["##### Odgadywanie słowa w luce\n\n"]},{"cell_type":"markdown","metadata":{},"source":["$$P_M(w_1\\dots w_{i-1}?w_{i+1}\\dots w_N) = \\operatorname{argmax}_w P_M(w_1\\ldots w_{i-1}ww_{i+1}\\dots w_N)$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Przykład dla autentycznego modelu języku\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Zobaczmy przykładowe zastosowania i wyniki dla modelu języku\nwyuczonego na tekstach z II poł. XX w.\n\n![img](./05_Ngramowy_model/tabelka.png)\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Do czego stosujemy model języka?\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Model języka sam w sobie nie jest zbyt użyteczny. To raczej środek do celu\nniż cel sam w sobie.\n\nModel języka:\n\n- ma zastosowanie w kryptoanalizie\n - Oxmynsxq mkx lo kmrsofon li cdenisxq sdc kvzrklodsm mrkbkmdobc kxn bozvkmsxq okmr yxo li dro 13dr voddob zvkmon pebdrob kvyxq sx dro kvzrklod.\n- pomaga(ł) wybrać właściwe tłumaczenie w tłumaczeniu maszynowym\n czy transkrypcję w systemach rozpoznawania mowy (ASR)\n (zanim zaczęto używać do tego sieci neuronowych, gdzie nie\n ma już wyraźnego rozróżnienia między modelem tłumaczenia\n czy modelem akustycznym a modelem języka),\n- pomaga znaleźć „podejrzane” miejsca w tekście\n (korekta pisowni/gramatyki),\n- może być stosowany jako klasyfikator (potrzeba wtedy więcej niż jednego modelu,\n np. model języka spamów kontra model języka niespamów),\n- może być stosowany w kompresji danych,\n- bardzo dobry model języka **musi** mieć **w środku** bardzo dobrą **wiedzę**\n o języku i o świecie, można wziąć **„wnętrzności”** modelu, nie dbając o prawdopodobieństwa\n i użyć modelu w zupełnie innym celu.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### N-gramowy model języka\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Zawsze prawdziwe:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)\\dots P_M(w_N|w_1\\dots w_{N-1}).$$\n\nMożna aproksymować prawdopodobieństwa używając $n$-gramów:\n\n$$P_M(w_1\\dots w_N) \\approx P_M(w_1)\\dots P_M(w_i|w_{i-n+1}\\dots w_{i-1})\\dots P_M(w_N|w_{N-n+1}\\dots w_{N-1}).$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Model trigramowy\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n=3$:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_1w_2)\\dots P_M(w_i|w_{i-2}w_{i-1})\\dots P_M(w_N|w_{N-2}w_{N-1}).$$\n\nZauważmy, że model trigramowy oznacza modelowanie kolejnego wyrazu przy znajomości\n2 (nie 3!) poprzedzających wyrazów (**razem** mamy 3 wyrazy).\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Model digramowy/bigramowy\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n=2$:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2|w_1)P_M(w_3|w_2)\\dots P_M(w_i|w_{i-1})\\dots P_M(w_N|w_{N-1})$$\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Model unigramowy\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n=1$ uzyskujemy przypadek szczególny:\n\n$$P_M(w_1\\dots w_N) = P_M(w_1)P_M(w_2)P_M(w_3)\\dots P_M(w_N) = \\prod_{i=1}^N P_M(w_i)$$\n\nZauważmy, że w modelu unigramowym w ogóle nie bierzemy pod uwagę kolejności wyrazów.\n\n"]},{"cell_type":"markdown","metadata":{},"source":["#### Estymacja prawdopodobieństw\n\n"]},{"cell_type":"markdown","metadata":{},"source":["Dla $n$-gramowego modelu potrzebujmy estymować wartości:\n\n$$P_M(w_i|w_{i-n+1}\\dots w_{i-1}).$$\n\nPrawdopodobieństwa te estymujemy na podstawie jakiegoś **korpusu tekstów**\n(możemy nazywać go również **zbiorem uczącym**).\n\nNajprostszy sposób:\n\n$$P_M(w_i|w_{i-n+1}\\dots w_{i-1}) = \\frac{\\# w_{i-n+1}\\dots w_{i-1}w_i}{\\# w_{i-n+1}\\dots w_{i-1}},$$\n\ngdzie $\\# w_1\\dots w_k$ oznacza liczbę wystąpień w korpusie.\n\nNa przykład, jeśli model $M$ zostanie wyuczony na tekście *do be do be do do*, wówczas\n$P_M(\\mathit{be}|\\mathit{do})=\\frac{2}{3}$.\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/04_Ngramowy_model.org b/wyk/05_Ngramowy_model.org similarity index 98% rename from wyk/04_Ngramowy_model.org rename to wyk/05_Ngramowy_model.org index 24081d0..8f637c8 100644 --- a/wyk/04_Ngramowy_model.org +++ b/wyk/05_Ngramowy_model.org @@ -1,5 +1,5 @@ -** Modele języka i ich zastosowania +* N-gramowe modele języka i ich zastosowania *** Przypomnienie @@ -36,7 +36,7 @@ $$P_M(w_1\dots w_{i-1}?w_{i+1}\dots w_N) = \operatorname{argmax}_w P_M(w_1\ldots Zobaczmy przykładowe zastosowania i wyniki dla modelu języku wyuczonego na tekstach z II poł. XX w. -[[./04_Ngramowy_model/tabelka.png]] +[[./05_Ngramowy_model/tabelka.png]] *** Do czego stosujemy model języka? diff --git a/wyk/04_Ngramowy_model/tabelka.pdf b/wyk/05_Ngramowy_model/tabelka.pdf similarity index 100% rename from wyk/04_Ngramowy_model/tabelka.pdf rename to wyk/05_Ngramowy_model/tabelka.pdf diff --git a/wyk/04_Ngramowy_model/tabelka.png b/wyk/05_Ngramowy_model/tabelka.png similarity index 100% rename from wyk/04_Ngramowy_model/tabelka.png rename to wyk/05_Ngramowy_model/tabelka.png