Drobne poprawki w wykładzie

This commit is contained in:
Filip Gralinski 2021-10-05 21:44:46 +02:00
parent f804311da1
commit 72db2aa687
11 changed files with 2095 additions and 2098 deletions

View File

@ -15,16 +15,14 @@
] ]
}, },
{ {
"cell_type": "code", "cell_type": "markdown",
"execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [],
"source": [ "source": [
"# Wyszukiwarki - wprowadzenie\n", "# Wyszukiwarki - wprowadzenie\n",
"\n", "\n",
"## Systemy wyszukiwania informacji (information retrieval systems)\n", "## Systemy wyszukiwania informacji (information retrieval systems)\n",
"\n", "\n",
"![System wyszukiwania informacji](system-wyszukiwania-informacji.png)" "![Schemat systemu wyszukiwania informacji](system-wyszukiwania-informacji.png)"
] ]
}, },
{ {
@ -36,7 +34,7 @@
"source": [ "source": [
"## Wyszukiwarki\n", "## Wyszukiwarki\n",
"\n", "\n",
"![Wyszukiwarki](wyszukiwarka-internetowa.png)" "![Schemat wyszukiwarki internetowej](wyszukiwarka-internetowa.png)"
] ]
}, },
{ {
@ -108,7 +106,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Dostępne są też \"ekstrakty\" czystego tekstu - zob. http://data.statmt.org/ngrams/raw/, np. 59 GB czystego tekstu po polsku z 2012 roku." "Dostępne są też „ekstrakty” czystego tekstu — zob. http://data.statmt.org/ngrams/raw/, np. 59 GB czystego tekstu po polsku z 2012 roku."
] ]
}, },
{ {
@ -303,7 +301,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Odpytywać \"pasożytniczo\" inną wyszukiwarkę" "### Odpytywać „pasożytniczo” inną wyszukiwarkę"
] ]
}, },
{ {
@ -312,7 +310,7 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"# see https://hackernoon.com/how-to-scrape-google-with-python-bo7d2tal\n", "# zob. https://hackernoon.com/how-to-scrape-google-with-python-bo7d2tal\n",
"\n", "\n",
"import urllib\n", "import urllib\n",
"import requests\n", "import requests\n",

View File

@ -328,7 +328,7 @@
"\n", "\n",
"* urllib\n", "* urllib\n",
"* request\n", "* request\n",
"* Beautiful Soup (do parsowania HTML-a)" "* Beautiful Soup (do parsowania dokumentów HTML)"
] ]
}, },
{ {

View File

@ -2,15 +2,13 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"collapsed": false
},
"source": [ "source": [
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n", "<div class=\"alert alert-block alert-info\">\n",
"<h1> Ekstrakcja informacji </h1>\n", "<h1> Ekstrakcja informacji </h1>\n",
"<h2> 5. <i>G\u0119ste reprezentacje wektorowe</i> [wyk\u0142ad]</h2> \n", "<h2> 5. <i>Gęste reprezentacje wektorowe</i> [wykład]</h2> \n",
"<h3> Filip Grali\u0144ski (2021)</h3>\n", "<h3> Filip Graliński (2021)</h3>\n",
"</div>\n", "</div>\n",
"\n", "\n",
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)" "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
@ -20,19 +18,19 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# Zag\u0119szczamy wektory\n", "# Zagęszczamy wektory\n",
"\n", "\n",
"Podstawowy problem z wektorow\u0105 reprezentacj\u0105 typu tf-idf polega na tym, \u017ce wektory dokument\u00f3w (i macierz ca\u0142ej kolekcji dokument\u00f3w) s\u0105 _rzadkie_, tzn. zawieraj\u0105 du\u017co zer. W praktyce potrzebujemy bardziej \"g\u0119stej\" czy \"kompaktowej\" reprezentacji numerycznej dokument\u00f3w. \n", "Podstawowy problem z wektorową reprezentacją typu tf-idf polega na tym, że wektory dokumentów (i macierz całej kolekcji dokumentów) są _rzadkie_, tzn. zawierają dużo zer. W praktyce potrzebujemy bardziej \"gęstej\" czy \"kompaktowej\" reprezentacji numerycznej dokumentów. \n",
"\n", "\n",
"## _Hashing trick_\n", "## _Hashing trick_\n",
"\n", "\n",
"Powierzchownie problem mo\u017cemy rozwi\u0105za\u0107 przez u\u017cycie tzw. _sztuczki z haszowaniem_ (_hashing trick_). B\u0119dziemy potrzebowa\u0107 funkcji mieszaj\u0105cej (haszuj\u0105cej) $H$, kt\u00f3ra rzutuje napisy na liczby, kt\u00f3rych reprezentacja binarna sk\u0142ada si\u0119 z $b$ bit\u00f3w:\n", "Powierzchownie problem możemy rozwiązać przez użycie tzw. _sztuczki z haszowaniem_ (_hashing trick_). Będziemy potrzebować funkcji mieszającej (haszującej) $H$, która rzutuje napisy na liczby, których reprezentacja binarna składa się z $b$ bitów:\n",
"\n", "\n",
"$$H : \\Sigma^{*} \\rightarrow \\{0,\\dots,2^b-1\\}$$\n", "$$H : \\Sigma^{*} \\rightarrow \\{0,\\dots,2^b-1\\}$$\n",
"\n", "\n",
"($\\Sigma^{*}$ to zbi\u00f3r wszystkich napis\u00f3w.)\n", "($\\Sigma^{*}$ to zbiór wszystkich napisów.)\n",
"\n", "\n",
"**Pytanie:** Czy funkcja $H$ mo\u017ce by\u0107 r\u00f3\u017cnowarto\u015bciowa?\n", "**Pytanie:** Czy funkcja $H$ może być różnowartościowa?\n",
"\n" "\n"
] ]
}, },
@ -40,7 +38,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Jako funkcji $H$ mo\u017cemy np. u\u017cy\u0107 funkcji MurmurHash2 lub 3." "Jako funkcji $H$ możemy np. użyć funkcji MurmurHash2 lub 3."
] ]
}, },
{ {
@ -138,14 +136,14 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"**Pytanie:** podobne napisy maj\u0105 zupe\u0142nie r\u00f3\u017cne warto\u015bci funkcji haszuj\u0105cej, czy to dobrze, czy to \u017ale?" "**Pytanie:** podobne napisy mają zupełnie różne wartości funkcji haszującej, czy to dobrze, czy to źle?"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Musimy tylko sparametryzowa\u0107 nasz\u0105 funkcj\u0119 rozmiarem \"odcisku\" (parametr $b$)." "Musimy tylko sparametryzować naszą funkcję rozmiarem „odcisku” (parametr $b$)."
] ]
}, },
{ {
@ -204,12 +202,12 @@
"\n", "\n",
"import Data.Text\n", "import Data.Text\n",
"\n", "\n",
"-- pomocnicza funkcja, kt\u00f3ra konwertuje warto\u015b\u0107 specjalnego\n", "-- pomocnicza funkcja, która konwertuje wartość specjalnego\n",
"-- typu Hash64 do zwyk\u0142ej liczby ca\u0142kowitej\n", "-- typu Hash64 do zwykłej liczby całkowitej\n",
"hashValueAsInteger :: Hash64 -> Integer\n", "hashValueAsInteger :: Hash64 -> Integer\n",
"hashValueAsInteger = toInteger . asWord64\n", "hashValueAsInteger = toInteger . asWord64\n",
"\n", "\n",
"-- unpack to funkcja, kt\u00f3ra warto\u015b\u0107 typu String konwertuje do Text\n", "-- unpack to funkcja, która wartość typu String konwertuje do Text\n",
"hash :: Integer -> Text -> Integer\n", "hash :: Integer -> Text -> Integer\n",
"hash b t = hashValueAsInteger (hash64 $ unpack t) `mod` (2 ^ b)\n", "hash b t = hashValueAsInteger (hash64 $ unpack t) `mod` (2 ^ b)\n",
"\n", "\n",
@ -224,21 +222,21 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"**Pytanie:** Jakie warto\u015bci $b$ b\u0119d\u0105 bezsensowne?" "**Pytanie:** Jakie wartości $b$ będą bezsensowne?"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Sztuczka z haszowaniem polega na tym, \u017ce zamiast numerowa\u0107 s\u0142owa korzystaj\u0105c ze s\u0142ownika, po prostu u\u017cywamy funkcji haszuj\u0105cej. W ten spos\u00f3b wektor b\u0119dzie _zawsze_ rozmiar $2^b$ - bez wzgl\u0119du na rozmiar s\u0142ownika." "Sztuczka z haszowaniem polega na tym, że zamiast numerować słowa korzystając ze słownika, po prostu używamy funkcji haszującej. W ten sposób wektor będzie _zawsze_ rozmiar $2^b$ - bez względu na rozmiar słownika."
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Zacznijmy od przywo\u0142ania wszystkich potrzebnych definicji." "Zacznijmy od przywołania wszystkich potrzebnych definicji."
] ]
}, },
{ {
@ -256,8 +254,8 @@
"isStopWord :: Text -> Bool\n", "isStopWord :: Text -> Bool\n",
"isStopWord \"w\" = True\n", "isStopWord \"w\" = True\n",
"isStopWord \"jest\" = True\n", "isStopWord \"jest\" = True\n",
"isStopWord \"\u017ce\" = True\n", "isStopWord \"że\" = True\n",
"isStopWord w = w \u2248 [re|^\\p{P}+$|]\n", "isStopWord w = w ≈ [re|^\\p{P}+$|]\n",
"\n", "\n",
"\n", "\n",
"removeStopWords :: [Text] -> [Text]\n", "removeStopWords :: [Text] -> [Text]\n",
@ -288,10 +286,10 @@
"mockInflectionDictionary = Map.fromList [\n", "mockInflectionDictionary = Map.fromList [\n",
" (\"kota\", \"kot\"),\n", " (\"kota\", \"kot\"),\n",
" (\"butach\", \"but\"),\n", " (\"butach\", \"but\"),\n",
" (\"masz\", \"mie\u0107\"),\n", " (\"masz\", \"mieć\"),\n",
" (\"ma\", \"mie\u0107\"),\n", " (\"ma\", \"mieć\"),\n",
" (\"buta\", \"but\"),\n", " (\"buta\", \"but\"),\n",
" (\"zgubi\u0142em\", \"zgubi\u0107\")]\n", " (\"zgubiłem\", \"zgubić\")]\n",
"\n", "\n",
"lemmatizeWord :: Map Text Text -> Text -> Text\n", "lemmatizeWord :: Map Text Text -> Text -> Text\n",
"lemmatizeWord dict w = findWithDefault w w dict\n", "lemmatizeWord dict w = findWithDefault w w dict\n",
@ -523,10 +521,10 @@
" where n = vectorNorm vs\n", " where n = vectorNorm vs\n",
"\n", "\n",
"\n", "\n",
"(\u2715) :: [Double] -> [Double] -> Double\n", "(✕) :: [Double] -> [Double] -> Double\n",
"(\u2715) v1 v2 = sum $ Prelude.zipWith (*) v1 v2\n", "(✕) v1 v2 = sum $ Prelude.zipWith (*) v1 v2\n",
"\n", "\n",
"cosineSim v1 v2 = toUnitVector v1 \u2715 toUnitVector v2\n", "cosineSim v1 v2 = toUnitVector v1 ✕ toUnitVector v2\n",
"\n", "\n",
"paintMatrix cosineSim labelsLimited limitedL" "paintMatrix cosineSim labelsLimited limitedL"
] ]
@ -535,9 +533,9 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Powy\u017csza macierz reprezentuje por\u00f3wnanie przy u\u017cyciu podobie\u0144stwa kosinusowego. Spr\u00f3bujmy teraz u\u017cy\u0107 g\u0119stszych wektor\u00f3w przy u\u017cyciu hashing trick. Jako warto\u015b\u0107 $b$ przyjmijmy 6.\n", "Powyższa macierz reprezentuje porównanie przy użyciu podobieństwa kosinusowego. Spróbujmy teraz użyć gęstszych wektorów przy użyciu hashing trick. Jako wartość $b$ przyjmijmy 6.\n",
"\n", "\n",
"Zobaczmy najpierw, w kt\u00f3re \"przegr\u00f3dki\" b\u0119d\u0105 wpada\u0142y poszczeg\u00f3lne wyrazy s\u0142ownika.\n", "Zobaczmy najpierw, w które \"przegródki\" będą wpadały poszczególne wyrazy słownika.\n",
"\n", "\n",
"\n" "\n"
] ]
@ -565,18 +563,18 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"**Pytanie:** Czy jakie\u015b dwa termy wpad\u0142y do jednej przegr\u00f3dki?" "**Pytanie:** Czy jakieś dwa termy wpadły do jednej przegródki?"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Stw\u00f3rzmy najpierw funkcj\u0119, kt\u00f3ra b\u0119dzie wektoryzowa\u0142a pojedynczy term $t$. Po prostu stworzymy wektor, kt\u00f3re b\u0119dzie mia\u0142 rozmiar $2^b$, wsz\u0119dzie b\u0119dzie mia\u0142 0 z wyj\u0105tkiem pozycji o numerze $H_b(t)$ - tam wpiszmy odwrotn\u0105 cz\u0119sto\u015b\u0107 dokumentow\u0105.\n", "Stwórzmy najpierw funkcję, która będzie wektoryzowała pojedynczy term $t$. Po prostu stworzymy wektor, które będzie miał rozmiar $2^b$, wszędzie będzie miał 0 z wyjątkiem pozycji o numerze $H_b(t)$ - tam wpiszmy odwrotną częstość dokumentową.\n",
"\n", "\n",
"$$\\vec{t} = [0,\\dots,\\idf_c t,\\dots,0]$$\n", "$$\\vec{t} = [0,\\dots,\\idf_c t,\\dots,0]$$\n",
"\n", "\n",
"Teraz dla dokumentu $d = (t_1,\\dots,t_n)$ i dla schematu wa\u017cenia tf-idf:\n", "Teraz dla dokumentu $d = (t_1,\\dots,t_n)$ i dla schematu ważenia tf-idf:\n",
"\n", "\n",
"$$\\vec{d} = \\sum \\vec{t_i}$$" "$$\\vec{d} = \\sum \\vec{t_i}$$"
] ]
@ -632,7 +630,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Teraz wystarczy zsumowa\u0107 wektory dla poszczeg\u00f3lnych s\u0142\u00f3w, \u017ceby otrzyma\u0107 wektor dokumentu. Najpierw zdefiniujmy sobie sum\u0119 wektorow\u0105." "Teraz wystarczy zsumować wektory dla poszczególnych słów, żeby otrzymać wektor dokumentu. Najpierw zdefiniujmy sobie sumę wektorową."
] ]
}, },
{ {
@ -661,7 +659,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Przydatna b\u0119dzie jeszcze funkcja, kt\u00f3ra tworzy wektor z samymi zerami o zadanej d\u0142ugo\u015bci:" "Przydatna będzie jeszcze funkcja, która tworzy wektor z samymi zerami o zadanej długości:"
] ]
}, },
{ {
@ -854,7 +852,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Zobaczmy, jak zag\u0119szczenie wp\u0142ywa na macierz podobie\u0144stwa." "Zobaczmy, jak zagęszczenie wpływa na macierz podobieństwa."
] ]
}, },
{ {
@ -896,19 +894,19 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"**Pytanie:** Co si\u0119 stanie, gdy zwi\u0119kszymy $b$, a co je\u015bli zmniejszymi?\n", "**Pytanie:** Co się stanie, gdy zwiększymy $b$, a co jeśli zmniejszymi?\n",
"\n", "\n",
"Zalety sztuczki z haszowaniem:\n", "Zalety sztuczki z haszowaniem:\n",
"\n", "\n",
"* zagwarantowany sta\u0142y rozmiar wektora\n", "* zagwarantowany stały rozmiar wektora\n",
"* szybsze obliczenia\n", "* szybsze obliczenia\n",
"* w naturalny spos\u00f3b uwzgl\u0119dniamy termy, kt\u00f3rych nie by\u0142o w pocz\u0105tkowej kolekcji (ale uwaga na idf!)\n", "* w naturalny sposób uwzględniamy termy, których nie było w początkowej kolekcji (ale uwaga na idf!)\n",
"* nie musimy pami\u0119ta\u0107 odzworowania rzutuj\u0105cego s\u0142owa na ich numery\n", "* nie musimy pamiętać odzworowania rzutującego słowa na ich numery\n",
"\n", "\n",
"Wady:\n", "Wady:\n",
"\n", "\n",
"* dwa r\u00f3\u017cne s\u0142owa mog\u0105 wpa\u015b\u0107 do jednej przegr\u00f3dki (szczeg\u00f3lnie cz\u0119ste, je\u015bli $b$ jest za ma\u0142e)\n", "* dwa różne słowa mogą wpaść do jednej przegródki (szczególnie częste, jeśli $b$ jest za małe)\n",
"* je\u015bli $b$ ustawimy za du\u017ce, wektory mog\u0105 by\u0107 nawet wi\u0119ksze ni\u017c w przypadku standardowego podej\u015bcia\n", "* jeśli $b$ ustawimy za duże, wektory mogą być nawet większe niż w przypadku standardowego podejścia\n",
"\n", "\n",
"\n", "\n",
"\n", "\n",
@ -921,11 +919,11 @@
"source": [ "source": [
"## Word2vec\n", "## Word2vec\n",
"\n", "\n",
"A mo\u017ce istnieje dobra wr\u00f3\u017cka, kt\u00f3ra da\u0142aby nam dobre wektory s\u0142\u00f3w (z kt\u00f3rych b\u0119dziemy sk\u0142adali proste wektory dokument\u00f3w przez sumowanie)?\n", "A może istnieje dobra wróżka, która dałaby nam dobre wektory słów (z których będziemy składali proste wektory dokumentów przez sumowanie)?\n",
"\n", "\n",
"**Pytanie:** Jakie w\u0142asno\u015bci powinny mie\u0107 dobre wektory s\u0142\u00f3w?\n", "**Pytanie:** Jakie własności powinny mieć dobre wektory słów?\n",
"\n", "\n",
"Tak! Istniej\u0105 gotowe \"bazy danych\" wektor\u00f3w. Jedn\u0105 z najpopularniejszych (i najstarszych) metod uzyskiwania takich wektor\u00f3w jest Word2vec. Jak dok\u0142adnie Word2vec, dowiemy si\u0119 p\u00f3\u017aniej, na dzisiaj po prostu u\u017cyjmy tych wektor\u00f3w.\n", "Tak! Istnieją gotowe \"bazy danych\" wektorów. Jedną z najpopularniejszych (i najstarszych) metod uzyskiwania takich wektorów jest Word2vec. Jak dokładnie Word2vec, dowiemy się później, na dzisiaj po prostu użyjmy tych wektorów.\n",
"\n", "\n",
"\n", "\n",
"\n", "\n",
@ -943,7 +941,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Najpierw wprowad\u017amy alternatywn\u0105 normalizacj\u0119 zgodn\u0105 z tym, jak zosta\u0142 wygenerowany model." "Najpierw wprowadźmy alternatywną normalizację zgodną z tym, jak został wygenerowany model."
] ]
}, },
{ {
@ -1331,7 +1329,7 @@
"toOurVector :: WVector -> [Double]\n", "toOurVector :: WVector -> [Double]\n",
"toOurVector (WVector v _) = map realToFrac $ V.toList v\n", "toOurVector (WVector v _) = map realToFrac $ V.toList v\n",
"\n", "\n",
"balwanV = toOurVector $ fromJust $ getVector model \"ba\u0142wan\"\n", "balwanV = toOurVector $ fromJust $ getVector model \"bałwan\"\n",
"balwanV\n", "balwanV\n",
"Prelude.length balwanV\n", "Prelude.length balwanV\n",
"\n", "\n",
@ -1397,7 +1395,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Mo\u017cemy pr\u00f3bowa\u0107 mno\u017cy\u0107 wektory z modelu Word2vec z idf. Najpierw zdefiniujmy mno\u017cenie przez skalar." "Możemy próbować mnożyć wektory z modelu Word2vec z idf. Najpierw zdefiniujmy mnożenie przez skalar."
] ]
}, },
{ {
@ -1426,7 +1424,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Teraz b\u0119dziemy przemna\u017cali wektory Word2vec przez idf (jako skalar)." "Teraz będziemy przemnażali wektory Word2vec przez idf (jako skalar)."
] ]
}, },
{ {
@ -1620,11 +1618,14 @@
} }
], ],
"metadata": { "metadata": {
"author": "Filip Graliński",
"email": "filipg@amu.edu.pl",
"kernelspec": { "kernelspec": {
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
}, },
"lang": "pl",
"language_info": { "language_info": {
"codemirror_mode": "ihaskell", "codemirror_mode": "ihaskell",
"file_extension": ".hs", "file_extension": ".hs",
@ -1633,10 +1634,7 @@
"pygments_lexer": "Haskell", "pygments_lexer": "Haskell",
"version": "8.10.4" "version": "8.10.4"
}, },
"author": "Filip Grali\u0144ski", "subtitle": "5.Gęste reprezentacje wektorowe[wykład]",
"email": "filipg@amu.edu.pl",
"lang": "pl",
"subtitle": "5.G\u0119ste reprezentacje wektorowe[wyk\u0142ad]",
"title": "Ekstrakcja informacji", "title": "Ekstrakcja informacji",
"year": "2021" "year": "2021"
}, },

