{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Uczenie maszynowe\n",
"# 9. Przegląd metod uczenia nadzorowanego – część 1"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## 9.1. Naiwny klasyfikator bayesowski"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"* Naiwny klasyfikator bayesowski jest algorytmem dla problemu klasyfikacji wieloklasowej.\n",
"* Naszym celem jest znalezienie funkcji uczącej $f \\colon x \\mapsto y$, gdzie $y$ oznacza jedną ze zdefiniowanych wcześniej klas.\n",
"* Klasyfikacja probabilistyczna polega na wskazaniu klasy o najwyższym prawdopodobieństwie:\n",
"$$ \\hat{y} = \\mathop{\\arg \\max}_y P( y \\,|\\, x ) $$\n",
"* Naiwny klasyfikator bayesowski należy do rodziny klasyfikatorów probabilistycznych"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"\n",
"\n",
"**Thomas Bayes** (wymowa: /beɪz/) (1702–1761) – angielski matematyk i duchowny"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Twierdzenie Bayesa – wzór ogólny\n",
"\n",
"$$ P( Y \\,|\\, X ) = \\frac{ P( X \\,|\\, Y ) \\cdot P( Y ) }{ P ( X ) } $$"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "notes"
}
},
"source": [
"Twierdzenie Bayesa opisuje związek między prawdopodobieństwami warunkowymi dwóch zdarzeń warunkujących się nawzajem."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Twierdzenie Bayesa\n",
"(po zastosowaniu wzoru na prawdopodobieństwo całkowite)\n",
"\n",
"$$ \\underbrace{P( y_k \\,|\\, x )}_\\textrm{ prawd. a posteriori } = \\frac{ \\overbrace{ P( x \\,|\\, y_k )}^\\textrm{ model klasy } \\cdot \\overbrace{P( y_k )}^\\textrm{ prawd. a priori } }{ \\underbrace{\\sum_{i} P( x \\,|\\, y_i ) \\, P( y_i )}_\\textrm{wyrażenie normalizacyjne} } $$"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "notes"
}
},
"source": [
" * W tym przypadku „zdarzenie $x$” oznacza, że cechy wejściowe danej obserwacji przyjmują wartości opisane wektorem $x$.\n",
" * „Zdarzenie $y_k$” oznacza, że dana obserwacja należy do klasy $y_k$.\n",
" * **Model klasy** $y_k$ opisuje rozkład prawdopodobieństwa cech obserwacji należących do tej klasy.\n",
" * **Prawdopodobieństwo *a priori*** to prawdopodobienstwo, że losowa obserwacja należy do klasy $y_k$.\n",
" * **Prawdopodobieństwo *a posteriori*** to prawdopodobieństwo, którego szukamy: że obserwacja opisana wektorem cech $x$ należy do klasy $y_k$."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Rola wyrażenia normalizacyjnego w twierdzeniu Bayesa\n",
"\n",
" * Wartość wyrażenia normalizacyjnego nie wpływa na wynik klasyfikacji.\n",
"\n",
"**Przykład**: obserwacja nietypowa ma małe prawdopodobieństwo względem dowolnej klasy, wyrażenie normalizacyjne sprawia, że to prawdopodobieństwo staje się porównywalne z prawdopodobieństwami typowych obserwacji, ale nie wpływa na klasyfikację!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Klasyfikatory dyskryminatywne a generatywne\n",
"\n",
"* Klasyfikatory generatywne tworzą model rozkładu prawdopodobieństwa dla każdej z klas.\n",
"* Klasyfikatory dyskryminatywne wyznaczają granicę klas (*decision boundary*) bezpośrednio.\n",
"* Naiwny klasyfikator bayesowski jest klasyfikatorem generatywnym (ponieważ wyznacza $P( x \\,|\\, y )$).\n",
"* Wszystkie klasyfikatory generatywne są probabilistyczne, ale nie na odwrót.\n",
"* Regresja logistyczna jest przykładem klasyfikatora dyskryminatywnego."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Założenie niezależności dla naiwnego klasyfikatora bayesowskiego\n",
"\n",
"* Naiwny klasyfikator bayesowski jest *naiwny*, ponieważ zakłada, że poszczególne cechy są niezależne od siebie:\n",
"$$ P( x_1, \\ldots, x_n \\,|\\, y ) \\,=\\, \\prod_{i=1}^n P( x_i \\,|\\, x_1, \\ldots, x_{i-1}, y ) \\,=\\, \\prod_{i=1}^n P( x_i \\,|\\, y ) $$\n",
"* To założenie jest bardzo przydatne ze względów obliczeniowych, ponieważ bardzo często mamy do czynienia z ogromną liczbą cech (bitmapy, słowniki itp.)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Naiwny klasyfikator bayesowski – przykład"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"slideshow": {
"slide_type": "notes"
}
},
"outputs": [],
"source": [
"# Przydtne importy\n",
"\n",
"import ipywidgets as widgets\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"# Wczytanie danych (gatunki kosaćców)\n",
"\n",
"data_iris = pandas.read_csv('iris.csv')\n",
"data_iris_setosa = pandas.DataFrame()\n",
"data_iris_setosa['dł. płatka'] = data_iris['pl'] # \"pl\" oznacza \"petal length\"\n",
"data_iris_setosa['szer. płatka'] = data_iris['pw'] # \"pw\" oznacza \"petal width\"\n",
"data_iris_setosa['Iris setosa?'] = data_iris['Gatunek'].apply(lambda x: 1 if x=='Iris-setosa' else 0)\n",
"\n",
"m, n_plus_1 = data_iris_setosa.values.shape\n",
"n = n_plus_1 - 1\n",
"Xn = data_iris_setosa.values[:, 0:n].reshape(m, n)\n",
"\n",
"X = np.matrix(np.concatenate((np.ones((m, 1)), Xn), axis=1)).reshape(m, n_plus_1)\n",
"Y = np.matrix(data_iris_setosa.values[:, 2]).reshape(m, 1)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"liczba przykładów: {0: 100, 1: 50}\n",
"prior probability: {0: 0.6666666666666666, 1: 0.3333333333333333}\n"
]
}
],
"source": [
"classes = [0, 1]\n",
"count = [sum(1 if y == c else 0 for y in Y.T.tolist()[0]) for c in classes]\n",
"prior_prob = [float(count[c]) / float(Y.shape[0]) for c in classes]\n",
"\n",
"print('liczba przykładów: ', {c: count[c] for c in classes})\n",
"print('prior probability:', {c: prior_prob[c] for c in classes})"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"slideshow": {
"slide_type": "notes"
}
},
"outputs": [],
"source": [
"# Wykres danych (wersja macierzowa)\n",
"def plot_data_for_classification(X, Y, xlabel, ylabel): \n",
" fig = plt.figure(figsize=(16*.6, 9*.6))\n",
" ax = fig.add_subplot(111)\n",
" fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9)\n",
" X = X.tolist()\n",
" Y = Y.tolist()\n",
" X1n = [x[1] for x, y in zip(X, Y) if y[0] == 0]\n",
" X1p = [x[1] for x, y in zip(X, Y) if y[0] == 1]\n",
" X2n = [x[2] for x, y in zip(X, Y) if y[0] == 0]\n",
" X2p = [x[2] for x, y in zip(X, Y) if y[0] == 1]\n",
" ax.scatter(X1n, X2n, c='r', marker='x', s=50, label='Dane')\n",
" ax.scatter(X1p, X2p, c='g', marker='o', s=50, label='Dane')\n",
" \n",
" ax.set_xlabel(xlabel)\n",
" ax.set_ylabel(ylabel)\n",
" ax.margins(.05, .05)\n",
" return fig"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"