{ "cells": [ { "cell_type": "markdown", "id": "45264aad", "metadata": {}, "source": [ "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", "
\n", "

Ekstrakcja informacji

\n", "

7. Naiwny klasyfikator bayesowski w ekstrakcji informacji [wykład]

\n", "

Filip Graliński (2021)

\n", "
\n", "\n", "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)" ] }, { "cell_type": "markdown", "id": "moderate-array", "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": "correct-victory", "metadata": {}, "source": [ "**Pytanie**: Czy można wyobrazić sobie zadanie klasyfikacji mejli, niebędące zadaniem klasyfikacji binarnej?" ] }, { "cell_type": "markdown", "id": "spiritual-diploma", "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": "secure-performance", "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", "**Pytanie:** 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": "indoor-ending", "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": "pleased-clinic", "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{pan})$\n", "* $x_3=(\\mathit{viagra}, \\mathit{viagra}, \\mathit{viagra})$\n", "* $x_4=(\\mathit{kupić}, \\mathit{tani}, \\mathit{cartridge})$\n", "\n", "$P(tani|c) = (1+1)/(9+7) = 2/16 = 0.125$\n", "$P(viagra|c) = \\frac{4+1}{9 + 7} = 5/16 = 0.3125 $\n", "$P(dla|c) = \\frac{0+1}{9+7} = 1/16 = 0.0625$\n", "$P(pan|c) = (1+1)/(9+7) = 2/16 = 0.125 $\n", "$P(c) = 0.75$\n", "\n", "w wersji wielomianowej: $P(c)P(tani|c)P(tani|c)P(viagra|c)P(dla|c)P(pan|c) = 0.75 * 0.125 * 0.125 * 0.3125 * 0.0625 * 0.125= 0.0002861$\n", "\n", "w werjis Bernoulliego: $P(c)P(U_{dla}=1|c)P(U_{cartridge}=0|c)P(U_{viagra}=1|c)P(U_{pan}=1|c)P(U_{tani}=1|c)P(U_{miejsce}=0|c)P(U_{kup}=0|c)$\n", "\n", "$P(tani|\\bar{c}) = (1+1)/(4+7) = 2/11 =0.182 $\n", "$P(viagra|\\bar{c}) = 1/11 = 0.091 $\n", "$P(dla|\\bar{c}) = 2/11 = 0.182 $\n", "$P(pan|\\bar{c}) = 2/11 = 0.182 $\n", "$P(\\bar{c}) = 0.25$\n", "\n", "$P(\\bar{c})P(tani|\\bar{c})P(tani|\\bar{c})P(dla|\\bar{c})P(pan|\\bar{c}) = 0.25 * 0.182 * 0.182 * 0.091 * 0.182 * 0.182 = 0.00002496$\n", "\n", "\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": "partial-military", "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": "colonial-creature", "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": "governing-fiction", "metadata": {}, "source": [ "Zastosujmy najpierw wzór Bayesa.\n", "\n", "$P(c|d) = \\frac{P(d|c) P(c)}{P(d)}$" ] }, { "cell_type": "markdown", "id": "northern-spine", "metadata": {}, "source": [ "$P(\\bar{c}|d) = \\frac{P(d|\\bar{c}) P(\\bar{c})}{P(d)}$" ] }, { "cell_type": "markdown", "id": "utility-induction", "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": "timely-force", "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": "embedded-involvement", "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", "\n", "$\\hat{P}(c) = 0,75$\n", "\n", "$\\hat{P}(\\bar{c}) = 0,25$\n" ] }, { "cell_type": "markdown", "id": "virgin-premiere", "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": "acting-zimbabwe", "metadata": {}, "source": [ "$P(d|c) = P(t_1\\dots t_n|c)$\n", "\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", "**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": "adjustable-disney", "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": "associate-variance", "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", "\n", "m=2, k1=2, k2=4, T=6, 2/6 => f(2, 2, 6) > 0.333, f(2, 4, 6) < 0.666 \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, inaczej wygładzanie Laplace'a.\n", "\n", "**Pytanie:** Wymyślić jakiś inny przykład funkcji, która będzie spełniała aksjomaty.\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "id": "complimentary-airplane", "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": "markdown", "id": "comprehensive-junior", "metadata": {}, "source": [ "### Metoda Bernoulliego" ] }, { "cell_type": "markdown", "id": "vocational-spanish", "metadata": {}, "source": [ "$$P(𝑑|𝑐) \\approx P(U=u_1|c)\\dots P(U=u_{|v|})$$, gdzie $u_i = 1$, $t_i$ pojawił się w dokumencie $d$, 0 - w przeciwnym razie\n", "\n" ] }, { "cell_type": "markdown", "id": "enabling-manitoba", "metadata": {}, "source": [ "$\\hat{P}(U_{viagra}=1|c) = \\frac{\\#(viagra,N_c) + 1}{N_c + 2}$" ] }, { "cell_type": "code", "execution_count": null, "id": "bearing-execution", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "author": "Filip Graliński", "email": "filipg@amu.edu.pl", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "lang": "pl", "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.6" }, "subtitle": "7.Naiwny klasyfikator bayesowski w ekstrakcji informacji[wykład]", "title": "Ekstrakcja informacji", "year": "2021" }, "nbformat": 4, "nbformat_minor": 5 }