View File

@ -24,7 +24,7 @@
"\n", "\n",
"Zakładamy, że mamy dwie klasy: $c$ i jej dopełnienie ($\\bar{c}$).\n", "Zakładamy, że mamy dwie klasy: $c$ i jej dopełnienie ($\\bar{c}$).\n",
"\n", "\n",
"Typowym przykładem jest zadanie klasyfikacji mejla, czy należy do spamu, czy nie (_spam_ vs _ham_), czyli innymi słowy filtr antyspamowy." "Typowym przykładem jest zadanie klasyfikacji mejla, czy należy do spamu, czy nie (_spam_ vs _ham_), czyli, innymi słowy, filtr antyspamowy."
] ]
}, },
{ {
@ -78,9 +78,9 @@
"\n", "\n",
"W klasyfikacji (i w ogóle w uczeniu nadzorowanym) można wskazać dwa podejścia:\n", "W klasyfikacji (i w ogóle w uczeniu nadzorowanym) można wskazać dwa podejścia:\n",
"\n", "\n",
"* generatywne - wymyślamy pewną \"historyjkę\", w jaki sposób powstaje tekst, \"historyjka\" powinna mieć miejsca do wypełnienia (parametry), np. częstości wyrazów, na podstawie zbioru uczącego dobieramy wartości parametrów (przez rachunki wprost); \"historyjka\" nie musi być prawdziwa, wystarczy, że jakoś przybliża rzeczywistość\n", "* generatywne — wymyślamy pewną „historyjkę”, w jaki sposób powstaje tekst, „historyjka” powinna mieć miejsca do wypełnienia (parametry), np. częstości wyrazów, na podstawie zbioru uczącego dobieramy wartości parametrów (przez rachunki wprost); „historyjka” nie musi być prawdziwa, wystarczy, że jakoś przybliża rzeczywistość\n",
"\n", "\n",
"* dyskryminatywne - nie zastanawiamy się, w jaki sposób powstają teksty, po prostu \"na siłę\" dobieramy wartości parametrów (wag) modelu, tak aby uzyskać jak najmniejszą wartość funkcji kosztu na zbiorze uczącym; zwykle odbywa się to w iteracyjnym procesie (tak jak przedstawiono na schemacie na poprzednim wykładzie).\n", "* dyskryminatywne — nie zastanawiamy się, w jaki sposób powstają teksty, po prostu „na siłę” dobieramy wartości parametrów (wag) modelu, tak aby uzyskać jak najmniejszą wartość funkcji kosztu na zbiorze uczącym; zwykle odbywa się to w iteracyjnym procesie (tak jak przedstawiono na schemacie na poprzednim wykładzie).\n",
"\n", "\n",
"**Pytanie**: Jakie są wady i zalety obu podejść?" "**Pytanie**: Jakie są wady i zalety obu podejść?"
] ]
@ -146,11 +146,11 @@
"source": [ "source": [
"## Naiwny klasyfikator bayesowski\n", "## Naiwny klasyfikator bayesowski\n",
"\n", "\n",
"* _naiwny_ - niekoniecznie oznacza, że to \"głupi\", bezużyteczny klasyfikator\n", "* _naiwny_— niekoniecznie oznacza, że to „głupi”, bezużyteczny klasyfikator\n",
"* _klasyfikator_ \n", "* _klasyfikator_ \n",
"* _bayesowski_ - będzie odwoływać się do wzoru Bayesa.\n", "* _bayesowski_ będzie odwoływać się do wzoru Bayesa.\n",
"\n", "\n",
"Naiwny klasyfikator bayesowski raczej nie powinien być stosowany \"produkcyjnie\" (są lepsze metody). Natomiast jest to metoda bardzo prosta w implementacji dająca przyzwoity _baseline_.\n", "Naiwny klasyfikator bayesowski raczej nie powinien być stosowany „produkcyjnie” (są lepsze metody). Natomiast jest to metoda bardzo prosta w implementacji dająca przyzwoity _baseline_.\n",
"\n", "\n",
"Naiwny klasyfikator bayesowski ma dwie odmiany:\n", "Naiwny klasyfikator bayesowski ma dwie odmiany:\n",
"\n", "\n",
@ -221,14 +221,14 @@
"source": [ "source": [
"#### Prawdopodobieństwo _a priori_\n", "#### Prawdopodobieństwo _a priori_\n",
"\n", "\n",
"$P(c)$ - prawdopodobieństwo a priori klasy $c$\n", "$P(c)$ prawdopodobieństwo a priori klasy $c$\n",
"\n", "\n",
"$\\hat{P}(c) = \\frac{N_c}{N}$\n", "$\\hat{P}(c) = \\frac{N_c}{N}$\n",
"\n", "\n",
"gdzie\n", "gdzie\n",
"\n", "\n",
"* N - liczba wszystkich dokumentów w zbiorze uczącym\n", "* N liczba wszystkich dokumentów w zbiorze uczącym\n",
"* N_c - liczba dokumentow w zbiorze uczącym z klasą $c$\n", "* N_c liczba dokumentow w zbiorze uczącym z klasą $c$\n",
"\n", "\n",
"$\\hat{P}(c) = 0,75$\n", "$\\hat{P}(c) = 0,75$\n",
"\n", "\n",
@ -256,11 +256,11 @@
"source": [ "source": [
"$P(d|c) = P(t_1\\dots t_n|c)$\n", "$P(d|c) = P(t_1\\dots t_n|c)$\n",
"\n", "\n",
"Żeby pójść dalej musimy doszczegółowić nasz model generatywny. Przyjmijmy bardzo naiwny i niezgodny z rzeczywistością model spamera (i nie-spamera): spamer wyciąga wyrazy z worka i wrzuca je z powrotem (losowanie ze zwracaniem). Jedyne co odróżnia spamera i nie-spamera, to **prawdopodobieństwo wylosowania wyrazu** (np. spamer wylosuje słowo _Viagra_ z dość dużym prawdopodobieństwem, nie-spamer - z bardzo niskim).\n", "Aby pójść dalej, musimy doszczegółowić nasz model generatywny. Przyjmijmy bardzo naiwny i niezgodny z rzeczywistością model spamera (i nie-spamera): spamer wyciąga wyrazy z worka i wrzuca je z powrotem (losowanie ze zwracaniem). Jedyne co odróżnia spamera i nie-spamera, to **prawdopodobieństwo wylosowania wyrazu** (np. spamer wylosuje słowo _Viagra_ z dość dużym prawdopodobieństwem, nie-spamer z bardzo niskim).\n",
"\n", "\n",
"**Pytanie:** Ile może wynosić $P(\\mathit{Viagra}|c)$?\n", "**Pytanie:** Ile może wynosić $P(\\mathit{Viagra}|c)$?\n",
"\n", "\n",
"Po przyjęciu takich \"naiwnych założeń\":\n", "Po przyjęciu takich „naiwnych założeń”:\n",
"\n", "\n",
"$$P(d|c) = P(t_1\\dots t_n|c) \\approx P(t_1|c)\\dots P(t_n|c) = \\prod_i^n P(t_i|c)$$" "$$P(d|c) = P(t_1\\dots t_n|c) \\approx P(t_1|c)\\dots P(t_n|c) = \\prod_i^n P(t_i|c)$$"
] ]
@ -306,7 +306,7 @@
"\n", "\n",
"$$f(m, k, T) = \\frac{k+1}{T+m}$$\n", "$$f(m, k, T) = \\frac{k+1}{T+m}$$\n",
"\n", "\n",
"Jest to wygładzanie +1, albo wygładzanie Laplace'a.\n", "Jest to wygładzanie +1, inaczej wygładzanie Laplace'a.\n",
"\n", "\n",
"**Pytanie:** Wymyślić jakiś inny przykład funkcji, która będzie spełniała aksjomaty.\n", "**Pytanie:** Wymyślić jakiś inny przykład funkcji, która będzie spełniała aksjomaty.\n",
"\n", "\n",

View File

@ -144,7 +144,10 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "freelance-controversy", "id": "freelance-controversy",
"metadata": {}, "metadata": {
"jp-MarkdownHeadingCollapsed": true,
"tags": []
},
"source": [ "source": [
"## Uczenie\n", "## Uczenie\n",
"\n", "\n",
@ -154,13 +157,11 @@
"\n", "\n",
"### Metoda gradientu prostego\n", "### Metoda gradientu prostego\n",
"\n", "\n",
"![Morskie Oko - Krzysztof Dudzik](08_files/morskieoko.jpg)\n", "![Morskie oko; Autor:Krzysztof Dudzik; Źródło: [https://pl.wikipedia.org/wiki/Morskie_Oko#/media/Plik:Morskie_Oko_ze_szlaku_przez_%C5%9Awist%C3%B3wk%C4%99.jpg](https://pl.wikipedia.org/wiki/Morskie_Oko#/media/Plik:Morskie_Oko_ze_szlaku_przez_%C5%9Awist%C3%B3wk%C4%99.jpg); Licencja: CC-BY 3.0](08_files/morskieoko.jpg)\n",
"\n",
"(Źródło: https://pl.wikipedia.org/wiki/Morskie_Oko#/media/Plik:Morskie_Oko_ze_szlaku_przez_%C5%9Awist%C3%B3wk%C4%99.jpg, licencja CC BY 3.0)\n",
"\n", "\n",
"Schodź wzdłuż lokalnego spadku funkcji błędu.\n", "Schodź wzdłuż lokalnego spadku funkcji błędu.\n",
"\n", "\n",
"Tak więc w praktyce zamiast podstawiać do wzoru lepiej się uczyć iteracyjnie -\n", "Tak więc w praktyce zamiast podstawiać do wzoru lepiej się uczyć iteracyjnie \n",
" metodą **gradientu prostego** (ang. _gradient descent_).\n", " metodą **gradientu prostego** (ang. _gradient descent_).\n",
"\n", "\n",
"1. Zacznij od byle jakich wag $w_i$ (np. wylosuj)\n", "1. Zacznij od byle jakich wag $w_i$ (np. wylosuj)\n",
@ -209,7 +210,7 @@
"\n", "\n",
"Czym jest wektor $\\vec{x} = (x_1,\\dots,x_n)$? Wiemy, np. reprezentacja tf-idf (być z trikiem z haszowaniem, Word2vec etc.).\n", "Czym jest wektor $\\vec{x} = (x_1,\\dots,x_n)$? Wiemy, np. reprezentacja tf-idf (być z trikiem z haszowaniem, Word2vec etc.).\n",
"\n", "\n",
"![schemat regresji liniowej](08_files/regresja-liniowa-tekst.png)\n" "![Schemat regresji liniowej tekstu](08_files/regresja-liniowa-tekst.png)\n"
] ]
}, },
{ {

View File

@ -26,7 +26,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Kilka uwag dotyczących wektorów\n", "## Kilka uwag dotyczących wektorów\n",
"\n" "\n"
] ]
}, },
@ -78,7 +78,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Funkcja sigmoidalna\n", "## Funkcja sigmoidalna\n",
"\n" "\n"
] ]
}, },
@ -86,7 +86,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Funkcja sigmoidalna zamienia dowolną wartość („sygnał”) w wartość z przedziału $(0,1)$, czyli wartość, która może być interperetowana jako prawdopodobieństwo.\n", "Funkcja sigmoidalna zamienia dowolną wartość („sygnał”) w wartość z przedziału $(0,1)$, czyli wartość, która może być interpretowana jako prawdopodobieństwo.\n",
"\n", "\n",
"$$\\sigma(x) = \\frac{1}{1 + e^{-x}}$$\n", "$$\\sigma(x) = \\frac{1}{1 + e^{-x}}$$\n",
"\n" "\n"
@ -175,7 +175,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"#### PyTorch\n", "### PyTorch\n",
"\n" "\n"
] ]
}, },
@ -283,7 +283,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"#### Wagi\n", "### Wagi\n",
"\n" "\n"
] ]
}, },
@ -307,7 +307,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Regresja liniowa\n", "## Regresja liniowa\n",
"\n" "\n"
] ]
}, },
@ -526,27 +526,25 @@
"Bezpośrednio możemy zastosować do zadania regresji dla tekstu (np.\n", "Bezpośrednio możemy zastosować do zadania regresji dla tekstu (np.\n",
"przewidywanie roku publikacji tekstu).\n", "przewidywanie roku publikacji tekstu).\n",
"\n", "\n",
"![img](./img-linear-regression.png)\n", "![Schemat regresji logistycznej dla tekstu](./img-linear-regression.png)\n",
"\n", "\n",
"W połączeniu z sigmoidą otrzymamy regresją logistyczną, np. dla zadania klasyfikacji tekstu:\n", "W połączeniu z sigmoidą otrzymamy regresją logistyczną, np. dla zadania klasyfikacji tekstu:\n",
"\n", "\n",
"$$p(c|\\vec{x}) = \\sigma(w_0 + w_1x_1 + w_2x_2 + \\dots + w_{|V|}x_{|v})\n", "$$p(c|\\vec{x}) = \\sigma(w_0 + w_1x_1 + w_2x_2 + \\dots + w_{|V|}x_{|v})\n",
"= \\sigma(\\Sigma_{i=0}^{|V|} w_ix_i) = \\sigma(\\vec{w}\\vec{x})$$\n", "= \\sigma(\\Sigma_{i=0}^{|V|} w_ix_i) = \\sigma(\\vec{w}\\vec{x})$$\n",
"\n", "\n",
"![img](./img-logistic-regression.png)\n",
"\n",
"Tak sieć będzie aktywowana dla tekstu <u>aardvark in Aachen</u>:\n", "Tak sieć będzie aktywowana dla tekstu <u>aardvark in Aachen</u>:\n",
"\n", "\n",
"![img](./img-logistic-regression-aardvark.png)\n", "![Schemat regresji logistycznej dla przykładowego tekstu](./img-logistic-regression-aardvark.png)\n",
"\n", "\n",
"Regresje logistyczną (liniową zresztą też) dla tekstu możemy połączyć z trikiem z haszowaniem:\n", "Regresję logistyczną (liniową zresztą też) dla tekstu możemy połączyć z trikiem z haszowaniem:\n",
"\n", "\n",
"$$p(c|\\vec{x}) = \\sigma(w_0 + w_1x_1 + w_2x_2 + \\dots + w_{2^b}x_{2^b})\n", "$$p(c|\\vec{x}) = \\sigma(w_0 + w_1x_1 + w_2x_2 + \\dots + w_{2^b}x_{2^b})\n",
"= \\sigma(\\Sigma_{i=0}^{2^b} w_ix_i) = \\sigma(\\vec{w}\\vec{x})$$ \n", "= \\sigma(\\Sigma_{i=0}^{2^b} w_ix_i) = \\sigma(\\vec{w}\\vec{x})$$ \n",
"{\\small hashing function $H : V \\rightarrow \\{1,\\dots,2^b\\}$,\n", "{\\small hashing function $H : V \\rightarrow \\{1,\\dots,2^b\\}$,\n",
" e.g. MurmurHash3}\n", " e.g. MurmurHash3}\n",
"\n", "\n",
"![img](./img-logistic-regression-hashing.png)\n", "![Schemat regresji logistycznej dla tekstu z zastosowaniem hashing trick](./img-logistic-regression-hashing.png)\n",
"\n", "\n",
"****Pytanie:**** Jaki tekst otrzyma na pewno taką samą klasę jak <u>aardvark in Aachen</u>?\n", "****Pytanie:**** Jaki tekst otrzyma na pewno taką samą klasę jak <u>aardvark in Aachen</u>?\n",
"\n" "\n"
@ -595,16 +593,16 @@
"Mnożenie macierzy przez wektor można interpretować jako zrównolegloną operację mnożenie wektora przez wektor.\n", "Mnożenie macierzy przez wektor można interpretować jako zrównolegloną operację mnożenie wektora przez wektor.\n",
"\n", "\n",
"$$\\left[\\begin{array}{ccc}\n", "$$\\left[\\begin{array}{ccc}\n",
" \\alert<2>{1.0} & \\alert<2>{-2.0} & \\alert<2>{3.0} \\\\\n", " 1.0 & -2.0 & 3.0 \\\\\n",
" \\alert<3>{-2.0} & \\alert<3>{0.0} & \\alert<3>{10.0}\\end{array}\\right]\n", " -2.0 & 0.0 & 10.0\\end{array}\\right]\n",
" \\left[\\begin{array}{c}\n", " \\left[\\begin{array}{c}\n",
" \\alert<2-3>{1.0} \\\\\n", " 1.0 \\\\\n",
" \\alert<2-3>{-0.5} \\\\\n", " -0.5 \\\\\n",
" \\alert<2-3>{2.0}\\end{array}\\right]\n", " 2.0\\end{array}\\right]\n",
" =\n", " =\n",
" \\left[\\begin{array}{c}\n", " \\left[\\begin{array}{c}\n",
" \\uncover<2->{\\alert<2>{8.0}} \\\\\n", " 8.0 \\\\\n",
" \\uncover<3->{\\alert<3>{18.0}}\\end{array}\\right]$$\n", " 8.0\\end{array}\\right]$$\n",
"\n", "\n",
"Jeśli przemnożymy macierz $n \\times m$ przez wektor kolumnowy o długości\n", "Jeśli przemnożymy macierz $n \\times m$ przez wektor kolumnowy o długości\n",
"$m$, otrzymamy wektor o rozmiarze $n$.\n", "$m$, otrzymamy wektor o rozmiarze $n$.\n",
@ -660,7 +658,7 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"Warstwa liniowa polega na przemnożeniu wejścia przez macierz. Można\n", "Warstwa liniowa polega na przemnożeniu wejścia przez macierz. Można\n",
"to intepretować jako zrównolegloną operację regresji liniowej (równolegle\n", "to interpretować jako zrównolegloną operację regresji liniowej (równolegle\n",
"uczymy czy wykonujemy $n$ regresji liniowych).\n", "uczymy czy wykonujemy $n$ regresji liniowych).\n",
"\n" "\n"
] ]
@ -731,7 +729,7 @@
"\n", "\n",
"Oto przykład prostej dwuwarstwowej sieci neuronowej do klasyfikacji binarnej.\n", "Oto przykład prostej dwuwarstwowej sieci neuronowej do klasyfikacji binarnej.\n",
"\n", "\n",
"![img](./img-feed-forward.png)\n", "![Schemat dwuwarstwowej sieci neuronowej do klasyfikacji binarnej tekstu](./img-feed-forward.png)\n",
"\n" "\n"
] ]
}, },
@ -747,7 +745,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"W klasyfikacji wieloklasowej należy zwrócić musimy zwrócić rozkład\n", "W klasyfikacji wieloklasowej należy zwrócić rozkład\n",
"prawdopodobieństwa po wszystkich klasach, w przeciwieństwie do\n", "prawdopodobieństwa po wszystkich klasach, w przeciwieństwie do\n",
"klasyfikacji binarnej, gdzie wystarczy zwrócić jedną liczbę —\n", "klasyfikacji binarnej, gdzie wystarczy zwrócić jedną liczbę —\n",
"prawdopodobieństwo pozytywnej klasy ($p$; prawdopodobieństwo drugiej\n", "prawdopodobieństwo pozytywnej klasy ($p$; prawdopodobieństwo drugiej\n",
@ -770,7 +768,7 @@
"$$s(z_i) = \\frac{z_i}{\\Sigma_{j=1}^k z_j}$$\n", "$$s(z_i) = \\frac{z_i}{\\Sigma_{j=1}^k z_j}$$\n",
"\n", "\n",
"To rozwiązanie zadziała błędnie dla liczb ujemnych, trzeba najpierw\n", "To rozwiązanie zadziała błędnie dla liczb ujemnych, trzeba najpierw\n",
"użyć funkcji monotonicznej, która przekształaca $\\mathcal{R}$ na $\\mathcal{R^+}$.\n", "użyć funkcji monotonicznej, która przekształca $\\mathcal{R}$ na $\\mathcal{R^+}$.\n",
"Naturalna funkcja tego rodzaju to funkcja wykładnicza $\\exp{x} = e^x$.\n", "Naturalna funkcja tego rodzaju to funkcja wykładnicza $\\exp{x} = e^x$.\n",
"Tym sposobem dochodzimy do funkcji softmax:\n", "Tym sposobem dochodzimy do funkcji softmax:\n",
"\n", "\n",
@ -815,7 +813,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"![img](./softmax.png \"Softmax\")\n", "![Schemat funkcji Softmax](./softmax.png \"Softmax\")\n",
"\n" "\n"
] ]
}, },
@ -1238,7 +1236,7 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"Ze względów obliczeniowych często korzysta się z funkcji **LogSoftmax**\n", "Ze względów obliczeniowych często korzysta się z funkcji **LogSoftmax**\n",
"która zwraca logarytmy pradopodobieństw (*logproby*).\n", "która zwraca logarytmy prawdopodobieństw (*logproby*).\n",
"\n", "\n",
"$$log s(z_i) = log \\frac{e^{z_i}}{\\Sigma_{j=1}^k e^{z_j}}$$\n", "$$log s(z_i) = log \\frac{e^{z_i}}{\\Sigma_{j=1}^k e^{z_j}}$$\n",
"\n" "\n"
@ -1776,7 +1774,7 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"W czasie inferencji mamy ustalone wagi funkcji $\\vec{v}(\\dots)$ oraz\n", "W czasie inferencji mamy ustalone wagi funkcji $\\vec{v}(\\dots)$ oraz\n",
"macierz $V$. Szukamy sekwencji $y$ która maksymalizuje prawdopodobieństwo estymowane przez model:\n", "macierz $V$. Szukamy sekwencji $y$, która maksymalizuje prawdopodobieństwo estymowane przez model:\n",
"\n", "\n",
"$$y = \\underset{l}{\\operatorname{argmax}} \\hat{p}(l|t^1,\\dots,t^K)$$\n", "$$y = \\underset{l}{\\operatorname{argmax}} \\hat{p}(l|t^1,\\dots,t^K)$$\n",
"\n", "\n",
@ -1819,7 +1817,7 @@
"\n", "\n",
"$$y^i = b[i, y^{i+1}]$$\n", "$$y^i = b[i, y^{i+1}]$$\n",
"\n", "\n",
"![img](./crf-viterbi.png)\n", "![CRF - Algorytm Viterbiego](./crf-viterbi.png)\n",
"\n" "\n"
] ]
}, },

