Merge branch 'master' of git.wmi.amu.edu.pl:filipg/aitech-eks
This commit is contained in:
commit
f351417476
390
wyk/06_Uczenie_maszynowe.ipynb
Normal file
390
wyk/06_Uczenie_maszynowe.ipynb
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Uczenie maszynowe i jego wyzwania\n",
|
||||||
|
"\n",
|
||||||
|
"Uwaga: my skupiamy się na uczeniu maszynowym na tekstach (i ostatecznie zmierzamy do ekstrakcji z dokumentów tekstowych).\n",
|
||||||
|
"\n",
|
||||||
|
"## Oznaczenia\n",
|
||||||
|
"\n",
|
||||||
|
"* $x$ — wejście (często interpretowane jako wektor $\\vec{x}$) \n",
|
||||||
|
"* $y$ — oczekiwane wyjście\n",
|
||||||
|
"* $\\hat{y}$ — przewidywane wyjście\n",
|
||||||
|
"* $(X, Y)$, zbiór wejść $X$ traktujemy jako listę $X = (x_1, \\dots, x_N)$ albo jako macierz, a $Y$ jest na ogół ciągiem liczb albo wektorem\n",
|
||||||
|
"* $V$ — słownik (zbiór słów/symboli)\n",
|
||||||
|
" * $V^*$ — zbiór wszystkich tekstów (ciągów na $V$)\n",
|
||||||
|
"* $C = \\{c_1, c_2, \\dots, c_n\\}$ — zbiór klas\n",
|
||||||
|
" * $\\bar{c}$ - dopełnienie klasy $c$\n",
|
||||||
|
"* $L = \\{l_1, l_2, \\dots, l_n\\}$ — zbiór etykiet/tagów (_labels_/_tags_)\n",
|
||||||
|
" * czasami wymiennie używać będziemy terminów klasa oraz etykieta/tag\n",
|
||||||
|
" * $L^*$ — zbiór wszystkich ciągów etykiet\n",
|
||||||
|
"* $q$ — zapytanie\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Rekomendacje książkowe\n",
|
||||||
|
"\n",
|
||||||
|
"(Bez aparatu matematycznego! Na przykład do polecenia laikowi.)\n",
|
||||||
|
"\n",
|
||||||
|
"* Stanisław Lem, _Summa technologiae_, Wydawnictwo Literackie, 1964\n",
|
||||||
|
" * może zacząć od spojrzenia, jak kiedyś sobie to wyobrażano?\n",
|
||||||
|
"* Pedro Domingos, _Naczelny Algorytm. Jak jego odkrycie zmieni nasz świat_, Helion, 2016\n",
|
||||||
|
" * książka się trochę zestarzała, czas pokazał, że autor nie do końca trafnie przewidział, jak się dalej potoczą losy uczenia maszynowego (sieci neuronowe zdecydowanie wygrały)\n",
|
||||||
|
" * ... ale bardzo ciekawe spostrzeżenia, dobrze się czyta\n",
|
||||||
|
"* Kai-Fu Lee, _Inteligencja sztuczna, rewolucja prawdziwa_, Media Rodzina, 2019.\n",
|
||||||
|
" * ciekawe w kontekście ekonomicznym, szczególnie Chin\n",
|
||||||
|
" \n",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Podstawowa idea\n",
|
||||||
|
"\n",
|
||||||
|
"**Uczenie maszynowe to odwrotność programowania** (trochę tak jak $\\sqrt{...}$ jest odwrotnością $^2$)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"![Uczenie maszynowe a programowanie](./uczenie-a-programowanie.png)\n",
|
||||||
|
"\n",
|
||||||
|
"(Na razie trochę upraszczamy - odnosimy się tylko do uczenia nienadzorowanego.)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 5 epok uczenia maszynowego\n",
|
||||||
|
"\n",
|
||||||
|
"### I. Systemy regułowe\n",
|
||||||
|
"\n",
|
||||||
|
"Systemy regułowe, wyrażenia regularne, systemy eksperckie, programowanie logiczne (Prolog)\n",
|
||||||
|
"\n",
|
||||||
|
"Praca człowieka: tworzenie reguł (czasochłonne!)\n",
|
||||||
|
"\n",
|
||||||
|
"### II. Proste algorytmy uczenia maszynowego (lata 90.)\n",
|
||||||
|
"\n",
|
||||||
|
"Naiwny klasyfikator bayesowskie, regresja logistyczna, SVM, XGBoost\n",
|
||||||
|
"\n",
|
||||||
|
"Praca człowieka: inżynieria cech, optymalizacja hiperparametrów, unikanie przeuczenia\n",
|
||||||
|
"\n",
|
||||||
|
"### III. Sieci neuronowe 1 - ucz na _big data_ (2012-2016)\n",
|
||||||
|
"\n",
|
||||||
|
"Sieci feed-forward, splotowe, LSTM; wymagane duże zbiory uczące (w trybie nadzorowanym).\n",
|
||||||
|
"\n",
|
||||||
|
"Praca człowieka: specyficzna architektura, przygotowanie dużego zbioru danych\n",
|
||||||
|
"\n",
|
||||||
|
"### IV. Sieci neuronowe 2 - pretrenuj i dostrajaj (2017-2020)\n",
|
||||||
|
"\n",
|
||||||
|
"Sieci konwolucyjne, LSTM (ELMo), Transformer (BERT). Zbiory uczące do uczenia nadzorowanego nie muszą być obszerne.\n",
|
||||||
|
"\n",
|
||||||
|
"Praca człowieka: dostrajanie modelu.\n",
|
||||||
|
"\n",
|
||||||
|
"### V. Sieci neuronowe 3 - pretrenuj i... po po prostu korzystaj (2019-)\n",
|
||||||
|
"\n",
|
||||||
|
"Duże wielowarstwowe generatywne modele Transformer (GPT-2/3, T5), uczenie few-, one- i zero-shot.\n",
|
||||||
|
"\n",
|
||||||
|
"Praca człowieka: jak sformułować zadanie w języku naturalnym?\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Rodzaje uczenia maszynowego\n",
|
||||||
|
"\n",
|
||||||
|
"* uczenie nienadzorowane (_unsupervised learning_)\n",
|
||||||
|
"* uczenie nadzorowane (_supervised learning_)\n",
|
||||||
|
" * predykcja prostej wartości\n",
|
||||||
|
" * klasyfikacja\n",
|
||||||
|
" * klasyfikacja binarna\n",
|
||||||
|
" * klasyfikacja wieloklasowa\n",
|
||||||
|
" * regresja\n",
|
||||||
|
" * ekstrakcja informacji \n",
|
||||||
|
" * zadania _seq2seq_\n",
|
||||||
|
" * etykietowanie sekwencji (_sequence labeling_)\n",
|
||||||
|
" * tłumaczenie maszynowe (szeroko rozumiane)\n",
|
||||||
|
" * automatyczne streszczanie (sumaryzacja) \n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Uczenie maszynowe - widok z góry\n",
|
||||||
|
"\n",
|
||||||
|
"![Uczenie maszynowe - schemat](./uczenie-schemat.png)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Wyzwania uczenia maszynowego\n",
|
||||||
|
"\n",
|
||||||
|
"Zbiór danych (_data set_) - w uczeniu nadzorowanym po prostu zestaw danych wejściowych i oczekiwanych danych wyjściowych $(X, Y)$.\n",
|
||||||
|
"Wyzwanie uczenia maszynowego (_ML challenge_) - ustandaryzowany zbiór danych, podzielony na zbiór uczący i zbiory testowe, z określoną metryką ewaluacji.\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zob. listę na stronie https://gonito.net/list-challenges"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Uczenie nadzorowane\n",
|
||||||
|
"\n",
|
||||||
|
"#### Klasyfikacja binarna\n",
|
||||||
|
"\n",
|
||||||
|
"$$V^* \\mapsto \\{c,\\bar{c}\\}$$"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Przykłady:\n",
|
||||||
|
" \n",
|
||||||
|
"* klasyfikacja spam/nie-spam \n",
|
||||||
|
"* https://gonito.net/challenge/petite-difference-challenge2\n",
|
||||||
|
"* https://gonito.net/challenge/sentiment-by-emoticons\n",
|
||||||
|
"* https://gonito.net/challenge/sane-words"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"Na platformie Gonito wyzwania (i zgłoszenia) są dostępne jako repozytoria git."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 19,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"/home/filipg/ext/amu/aitech-eks/wyk\n",
|
||||||
|
"Klonowanie do „sentiment-by-emoticons”...\n",
|
||||||
|
"remote: Wymienianie obiektów: 29, gotowe.\u001b[K\n",
|
||||||
|
"remote: Zliczanie obiektów: 100% (29/29), gotowe.\u001b[K\n",
|
||||||
|
"remote: Kompresowanie obiektów: 100% (25/25), gotowe.\u001b[K\n",
|
||||||
|
"remote: Razem 29 (delty 5), użyte ponownie 0 (delty 0), paczki użyte ponownie 0\n",
|
||||||
|
"Pobieranie obiektów: 100% (29/29), 155.07 MiB | 2.39 MiB/s, gotowe.\n",
|
||||||
|
"Rozwiązywanie delt: 100% (5/5), gotowe.\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"%cd wyk\n",
|
||||||
|
"! git clone --single-branch git://gonito.net/sentiment-by-emoticons"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 20,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"/home/filipg/ext/amu/aitech-eks/wyk/sentiment-by-emoticons\n",
|
||||||
|
"config.txt dev-0 README.md test-A train\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"%cd sentiment-by-emoticons\n",
|
||||||
|
"! ls"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 21,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"--metric LogLoss --metric Accuracy --precision 5 -%\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# plik konfiguracyjny\n",
|
||||||
|
"! cat config.txt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 22,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"expected.tsv in.tsv.xz meta.tsv.xz\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# zbiór uczący, oczywiście z oczekiwanym wyjściem\n",
|
||||||
|
"! ls train"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 23,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"expected.tsv in.tsv meta.tsv\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# zbiór deweloperski też ma\n",
|
||||||
|
"! ls dev-0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 24,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"in.tsv\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# a ostateczny zbiór testowy - nie ma (plik jest dostępny tylko dla ewaluatora)\n",
|
||||||
|
"! ls test-A"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 26,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"1\t1) Amor omnia vincit!!!!- miłość wszystko zwycięży!!!! 2) każdy człowiek jest jak kwiat...Więdnieje bez miłości *) 3) Szukaj mnie cierpliwie dzień po dniu... 4) BĄDű DLA INNYCH SŁONECZNYM ZEGAREM, ODMIERZAJ TYLKO SŁONECZNE GODZINY 5) \\\"... Momenty ze ze snu wyrwana; zas nie wyspana...\\\" 6) ULEWA JEST MA SIOSTRA , STRUMIEN BRATEM 7) KażdaMiłośMusiPrzejścPrzezPróbęWtedyOkażeSięJejPrawdziwaWartość... 8) Zaplątana w pajęczynę snów.. Lepkie nici marzeń.. Utkane przez noc.. 9) Podobno ludzi lubimy za ich zalety, a kochamy za ich wady.... 10) Pozwól mi pozostać... 11) KIEDYŚ-to juz przeszeszłosc...Trzeba przyzwyczajic sie do-DZISIAJ;/ 12) To MoJa JeSt..NiEdOrOsLa MiLoSć..UpArcIe WiEc...BeDe BrOnIć JeJ... 13) Jeszcze jeden krok , a zgine.. 14) *CoRazBl!ŻejŚw!ęTa* NapisałamListDoŚw.Mikołaja ProszącOTwojąMiłość! 15) JeStEm W TeScO Na UrOdZiNaCh <EMOTICON> <EMOTICON> <EMOTICON> 16) Facet jest jak plemnik,tylko jeden na milion staje się człowiekiem! 17) Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to myślę iż wątpię 18) Samotna wśród ludzi którzy myślą...ONA NIGDY NIE JEST SAMA ! 19) PotrzebaCałegoŻycia, AbyZapomniecOKimś, KtoByłDla NasNaprawdeWażny :&# 20) NieŻałujTegoCoZrobiłeś,KaraPrzyjdzieZCzasem;TymczasemUczSięDobroci...\n",
|
||||||
|
"0\t@ Rodzyn \"Ech szkoda, że to wersja komercyjna <EMOTICON>\" A jaki to problem załatać jądro np. za pomocą RTAI lub skorzystać z preempt_RT? Tylko co ci po tym? @ Mily \"Ja chetnie bym przetestowal ten system. Mysle, ze pomimo ze jest on dedykowany do innych zastosowan, bardzo dobrze sprawowal by sie jako system desktopowy. Mam tu na mysli gwarantowane czsy odpowiedzi (muzyka, film, reakcja interface'u graficznego na dzialania uzytkownika).\" To nie działa w ten sposób. Zagadnienia systemów czasu rzeczywistego są o wiele bardziej skomplikowane. Zazwyczaj tylko krytyczne aplikacje działają w czasie rzeczywistym. Gdybyś nadał priorytet czasu rzeczywistego wszystkim aplikacjom \"zwykłego użytkownika\" walczyłyby między sobą o zasoby tak samo jak teraz. O wiele lepiej byłoby gdyby w końcu zaczęto tworzyć aplikacje również z myślą o oszczędności zasobów. @ Macius \"8 rdzeni rowna sie 1system, 2desktop, 3muza,4film, 5net, 6 7 8 inne pierdoly ktore dzialaja w czasie rzeczywistym to jest cos.\" Wybacz, ale uważam to za piekielne marnotrawienie zasobów. Chcesz żeby jeden rdzeń obsługiwał np. tylko muzykę? Przecież to będzie jakieś 5% zasobów współczesnego rdzenia. Wszystko działałoby szybciej gdybyśmy większą uwagę przywiązywali do szybkości działania aplikacji niż jej wizualnych bajerów.\n",
|
||||||
|
"0\tCzy u Was też taka brzydka pogoda, która sprawia, że nic się nie chce?<EMOTICON> ale ja na szczęście jakoś chyba na przekór tej jesieni zaczęłam wyplatać...\n",
|
||||||
|
"0\tPo spektaklu w teatrze,,KOMEDIA''wracałam obok tej pani samochodem i uśmiechałam się ,ale pani jest faktycznie sztuczna i sztywna....zagrała ,wyszła i ma gdzieś sympatię ludzi...ja już jej nie mam dla tej pani<EMOTICON>\n",
|
||||||
|
"1\ta wtedy i ekskomunika niestraszna <EMOTICON>\n",
|
||||||
|
"paste: błąd zapisu: Przerwany potok\n",
|
||||||
|
"paste: błąd zapisu\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# W każdym wierszu jest osobny dokument\n",
|
||||||
|
"! xzcat train/in.tsv.xz | paste train/expected.tsv - | head -n 5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"#### Klasyfikacja wieloklasowa\n",
|
||||||
|
"\n",
|
||||||
|
"$$V^* \\mapsto \\{c_1,\\dots,c_n\\}$$\n",
|
||||||
|
"\n",
|
||||||
|
"#### Regresja\n",
|
||||||
|
"\n",
|
||||||
|
"$$V^* \\mapsto \\mathbb{R}$$\n",
|
||||||
|
"\n",
|
||||||
|
"#### Zadania seq2seq\n",
|
||||||
|
"\n",
|
||||||
|
"$$V^* \\mapsto Y^*$$\n",
|
||||||
|
"\n",
|
||||||
|
"##### Zadania tłumaczenia maszynowego\n",
|
||||||
|
"\n",
|
||||||
|
"$$V^* \\mapsto V^*$$\n",
|
||||||
|
"\n",
|
||||||
|
"##### Zadania sequence labeling\n",
|
||||||
|
"\n",
|
||||||
|
"$$V^* \\mapsto L^*$$\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.9.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
316
wyk/07_Naiwny_klasyfikator_bayesowski.ipynb
Normal file
316
wyk/07_Naiwny_klasyfikator_bayesowski.ipynb
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "damaged-senator",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Klasyfikacja binarna dla tekstu\n",
|
||||||
|
"\n",
|
||||||
|
"Zakładamy, że mamy dwie klasy: $c$ i jej dopełnienie ($\\bar{c}$).\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."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "explicit-gathering",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Pytanie**: Czy można wyobrazić sobie zadanie klasyfikacji mejli, niebędące zadaniem klasyfikacji binarnej?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "material-watch",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zakładamy paradygmat uczenia nadzorowanego, tzn. dysponujemy zbiorem uczącym.\n",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie**: Czym jest i w jaki sposób powstaje zbiór uczący dla filtru antyspamowego?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "referenced-hello",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Klasyfikacja regułowa\n",
|
||||||
|
"\n",
|
||||||
|
"Filtr anyspamowe _można_ zrealizować za pomocą metod innych niż opartych na uczeniu maszynowym. Można np. tworzyć reguły (np. wyrażenia regularne). Przykładem są (barokowe...) reguły w programie SpamAssassin, zob. fragment [pliku reguł](https://github.com/apache/spamassassin/blob/trunk/rules/20_advance_fee.cf):\n",
|
||||||
|
"\n",
|
||||||
|
"```\n",
|
||||||
|
"header __FRAUD_VQE\tSubject =~ /^(?:Re:|\\[.{1,10}\\])?\\s*(?:very )?urgent\\s+(?:(?:and|&)\\s+)?(?:confidential|assistance|business|attention|reply|response|help)\\b/i\n",
|
||||||
|
"\n",
|
||||||
|
"body __FRAUD_DBI\t/(?:\\bdollars?\\b|\\busd(?:ollars)?(?:[0-9]|\\b)|\\bus\\$|\\$[0-9,.]{6,}|\\$[0-9].{0,8}[mb]illion|\\$[0-9.,]{2,10} ?m|\\beuros?\\b|u[.]?s[.]? [0-9.]+ m)/i\n",
|
||||||
|
"body __FRAUD_KJV\t/(?:claim|concerning) (?:the|this) money/i\n",
|
||||||
|
"body __FRAUD_IRJ\t/(?:finance|holding|securit(?:ies|y)) (?:company|firm|storage house)/i\n",
|
||||||
|
"body __FRAUD_NEB\t/(?:government|bank) of nigeria/i\n",
|
||||||
|
"body __FRAUD_XJR\t/(?:who was a|as a|an? honest|you being a|to any) foreigner/i\n",
|
||||||
|
"```\n",
|
||||||
|
"\n",
|
||||||
|
"Jakie są wady i zalety regułowych filtrów antyspamowych?\n",
|
||||||
|
"\n",
|
||||||
|
"Współcześnie zdecydowanie dominuje użycie metod statystycznych (opartych na nadzorowanym uczeniu maszynowym). Do popularności tych metod przyczynił się artykuł [Plan for spam](http://www.paulgraham.com/spam.html) autorstwa Paula Grahama."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "cathedral-uganda",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Podejście generatywne i dyskryminatywne\n",
|
||||||
|
"\n",
|
||||||
|
"W klasyfikacji (i w ogóle w uczeniu nadzorowanym) można wskazać dwa podejścia:\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",
|
||||||
|
"\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",
|
||||||
|
"**Pytanie**: Jakie są wady i zalety obu podejść?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "powerful-engineer",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Nasz \"dyżurny\" przykład\n",
|
||||||
|
"\n",
|
||||||
|
"Zakładamy, że nasz zbiór uczący ($X$) składa się z 4 dokumentów:\n",
|
||||||
|
"\n",
|
||||||
|
"* $x_1=\\mathit{kup\\ pan\\ Viagrę}$\n",
|
||||||
|
"* $x_2=\\mathit{tanie\\ miejsce\\ dla\\ pana}$\n",
|
||||||
|
"* $x_3=\\mathit{viagra\\ viagra\\ viagra}$\n",
|
||||||
|
"* $x_4=\\mathit{kup\\ tanie\\ cartridge'e}$\n",
|
||||||
|
"\n",
|
||||||
|
"z następującymi etykietami:\n",
|
||||||
|
"\n",
|
||||||
|
"* $y_1=c$ (spam)\n",
|
||||||
|
"* $y_2=\\bar{c}$ (nie-spam)\n",
|
||||||
|
"* $y_3=c$\n",
|
||||||
|
"* $y_4=c$\n",
|
||||||
|
"\n",
|
||||||
|
"Zakładamy, że dokumenty podlegają lematyzacji i sprowadzeniu do mały liter, więc ostatecznie będziemy mieli następujące ciąg termów:\n",
|
||||||
|
"\n",
|
||||||
|
"* $x_1=(\\mathit{kupić}, \\mathit{pan}, \\mathit{viagra})$\n",
|
||||||
|
"* $x_2=(\\mathit{tani}, \\mathit{miejsce}, \\mathit{dla}, \\mathit{pana})$\n",
|
||||||
|
"* $x_3=(\\mathit{viagra}, \\mathit{viagra}, \\mathit{viagra})$\n",
|
||||||
|
"* $x_4=(\\mathit{kupić}, \\mathit{tani}, \\mathit{cartridge})$\n",
|
||||||
|
"\n",
|
||||||
|
"Uczymy na tym zbiorze klasyfikator, który będziemy testować na dokumencie $d=\\mathit{tania tania viagra dla pana}$, tj. po normalizacji\n",
|
||||||
|
"$d=(\\mathit{tani}, \\mathit{tani}, \\mathit{viagra}, \\mathit{dla}, \\mathit{pan})$.\n",
|
||||||
|
"\n",
|
||||||
|
"**Uwaga:** Przykład jest oczywiście nierealistyczny i trudno będzie nam ocenić sensowność odpowiedzi. Za to będziemy w stanie policzyć ręcznie wynik.\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "controversial-rotation",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Naiwny klasyfikator bayesowski\n",
|
||||||
|
"\n",
|
||||||
|
"* _naiwny_ - niekoniecznie oznacza, że to \"głupi\", bezużyteczny klasyfikator\n",
|
||||||
|
"* _klasyfikator_ \n",
|
||||||
|
"* _bayesowski_ - będzie odwoływać się do wzoru Bayesa.\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",
|
||||||
|
"\n",
|
||||||
|
"Naiwny klasyfikator bayesowski ma dwie odmiany:\n",
|
||||||
|
"\n",
|
||||||
|
"* wielomianową,\n",
|
||||||
|
"* Bernoulliego.\n",
|
||||||
|
"\n",
|
||||||
|
"Wielomianowy naiwny klasyfikator bayesowski jest częściej spotykany i od niego zaczniemy."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "spatial-citizenship",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Mamy dokument $d$ i dwie klasy $c$ i $\\bar{c}$. Policzymy prawdopodobieństwa $P(c|d)$ (mamy dokument $d$, jakie jest prawdopodobieństwo, że to klasa $c$) i $P(\\bar{c}|d)$. A właściwie będziemy te prawdopodobieństwa porównywać.\n",
|
||||||
|
"\n",
|
||||||
|
"**Uwaga**: nasz zapis to skrót notacyjny, właściwie powinniśmy podać zmienne losowe $P(C=c|D=d)$, ale zazwyczaj będziemy je pomijać. \n",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie**: kiedy ostatecznie nasz klasyfikator zwróci informację, że klasa $c$, a kiedy że $\\bar{c}$? czy użytkownika interesują prawdopodobieństwa $P(c|d)$ i $P(\\bar{c}|d)$?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "united-recognition",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zastosujmy najpierw wzór Bayesa.\n",
|
||||||
|
"\n",
|
||||||
|
"$P(c|d) = \\frac{P(d|c) P(c)}{P(d)} \\propto P(d|c) P(c)$"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "present-draft",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"$P(\\bar{c}|d) = \\frac{P(d|\\bar{c}) P(\\bar{c})}{P(d)} \\propto P(d|\\bar{c}) P(\\bar{c}) $"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "accepting-tamil",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"(Oczywiście skądinąd $P(\\bar{c}|d) = 1 - P(c|d)$, ale nie będziemy teraz tego wykorzystywali.)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "equipped-outreach",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Co możemy pominąć, jeśli tylko porównujemy $P(c|d)$ i $P(\\bar{c}|d)$?\n",
|
||||||
|
"\n",
|
||||||
|
"Użyjmy znaku proporcjonalności $\\propto$:\n",
|
||||||
|
"\n",
|
||||||
|
"$P(c|d) = \\frac{P(d|c) P(c)}{P(d)} \\propto P(d|c) P(c)$\n",
|
||||||
|
"\n",
|
||||||
|
"$P(\\bar{c}|d) = \\frac{P(d|\\bar{c}) P(\\bar{c})}{P(d)} \\propto P(d|\\bar{c}) P(\\bar{c})$\n",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie:** czy iloczyn $P(d|c)P(c)$ można interpretować jako prawdopodobieństwo?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "active-motor",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"#### Prawdopodobieństwo _a priori_\n",
|
||||||
|
"\n",
|
||||||
|
"$P(c)$ - prawdopodobieństwo a priori klasy $c$\n",
|
||||||
|
"\n",
|
||||||
|
"$\\hat{P}(c) = \\frac{N_c}{N}$\n",
|
||||||
|
"\n",
|
||||||
|
"gdzie\n",
|
||||||
|
"\n",
|
||||||
|
"* N - liczba wszystkich dokumentów w zbiorze uczącym\n",
|
||||||
|
"* N_c - liczba dokumentow w zbiorze uczącym z klasą $c$\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "trying-indonesian",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"#### Prawdopodobieństwo _a posteriori_\n",
|
||||||
|
"\n",
|
||||||
|
"Jak interpretować $P(d|c)$?\n",
|
||||||
|
"\n",
|
||||||
|
"Wymyślmy sobie model generatywny, $P(d|c)$ będzie prawdopodobieństwem, że spamer (jeśli $c$ to spam) wygeneruje tekst.\n",
|
||||||
|
"\n",
|
||||||
|
"Załóżmy, że dokument $d$ to ciąg $n$ termów, $d = (t_1\\dots t_n)$. Na razie niewiele z tego wynika."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "median-nomination",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"$P(d|c) = P(t_1\\dots t_n|c)$\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",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie:** Ile może wynosić $P(\\mathit{Viagra}|c)$?\n",
|
||||||
|
"\n",
|
||||||
|
"Po przyjęciu takich \"naiwnych założeń\":\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)$$"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "romantic-verse",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Jak oszacować $\\hat{P}(t|c)$?\n",
|
||||||
|
"\n",
|
||||||
|
"$$\\hat{P}(t|c) = \\frac{\\#(t,c)}{\\sum_i^{|V|} \\#(t_i,c)} = \\frac{\\mathit{ile\\ razy\\ term\\ t\\ pojawił\\ się\\ w\\ dokumentach\\ klasy\\ c}}{liczba\\ wyrazów\\ w\\ klasie\\ c}$$"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "interracial-today",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Wygładzanie\n",
|
||||||
|
"\n",
|
||||||
|
"Mamy problem z zerowymi prawdopodobieństwami.\n",
|
||||||
|
"\n",
|
||||||
|
"Czy jeśli w naszym zbiorze uczącym spamerzy ani razu nie użyli słowa _wykładzina_, to $P(\\mathit{wykładzina}|c) = 0$?.\n",
|
||||||
|
"\n",
|
||||||
|
"Musimy zastosować wygładzanie (_smoothing_). Spróbujmy wymyślić wygładzanie wychodząc od zdroworozsądkowych aksjomatów.\n",
|
||||||
|
"\n",
|
||||||
|
"#### Aksjomaty wygładzania.\n",
|
||||||
|
"\n",
|
||||||
|
"Założmy, że mamy dyskretną przestrzeń probabilistyczną $\\Omega = \\{\\omega_1,\\dots,\\omega_m\\}$, zdarzenie $\\omega_i$ w naszym zbiorze uczącym wystąpiło $k_i$ razy. Wprost prawdopodobieństwa byśmy oszacowali tak: $P(\\omega_i) = \\frac{k_i}{\\sum_j^m k_j}$.\n",
|
||||||
|
"Szukamy zamiast tego funkcji wygładzającej $f(m, k, T)$ (innej niż $f(m, k, T) = \\frac{k}{T}$), która spełniałaby następujące aksjomaty:\n",
|
||||||
|
"\n",
|
||||||
|
"1. $f(m, k, T) \\in [0, 1]$\n",
|
||||||
|
"2. $f(m, k, T) \\in (0, 1)$ jeśli $m > 1$\n",
|
||||||
|
"3. $\\sum_i f(m, k_i, T) = 1$, jeśli $\\sum_i k_i = T$\n",
|
||||||
|
"4. $f(m, 0, 0) = \\frac{1}{m}$\n",
|
||||||
|
"5. $\\lim_{T \\to \\inf} f(m, k, T) = \\frac{k}{T}$\n",
|
||||||
|
"\n",
|
||||||
|
"Jaka funkcja spełnia te aksjomaty?\n",
|
||||||
|
"\n",
|
||||||
|
"$$f(m, k, T) = \\frac{k+1}{T+m}$$\n",
|
||||||
|
"\n",
|
||||||
|
"Jest to wygładzanie +1, albo wygładzanie Laplace'a.\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "accepting-stockholm",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Po zastosowaniu do naszego naiwnego klasyfikatora otrzymamy:\n",
|
||||||
|
" \n",
|
||||||
|
"$$\\hat{P}(t|c) = \\frac{\\#(t,c) + 1}{\\sum_i^{|V|} \\#(t_i,c) + |V|}$$"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "moral-ceremony",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.9.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
1
wyk/uczenie-a-programowanie.drawio
Normal file
1
wyk/uczenie-a-programowanie.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2021-04-13T11:39:17.647Z" agent="5.0 (X11)" etag="XxEtXX0WYzlqqzidtQgP" version="14.4.9" type="device"><diagram id="uLKjCm85fMcSPGM1o2xF" name="Page-1">7VpJc6M4FP41VE5xsRgvx9hJeg7JJNWdqV4uKQEyVgKIESK28+vniR2EHdttbGdmcnDQQ+t731uFYkz95ReGwvk9dbCn6KqzVIxrRdfHfQ1+BWGVEkzDSAkuI05K0krCN/KOM6KaUWPi4KjWkVPqcRLWiTYNAmzzGg0xRhf1bjPq1VcNkYslwjcbeTL1O3H4PKWO9GFJ/wMTd56vrA3G6Rsf5Z2zk0Rz5NBFhWTcKMaUUcrTJ385xZ7gXc6XdNztmrfFxhgO+DYD4PCq9qQOnx6nVPvB9D9/Te3LQbY3vsoPjB04f9akjM+pSwPk3ZTUCaNx4GAxqwqtss8dpSEQNSC+YM5XmTBRzCmQ5tz3srd4SfgPMbxnZq2flTfXy2zmpLHKGwFnq8og0fxZfVcOS1r5uPR84lBr2ZaRIhozG2/glVYIDcCOqY9hHRjHsIc4eavPjzLYuUW/YugjJbCyrmYaog/MdEimIFqOl3wKjpiLeTaqlC88VLZRkhKp74CAbMNvyIuzI3zHL8rUVMYTm2AJHqXwhbwWc8LxtxAlfFuAAagLOpsaM46Xm9kvszVnj1pnj5lxZ1EqY8GxeUURDXW9IGos3JVfusyv1Rnzyzg5w4afxcRsbypSlfwIJJ2bCn3ckFlqwjozFeYpJalV5Kj2jMbfZt8BjUfMCJwfM8mf1LxJ6Vy69yf9LcGkqZ2gSRupdTTlluNIjqcvGdJHRl2GfBJxJCENoqdQPMa+d2VzCmKcCDtJIFK7Qxb2HmlEOKEBdLEo59SvdLjyiCtecNqwtzTmHgnwtIgd1cMYYYmzsg02WkzwoCsTrMlOS9EHHiw7mdEEE1EeeA/+jkVAOtHKR3hys//JEKsmmbyXmOgyneYKOmhmuJSneGLIWdmrlwALfqbipgsUCMeZTg7ns5oLAi3dZk5uYAMExeuCjTijryBXTwDlOqCBMEUz4nkNEsqQYYNgMWuBjE8cJ7FjbZ67btsOgBttUAeOJuOmoFWB0wwZDwec4ZkA5y/7HScogbwqel8FdFEgxmItePnvYmhgmOeFId1owVCD+y6wIVx7+Cy3R1beXd1ZscYNxdJbouJBC1e0YWeqpX7Mljo4DpE8bJCQzLwTMkfOStere9hiZ1LC49eHL1+v7jfZBXm6kkJmsIULyOpe0QJfiD0HIl5L7FTLaOQLiQRWFG7VhviNx0zMqFU2KB0mrO/GFanmSI9DUt0RiCBw4Deg4vkiIF1u91LbaHrXn6CYQd1zgj12ve1KB3MHESgoCVwgmGXrKUl2LvV1akxBbWdeUh2cg7fAwX6eYSftzqdpsYT9NmXvLDo12oKMIzuIQSPyKmLx09lAY3Q2DiKV0Dk5CGN8WAdxe/9wfXO3m6NoM1WbF//feB0KeWdjvPobIpWm0PKU6aMUyBi3pUCKcbs2mWmD7ZoCih1b63KRCmCsVH53VkFA9qubSPUhLZpkdAex1weBE55UyHqqWSfqCbUb81OUvGumu2/KmGgreGvNetfhMNFWbjm2Q2vUoNr8WRtXuqtByWngkS+aNshqs2s76nWJJtdFj3zBtBOfVnV2nIxt/c9zk73xNuJkt9u52fzwOiINvX7jOuL35Gx+bFtzV+cvXfFNSs8mkU17NvXDGFgePUOu/ByCBMI5ZsiLesTyn30SkGcU9VW1LuFQXH9gdvMGDI0KnxfNC9RUoygF8G0MRuOhFHLBm1nyV7zJvyYBVu57kyFVHru6zxhqo16jqthyrdw3WtyJ3hUOPs218r66nbSahuKACq9te/+YqtzJFF5Og39ZRJkaysSAtEiN7Xdl2ldGpr2SEPGvKeqbjfr1SNa+UYu33aOmD83yk7T0qrf8rs+4+Qc=</diagram></mxfile>
|
BIN
wyk/uczenie-a-programowanie.png
Normal file
BIN
wyk/uczenie-a-programowanie.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
1
wyk/uczenie-schemat.drawio
Normal file
1
wyk/uczenie-schemat.drawio
Normal file
File diff suppressed because one or more lines are too long
BIN
wyk/uczenie-schemat.png
Normal file
BIN
wyk/uczenie-schemat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 KiB |
Loading…
Reference in New Issue
Block a user