\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":["## 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\npozostajemy tylko na gruncie najprostszych, $n$-gramowych modeli\njęzyka, inne prawdopodobieństwa uzyskamy dla modelu digramowego, a\ninny dla trigramowego. Jedne modele będą lepsze, inne — gorsze. Jak\nobiektywnie odróżnić dobry model od złego? Innymi słowy, jak ewaluować\nmodele 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\ndo ewaluacji większego systemu, którego częścią jest model języka, na przykład\nsystemu tłumaczenia maszynowego albo systemu ASR.\n\nEwaluacja 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\npodzielić nasz zbiór danych. W modelowaniu języka zbiorem danych jest\nzbiór tekstów w danym języku, czyli korpus języka.\nPowinniś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\nWarto też wydzielić osobny „deweloperski” zbiór testowy (*dev set*) —\ndo testowania na bieżąco, optymalizacji hiperparametrów itd. Zbiory\ntestowe nie muszą być bardzo duże, np. kilka tysięcy zdań może w zupełności wystarczyć.\n\nTak 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)\nto 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\nDodajmy, że poszczególne zbiory zawierają teksty z różnych gazet. Jest\nto 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\nOto 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\nZauważmy, że mamy nie tylko tekst, lecz również metadane (czas i\nwspółrzędne geograficzne). W modelowaniu języka można uwzględnić\nrównież takie dodatkowe parametry (np. prawdopodobieństwa wystąpienia\nsłowa *koronawirus* wzrasta po roku 2019).\n\nZauważmy również, że tekst zawiera błędy OCR-owe (np. *nad* zamiast\n*had*). Czy w takim razie jest to sensowne wyzwanie modelowania\njęzyka? Tak, w niektórych przypadkach możemy chcieć modelować tekst z\nuwzglę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\nprawdopodobieństwo przypisane zbiorowi testowemu $C'$ przez model\n(wyuczony na zbiorze $C$).\n\nJeśli oceniamy przewidywania, które człowiek lub komputer czynią, to\nim większe prawdopodobieństwo przypisane do tego, co miało miejsce,\ntym lepiej. Zatem im wyższe $P_M(C')$, tym lepiej.\n\nZazwyczaj będziemy rozbijali $P_M(C')$ na prawdopodobieństwa\nprzypisane 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\nnadawca i odbiorca tekstu mają do dyspozycji ten sam model języka…\n\n![img](./06_Ewaluacja/lm-communication.drawio.png)\n\n… powinni być w stanie zaoszczędzić na długości komunikatu.\n\nW 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\nnic nie trzeba przesyłać przez kanał komunikacji. Taka sytuacja może\nrealnie 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\nModel języka może pomóc również w mniej skrajnym przypadkach, np.\njeżeli na danej pozycji w tekście model redukuje cały słownik do dwóch\nwyrazów z prawdopodobieństwem 1/2, wówczas nadawca może zakodować tę\npozycję 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\npomocą (średnio) $-\\log_2(p)$ bitów, tak więc jeśli nadawca i odbiorca dysponują\nmodelem $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\nAby móc porównywać wyniki dla korpusów dla różnej długości, warto znormalizować\ntę 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\nTę wartość nazywamy **entropią krzyżową** modelu $M$. Entropia krzyżowa\nmierzy naszą niewiedzę przy założeniu, że dysponujemy modelem $M$. Im niższa wartość\nentropii krzyżowej, tym lepiej, im bowiem mniejsza nasza niewiedza,\ntym lepiej.\n\nEntropią krzyżową jest często nazywaną funkcją **log loss**, zwłaszcza w\nkontekś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\nprawdopodobieństwo przypisane zdarzeniom niejako „po fakcie”. Jak już\nwspomnieliśmy, im wyższe prawdopodobieństwo (wiarygodność) przypisane\ntestowej części korpusu, tym lepiej. Innymi słowy, jako metrykę ewaluacji\nuż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\nz tym, że znowu warto znormalizować to prawdopodobieństwo względem rozmiaru korpusu.\nZe względu na to, że prawdopodobieństwa przemnażamy, zamiast średniej arytmetycznej\nlepiej 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\njęzyka rzadziej niż entropia krzyżowa (log loss), mimo tego, że wydaje\nsię nieco łatwiejsza do interpretacji dla człowieka. Otóż wiarygodność\nto **ś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ą.\nOtóż 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*),\nzamiast 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\nIntuicyjnie można sobie wyobrazić, że perplexity to liczba możliwości\nprognozowanych przez model z równym prawdopodobieństwem. Na przykład,\njeśli model przewiduje, że w danym miejscu tekstu może wystąpić z\nrównym prawdopodobieństwem jedno z 32 słów, wówczas (jeśli\nrzeczywiście któreś z tych słów wystąpiło) entropia wynosi 5 bitów, a\nperplexity — 32.\n\nInaczej: perplexity to po prostu odwrotność wiarygodności:\n\n$$\\operatorname{PP}(M) = \\sqrt[N']{P_M(w_1'\\dots w_N')}.$$\n\nPerplexity zależy oczywiście od języka i modelu, ale typowe wartości\nzazwyczaj 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).\nKenLM 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\nWyuczmy na zbiorze uczącym wspomnianego wyzwania *Challenging America word-gap prediction*\ndwa modele, jeden 3-gramowy, drugi 4-gramowy.\n\nZ 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\nJak widać model 4-gramowy jest lepszy (ma niższe perplexity) niż model 3-gramowy, przynajmniej\njeś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,\nwiarygodność i perplexity) są ze sobą ściśle związane, w gruncie\nrzeczy 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\ndużą pewność siebie. Wystarczy, że dla **jednej** pozycji w zbiorze\nprzypiszemy zerowe prawdopodobieństwo, wówczas wszystko „eksploduje”.\nPerplexity i entropia krzyżowa „wybuchają” do nieskończoności,\nwiarygodność spada do zera — bez względu na to, jak dobre są\nprzewidywania dotyczące innych pozycji w tekście!\n\nW przypadku wiarygodności wiąże się to z tym, że wiarygodność\ndefiniujemy jako iloczyn prawdopodobieństwa, oczywiście wystarczy, że\njedna liczba w iloczynie była zerem, żeby iloczyn przyjął wartość\nzero. Co więcej, nawet jeśli pominiemy taki skrajny przypadek, to\nśrednia geometryczna „ciągnie” w dół, bardzo niska wartość\nprawdopodobieństwa przypisana do rzeczywistego słowa może drastycznie obniżyć\nwartość 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\nprzypisywanie każdemu możliwemu słowu przynajmniej niskiego\nprawdopodobieństwa $\\epsilon$. Niestety, zawsze może pojawić się\nsł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\npojawić 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\nczy wiarygodność), bardzo łatwo można „oszukać” — wystarczy\nzaraportować prawdopodobieństwo 1! Oczywiście to absurd, bo albo\nwszystkim innym tekstom przypisujemy prawdopodobieństwo 0, albo —\njeśli „oszukańczy” system każdemu innemu tekstowi przypisze\nprawdopodobieństwo 1 — nie mamy do czynienia z poprawnym rozkładem\nprawdopodobieństwa.\n\nCo gorsza, nawet jeśli wykluczymy scenariusz świadomego oszustwa,\nłatwo *samego siebie* wprowadzić w błąd. Na przykład przez pomyłkę\nmożna zwracać zawyżone prawdopodobieństwo (powiedzmy przemnożone przez 2).\n\nTe problemy stają się szczególnie dokuczliwe, jeśli organizujemy\nwyzwanie, *konkurs* modelowania języka, gdzie chcemy w sposób\nobiektywny porównywać różne modele języka, tak aby uniknąć celowego\nbądź nieświadomego zawyżania wyników.\n\nPrzedstawimy teraz, w jaki sposób poradzono sobie z tym problemem\nw 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\nword-gap prediction* zamiast zwracania prawdopodobieństwa dla całego\ntekstu oczekuje się podania rozkładu prawdopodobieństwa dla brakującego słowa.\n\nMianowicie, w każdym wierszu wejściu (plik `in.tsv.xz`) w 7. i 8. polu\npodany 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,\nna razie nie będziemy ich wykorzystywać).\nW pliku z oczekiwanym wyjściem (`expected.tsv`), w odpowiadającym\nwierszu, podawane jest brakujące słowo. Oczywiście w ostatecznym\nteś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\nsłowa w luce w formacie:\n\n wyraz1:prob1 wyraz2:prob2 ... wyrazN:probN :prob0\n\ngdzie wyraz1, …, wyrazN to konkretne wyrazy, prob1, …, probN ich prawdopodobieństwa.\nMożna podać dowolną liczbę wyrazów.\nZ kolei prob0 to „resztowe” prawdopodobieństwo przypisane do wszystkich pozostałych wyrazów,\nprawdopodobieństwo to pozwala uniknąć problemów związanych ze słowami OOV, trzeba jeszcze tylko dokonać\nmodyfikacji 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\nmodelowania języka. W tej metryce każde słowo wpada pseudolosowo do\njednego z $2^{10}=1024$ „kubełków”. Numer kubełka jest wyznaczony na\npodstawie funkcji haszującej MurmurHash.\n\nPrawdopodobieństwa zwrócone przez ewaluowany model są sumowane w\nkażdym kubełku, następnie ewaluator zagląda do pliku \\`expected.tsv\\` i\nuwzględnia prawdopodobieństwo z kubełka, do którego „wpada” oczekiwane\nsłowo. Oczywiście czasami więcej niż jedno słowo może wpaść do\nkubełka, model mógł też „wrzucić” do kubełka tak naprawdę inne słowo\nniż oczekiwane (przypadkiem oba słowa wpadają do jednego kubełka).\nTak więc LikelihoodHashed będzie nieco zawyżone w stosunku do Likelihood.\n\nDlaczego więc taka komplikacja? Otóż LikelihoodHashed nie zakłada\nżadnego słownika, znika problem słów OOV — prawdopodobieństwa resztowe prob0\nsą 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\nanalogiczne warianty entropii krzyżowej (log loss) i perplexity\n(LogLossHashed i PerplexityHashed).\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}