View File

@ -34,7 +34,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"#### Regresja liniowa/logistyczna lub klasyfikacja wieloklasowa na całym tekście\n", "### Regresja liniowa/logistyczna lub klasyfikacja wieloklasowa na całym tekście\n",
"\n" "\n"
] ]
}, },
@ -179,7 +179,7 @@
"\n", "\n",
"Taką sieć RNN można przedstawić schematycznie w następujący sposób:\n", "Taką sieć RNN można przedstawić schematycznie w następujący sposób:\n",
"\n", "\n",
"![img](./img-rnn.png)\n", "![Pojedynczy krok sieci rekurencyjnej](./img-rnn.png)\n",
"\n", "\n",
"Zauważmy, że zamiast macierzy $W$ działającej na konkatenacji wektorów można wprowadzić dwie\n", "Zauważmy, że zamiast macierzy $W$ działającej na konkatenacji wektorów można wprowadzić dwie\n",
"macierze $U$ i $V$ i tak zapisać wzór:\n", "macierze $U$ i $V$ i tak zapisać wzór:\n",
@ -188,12 +188,12 @@
"\n", "\n",
"Jeszcze inne spojrzenie na sieć RNN:\n", "Jeszcze inne spojrzenie na sieć RNN:\n",
"\n", "\n",
"![img](./rnn.png)\n", "![Pojedynczy krok sieci rekurencyjnej II](./rnn.png)\n",
"\n", "\n",
"Powyższy rysunek przedstawia pojedynczy krok sieci RNN. Dla całego\n", "Powyższy rysunek przedstawia pojedynczy krok sieci RNN. Dla całego\n",
"wejścia (powiedzmy, 3-wyrazowego) możemy sieć rozwinąć (*unroll*):\n", "wejścia (powiedzmy, 3-wyrazowego) możemy sieć rozwinąć (*unroll*):\n",
"\n", "\n",
"![img](./rnn-seq.png)\n", "![Rozwinięta sieć rekurencyjna](./rnn-seq.png)\n",
"\n" "\n"
] ]
}, },
@ -202,7 +202,8 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"#### Zastosowanie sieci RNN do etykietowania sekwencji\n", "#### Zastosowanie sieci RNN do etykietowania sekwencji\n",
"\n" "\n",
"Sieć RNN może w prosty sposób być użyta do etykietowania sekwencji (w każdym kroku zwracamy etykietę)."
] ]
}, },
{ {
@ -228,7 +229,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Sieci RNN z bramkami\n", "## Sieci RNN z bramkami\n",
"\n" "\n"
] ]
}, },

View File

@ -507,7 +507,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### BPE\n", "## BPE\n",
"\n" "\n"
] ]
}, },
@ -532,7 +532,7 @@
"słownika. W każdym kroku szukamy najczęstszego bigramu, od tego\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", "momentu traktujemy go jako całostkę (wkładamy go do „pudełka”).\n",
"\n", "\n",
"![img](./bpe.png)\n", "![Sekwencja kroków algorytmu BPE dla przykładowego zdania](./bpe.png)\n",
"\n" "\n"
] ]
}, },

View File

@ -36,11 +36,11 @@
"source": [ "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", "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", "\n",
"![img](./ie-seqlab.png)\n", "![Ekstrakcja informacji jako etykietowanie sekwencji, schemat](./ie-seqlab.png)\n",
"\n", "\n",
"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ę.\n", "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ę.\n",
"\n", "\n",
"![img](./ie-gener.png)\n", "![Ekstrakcja informacji w podejściu generatywnym](./ie-gener.png)\n",
"\n", "\n",
"To podejście może się wydawać trudniejsze niż etykietowanie sekwencji, ale wystarczająco zaawansowanej architekturze sieci, jest wykonalne.\n", "To podejście może się wydawać trudniejsze niż etykietowanie sekwencji, ale wystarczająco zaawansowanej architekturze sieci, jest wykonalne.\n",
"\n", "\n",
@ -56,7 +56,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Atencja\n", "## Atencja\n",
"\n" "\n"
] ]
}, },

View File

@ -2,15 +2,13 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"collapsed": false
},
"source": [ "source": [
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n", "<div class=\"alert alert-block alert-info\">\n",
"<h1> Ekstrakcja informacji </h1>\n", "<h1> Ekstrakcja informacji </h1>\n",
"<h2> 14. <i>Pretrenowane modele j\u0119zyka</i> [wyk\u0142ad]</h2> \n", "<h2> 14. <i>Pretrenowane modele języka</i> [wykład]</h2> \n",
"<h3> Filip Grali\u0144ski (2021)</h3>\n", "<h3> Filip Graliński (2021)</h3>\n",
"</div>\n", "</div>\n",
"\n", "\n",
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)" "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
@ -28,27 +26,27 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"System AlphaZero uczy si\u0119 graj\u0105c sam ze sob\u0105 \u2014 wystarczy 24 godziny,\n", "System AlphaZero uczy się grając sam ze sobą — wystarczy 24 godziny,\n",
"by system nauczy\u0142 si\u0119 gra\u0107 w szachy lub go na nadludzkim poziomie.\n", "by system nauczył się grać w szachy lub go na nadludzkim poziomie.\n",
"\n", "\n",
"**Pytanie**: Dlaczego granie samemu ze sob\u0105 nie jest dobrym sposobem\n", "**Pytanie**: Dlaczego granie samemu ze sobą nie jest dobrym sposobem\n",
" nauczenia si\u0119 grania w szachy dla cz\u0142owieka, a dla maszyny jest?\n", " nauczenia się grania w szachy dla człowieka, a dla maszyny jest?\n",
"\n", "\n",
"Co jest odpowiednikiem grania samemu ze sob\u0105 w \u015bwiecie przetwarzania tekstu?\n", "Co jest odpowiednikiem grania samemu ze sobą w świecie przetwarzania tekstu?\n",
"Tzn. **pretrenowanie** (*pretraining*) na du\u017cym korpusie tekstu. (Tekst jest tani!)\n", "Tzn. **pretrenowanie** (*pretraining*) na dużym korpusie tekstu. (Tekst jest tani!)\n",
"\n", "\n",
"Jest kilka sposob\u00f3w na pretrenowanie modelu, w ka\u017cdym razie sprowadza\n", "Jest kilka sposobów na pretrenowanie modelu, w każdym razie sprowadza\n",
"si\u0119 do odgadywania nast\u0119pnego b\u0105d\u017a zamaskowanego s\u0142owa.\n", "się do odgadywania następnego bądź zamaskowanego słowa.\n",
"W ka\u017cdym razie zawsze stosujemy softmax (by\u0107 mo\u017ce ze \u201esztuczkami\u201d takimi jak\n", "W każdym razie zawsze stosujemy softmax (być może ze „sztuczkami” takimi jak\n",
"negatywne pr\u00f3bkowanie albo hierarchiczny softmax) na pewnej **reprezentacji kontekstowej**:\n", "negatywne próbkowanie albo hierarchiczny softmax) na pewnej **reprezentacji kontekstowej**:\n",
"\n", "\n",
"$$\\vec{p} = \\operatorname{softmax}(f(\\vec{c})).$$\n", "$$\\vec{p} = \\operatorname{softmax}(f(\\vec{c})).$$\n",
"\n", "\n",
"Model jest karany u\u017cywaj\u0105c funkcji log loss:\n", "Model jest karany przy użyciu funkcji log loss:\n",
"\n", "\n",
"$$-\\log(p_j),$$\n", "$$-\\log(p_j),$$\n",
"\n", "\n",
"gdzie $w_j$ jest wyrazem, kt\u00f3ry pojawi\u0142 si\u0119 rzeczywi\u015bcie w korpusie.\n", "gdzie $w_j$ jest wyrazem, który pojawił się rzeczywiście w korpusie.\n",
"\n" "\n"
] ]
}, },
@ -56,7 +54,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Przewidywanie s\u0142owa (GPT-2)\n", "## Przewidywanie słowa (GPT-2)\n",
"\n" "\n"
] ]
}, },
@ -64,10 +62,10 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Jeden ze sposob\u00f3w pretrenowania modelu to po prostu przewidywanie\n", "Jeden ze sposobów pretrenowania modelu to po prostu przewidywanie\n",
"nast\u0119pnego s\u0142owa.\n", "następnego słowa.\n",
"\n", "\n",
"Zainstalujmy najpierw bibliotek\u0119 transformers.\n", "Zainstalujmy najpierw bibliotekę transformers.\n",
"\n" "\n"
] ]
}, },
@ -95,36 +93,36 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"[('\u00c2\u0142', 0.6182783842086792),\n", "[('Âł', 0.6182783842086792),\n",
" ('\u00c8', 0.1154019758105278),\n", " ('È', 0.1154019758105278),\n",
" ('\u00d1\u0123', 0.026960616931319237),\n", " ('Ñģ', 0.026960616931319237),\n",
" ('_____', 0.024418892338871956),\n", " ('_____', 0.024418892338871956),\n",
" ('________', 0.014962316490709782),\n", " ('________', 0.014962316490709782),\n",
" ('\u00c3\u0124', 0.010653386823832989),\n", " ('ÃĤ', 0.010653386823832989),\n",
" ('\u00e4\u00b8\u0143', 0.008340531960129738),\n", " ('ä¸Ń', 0.008340531960129738),\n",
" ('\u00d1', 0.007557711564004421),\n", " ('Ñ', 0.007557711564004421),\n",
" ('\u00ca', 0.007046067621558905),\n", " ('Ê', 0.007046067621558905),\n",
" ('\u00e3\u0122', 0.006875576451420784),\n", " ('ãĢ', 0.006875576451420784),\n",
" ('ile', 0.006685272324830294),\n", " ('ile', 0.006685272324830294),\n",
" ('____', 0.006307446397840977),\n", " ('____', 0.006307446397840977),\n",
" ('\u00e2\u0122\u012d', 0.006306538358330727),\n", " ('âĢĭ', 0.006306538358330727),\n",
" ('\u00d1\u0122', 0.006197483278810978),\n", " ('ÑĢ', 0.006197483278810978),\n",
" ('\u0120Belarus', 0.006108700763434172),\n", " ('ĠBelarus', 0.006108700763434172),\n",
" ('\u00c6', 0.005720408633351326),\n", " ('Æ', 0.005720408633351326),\n",
" ('\u0120Poland', 0.0053678699769079685),\n", " ('ĠPoland', 0.0053678699769079685),\n",
" ('\u00e1\u00b9', 0.004606408067047596),\n", " ('á¹', 0.004606408067047596),\n",
" ('\u00ee\u0122', 0.004161055199801922),\n", " ('îĢ', 0.004161055199801922),\n",
" ('????', 0.004056799225509167),\n", " ('????', 0.004056799225509167),\n",
" ('_______', 0.0038176667876541615),\n", " ('_______', 0.0038176667876541615),\n",
" ('\u00e4\u00b8', 0.0036082742735743523),\n", " ('ä¸', 0.0036082742735743523),\n",
" ('\u00cc', 0.003221835708245635),\n", " ('Ì', 0.003221835708245635),\n",
" ('urs', 0.003080119378864765),\n", " ('urs', 0.003080119378864765),\n",
" ('________________', 0.0027312245219945908),\n", " ('________________', 0.0027312245219945908),\n",
" ('\u0120Lithuania', 0.0023860156070441008),\n", " ('ĠLithuania', 0.0023860156070441008),\n",
" ('ich', 0.0021211160346865654),\n", " ('ich', 0.0021211160346865654),\n",
" ('iz', 0.002069818088784814),\n", " ('iz', 0.002069818088784814),\n",
" ('vern', 0.002001357264816761),\n", " ('vern', 0.002001357264816761),\n",
" ('\u00c5\u0124', 0.001717406208626926)]" " ('ÅĤ', 0.001717406208626926)]"
] ]
}, },
"execution_count": 17, "execution_count": 17,
@ -161,22 +159,22 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Zalety tego podej\u015bcia:\n", "Zalety tego podejścia:\n",
"\n", "\n",
"- prostota,\n", "- prostota,\n",
"- dobra podstawa do strojenia system\u00f3w generowania tekstu zw\u0142aszcza\n", "- dobra podstawa do strojenia systemów generowania tekstu zwłaszcza\n",
" \u201eotwartego\u201d (systemy dialogowe, generowanie (fake) news\u00f3w, streszczanie tekstu),\n", " „otwartego” (systemy dialogowe, generowanie (fake) newsów, streszczanie tekstu),\n",
" ale niekoniecznie t\u0142umaczenia maszynowego,\n", " ale niekoniecznie tłumaczenia maszynowego,\n",
"- zaskakuj\u0105ca skuteczno\u015b\u0107 przy uczeniu *few-shot* i *zero-shot*.\n", "- zaskakująca skuteczność przy uczeniu *few-shot* i *zero-shot*.\n",
"\n", "\n",
"Wady:\n", "Wady:\n",
"\n", "\n",
"- asymetryczno\u015b\u0107, przetwarzanie tylko z lewej do prawej, preferencja\n", "- asymetryczność, przetwarzanie tylko z lewej do prawej, preferencja\n",
" dla lewego kontekstu,\n", " dla lewego kontekstu,\n",
"- mniejsza skuteczno\u015b\u0107 przy dostrajaniu do zada\u0144 klasyfikacji i innych zada\u0144\n", "- mniejsza skuteczność przy dostrajaniu do zadań klasyfikacji i innych zadań\n",
" niepolegaj\u0105cych na prostym generowaniu.\n", " niepolegających na prostym generowaniu.\n",
"\n", "\n",
"Przyk\u0142ady modeli: GPT, GPT-2, GPT-3, DialoGPT.\n", "Przykłady modeli: GPT, GPT-2, GPT-3, DialoGPT.\n",
"\n" "\n"
] ]
}, },
@ -184,7 +182,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Maskowanie s\u0142\u00f3w (BERT)\n", "## Maskowanie słów (BERT)\n",
"\n" "\n"
] ]
}, },
@ -192,18 +190,18 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Inn\u0105 metod\u0105 jest maskowanie s\u0142\u00f3w (*Masked Language Modeling*, *MLM*).\n", "Inną metodą jest maskowanie słów (*Masked Language Modeling*, *MLM*).\n",
"\n", "\n",
"W tym podej\u015bciu losowe wybrane zast\u0119pujemy losowe s\u0142owa specjalnym\n", "W tym podejściu losowe wybrane zastępujemy losowe słowa specjalnym\n",
"tokenem (`[MASK]`) i ka\u017cemy modelowi odgadywa\u0107 w ten spos\u00f3b\n", "tokenem (`[MASK]`) i każemy modelowi odgadywać w ten sposób\n",
"zamaskowane s\u0142owa (z uwzgl\u0119dnieniem r\u00f3wnie\u017c prawego kontekstu!).\n", "zamaskowane słowa (z uwzględnieniem również prawego kontekstu!).\n",
"\n", "\n",
"M\u00f3ci\u0105c \u015bci\u015ble, w jednym z pierwszych modeli tego typu (BERT)\n", "Móciąc ściśle, w jednym z pierwszych modeli tego typu (BERT)\n",
"zastosowano schemat, w kt\u00f3rym r\u00f3wnie\u017c niezamaskowane s\u0142owa s\u0105 odgadywane (!):\n", "zastosowano schemat, w którym również niezamaskowane słowa są odgadywane (!):\n",
"\n", "\n",
"- wybieramy losowe 15% wyraz\u00f3w do odgadni\u0119cia\n", "- wybieramy losowe 15% wyrazów do odgadnięcia\n",
"- 80% z nich zast\u0119pujemy tokenem `[MASK]`,\n", "- 80% z nich zastępujemy tokenem `[MASK]`,\n",
"- 10% zast\u0119pujemy innym losowym wyrazem,\n", "- 10% zastępujemy innym losowym wyrazem,\n",
"- 10% pozostawiamy bez zmian.\n", "- 10% pozostawiamy bez zmian.\n",
"\n" "\n"
] ]
@ -225,16 +223,16 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W USA. (score: 0.16715531051158905)\n", "W którym państwie leży Bombaj? W USA. (score: 0.16715531051158905)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W India. (score: 0.09912960231304169)\n", "W którym państwie leży Bombaj? W India. (score: 0.09912960231304169)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W Indian. (score: 0.039642028510570526)\n", "W którym państwie leży Bombaj? W Indian. (score: 0.039642028510570526)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W Nepal. (score: 0.027137665078043938)\n", "W którym państwie leży Bombaj? W Nepal. (score: 0.027137665078043938)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W Pakistan. (score: 0.027065709233283997)\n", "W którym państwie leży Bombaj? W Pakistan. (score: 0.027065709233283997)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W Polsce. (score: 0.023737527430057526)\n", "W którym państwie leży Bombaj? W Polsce. (score: 0.023737527430057526)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W .... (score: 0.02306722290813923)\n", "W którym państwie leży Bombaj? W .... (score: 0.02306722290813923)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W Bangladesh. (score: 0.022106658667325974)\n", "W którym państwie leży Bombaj? W Bangladesh. (score: 0.022106658667325974)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W .... (score: 0.01628892682492733)\n", "W którym państwie leży Bombaj? W .... (score: 0.01628892682492733)\n",
"W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W Niemczech. (score: 0.014501162804663181)\n" "W którym państwie leży Bombaj? W Niemczech. (score: 0.014501162804663181)\n"
] ]
} }
], ],
@ -245,7 +243,7 @@
"tokenizer = AutoTokenizer.from_pretrained(\"xlm-roberta-large\")\n", "tokenizer = AutoTokenizer.from_pretrained(\"xlm-roberta-large\")\n",
"model = AutoModelWithLMHead.from_pretrained(\"xlm-roberta-large\")\n", "model = AutoModelWithLMHead.from_pretrained(\"xlm-roberta-large\")\n",
"\n", "\n",
"sequence = f'W kt\u00f3rym pa\u0144stwie le\u017cy Bombaj? W {tokenizer.mask_token}.'\n", "sequence = f'W którym państwie leży Bombaj? W {tokenizer.mask_token}.'\n",
"\n", "\n",
"input_ids = tokenizer.encode(sequence, return_tensors=\"pt\")\n", "input_ids = tokenizer.encode(sequence, return_tensors=\"pt\")\n",
"mask_token_index = torch.where(input_ids == tokenizer.mask_token_id)[1]\n", "mask_token_index = torch.where(input_ids == tokenizer.mask_token_id)[1]\n",
@ -265,7 +263,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Przyk\u0142ady: BERT, RoBERTa (r\u00f3wnie\u017c Polish RoBERTa).\n", "Przykłady: BERT, RoBERTa (również Polish RoBERTa).\n",
"\n" "\n"
] ]
}, },
@ -273,7 +271,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"### Podej\u015bcie generatywne (koder-dekoder).\n", "## Podejście generatywne (koder-dekoder).\n",
"\n" "\n"
] ]
}, },
@ -281,8 +279,8 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"System ma wygenerowa\u0107 odpowied\u017a na r\u00f3\u017cne pytania (r\u00f3wnie\u017c\n", "System ma wygenerować odpowiedź na różne pytania (również\n",
"odpowiadaj\u0105ce zadaniu MLM), np.:\n", "odpowiadające zadaniu MLM), np.:\n",
"\n", "\n",
"- \"translate English to German: That is good.\" => \"Das ist gut.\"\n", "- \"translate English to German: That is good.\" => \"Das ist gut.\"\n",
"- \"cola sentence: The course is jumping well.\" => \"not acceptable\"\n", "- \"cola sentence: The course is jumping well.\" => \"not acceptable\"\n",
@ -355,17 +353,20 @@
"source": [ "source": [
"(Zob. [https://arxiv.org/pdf/1910.10683.pdf](https://arxiv.org/pdf/1910.10683.pdf))\n", "(Zob. [https://arxiv.org/pdf/1910.10683.pdf](https://arxiv.org/pdf/1910.10683.pdf))\n",
"\n", "\n",
"Przyk\u0142ad: T5, mT5\n", "Przykład: T5, mT5\n",
"\n" "\n"
] ]
} }
], ],
"metadata": { "metadata": {
"author": "Filip Graliński",
"email": "filipg@amu.edu.pl",
"kernelspec": { "kernelspec": {
"display_name": "Python 3 (ipykernel)", "display_name": "Python 3 (ipykernel)",
"language": "python", "language": "python",
"name": "python3" "name": "python3"
}, },
"lang": "pl",
"language_info": { "language_info": {
"codemirror_mode": { "codemirror_mode": {
"name": "ipython", "name": "ipython",
@ -379,10 +380,7 @@
"version": "3.9.6" "version": "3.9.6"
}, },
"org": null, "org": null,
"author": "Filip Grali\u0144ski", "subtitle": "14.Pretrenowane modele języka[wykład]",
"email": "filipg@amu.edu.pl",
"lang": "pl",
"subtitle": "14.Pretrenowane modele j\u0119zyka[wyk\u0142ad]",
"title": "Ekstrakcja informacji", "title": "Ekstrakcja informacji",
"year": "2021" "year": "2021"
}, },

View File

@ -219,7 +219,10 @@
"- $V$ = $EW^V$\n", "- $V$ = $EW^V$\n",
"\n", "\n",
"W kolejnych warstwach zamiast $E$ wykorzystywane jest wyjście z poprzedniej warstwy.\n", "W kolejnych warstwach zamiast $E$ wykorzystywane jest wyjście z poprzedniej warstwy.\n",
"\n" "\n",
"## Zastosowanie w ekstrakcji informacji\n",
"\n",
"W prosty sposób możemy do sieci Transformer dołączyć głowicę realizującą etykietowanie sekwencji."
] ]
}, },
{ {