817 lines
172 KiB
Plaintext
817 lines
172 KiB
Plaintext
|
{
|
|||
|
"cells": [
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"## Uczenie maszynowe UMZ 2017/2018\n",
|
|||
|
"# 4. Algorytm KNN, uczenie nienadzorowane\n",
|
|||
|
"### Część 1"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"## 4.1. Algorytm $k$ najbliższych sąsiadów"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"### KNN – intuicja"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Do której kategorii powinien należeć punkt oznaczony gwiazdką?"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 1,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Przydatne 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": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Wczytanie danych (gatunki kosaćców)\n",
|
|||
|
"\n",
|
|||
|
"data_iris_setosa = (\n",
|
|||
|
" pandas.read_csv('iris.csv', usecols=['pł.dł.', 'pł.sz.', 'Gatunek'])\n",
|
|||
|
" .apply(lambda x: [x[0], x[1], 1 if x[2] == 'Iris-setosa' else 0], axis=1))\n",
|
|||
|
"data_iris_setosa.columns = ['dł. płatka', 'szer. płatka', 'Iris setosa?']\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": "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": 4,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"def plot_new_example(fig, x, y):\n",
|
|||
|
" ax = fig.axes[0]\n",
|
|||
|
" ax.scatter([x], [y], c='k', marker='*', s=100, label='?')"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "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\nABNXm3BVl9o7YbVJSnV
|
|||
|
"text/plain": [
|
|||
|
"<matplotlib.figure.Figure at 0x7f468dbd0f90>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"fig = plot_data_for_classification(X, Y, xlabel=u'dł. płatka', ylabel=u'szer. płatka')\n",
|
|||
|
"plot_new_example(fig, 2.8, 0.9)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Wydaje się sensownym przyjąć, że punkt oznaczony gwiazdką powinien być czerwony, ponieważ sąsiednie punkty są czerwone. Najbliższe czerwone punkty są położone bliżej niż najbliższe zielone."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Algorytm oparty na tej intuicji nazywamy algorytmem **$k$ najbliższych sąsiadów** (_$k$ nearest neighbors_, KNN)."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Idea (KNN dla $k = 1$):\n",
|
|||
|
" 1. Dla nowego przykładu $x'$ znajdź najbliższy przykład $x$ ze zbioru uczącego.\n",
|
|||
|
" 1. Jego klasa $y$ to szukana klasa $y'$."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 6,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"from scipy.spatial import Voronoi, voronoi_plot_2d\n",
|
|||
|
"\n",
|
|||
|
"def plot_voronoi(fig, points):\n",
|
|||
|
" ax = fig.axes[0]\n",
|
|||
|
" vor = Voronoi(points)\n",
|
|||
|
" ax.scatter(vor.vertices[:, 0], vor.vertices[:, 1], s=1)\n",
|
|||
|
" \n",
|
|||
|
" for simplex in vor.ridge_vertices:\n",
|
|||
|
" simplex = np.asarray(simplex)\n",
|
|||
|
" if np.all(simplex >= 0):\n",
|
|||
|
" ax.plot(vor.vertices[simplex, 0], vor.vertices[simplex, 1],\n",
|
|||
|
" color='orange', linewidth=1)\n",
|
|||
|
" \n",
|
|||
|
" xmin, ymin = points.min(axis=0).tolist()[0]\n",
|
|||
|
" xmax, ymax = points.max(axis=0).tolist()[0]\n",
|
|||
|
" pad = 0.1\n",
|
|||
|
" ax.set_xlim(xmin - pad, xmax + pad)\n",
|
|||
|
" ax.set_ylim(ymin - pad, ymax + pad)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 7,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "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\ntCkjRtqXOOr5FyBlLlC
|
|||
|
"text/plain": [
|
|||
|
"<matplotlib.figure.Figure at 0x7f468dbd0990>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"fig = plot_data_for_classification(X, Y, xlabel=u'dł. płatka', ylabel=u'szer. płatka')\n",
|
|||
|
"plot_new_example(fig, 2.8, 0.9)\n",
|
|||
|
"plot_voronoi(fig, X[:, 1:])"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Podział płaszczyzny jak na powyższym wykresie nazywamy **diagramem Woronoja** (_Voronoi diagram_)."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Taki algorytm wyznacza dość efektowne granice klas, zwłaszcza jak na tak prosty algorytm. "
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Niestety jest bardzo podatny na obserwacje odstające:"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 8,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"X_outliers = np.vstack((X, np.matrix([[1.0, 3.9, 1.7]])))\n",
|
|||
|
"Y_outliers = np.vstack((Y, np.matrix([[1]])))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 9,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "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\nzlpj3g7cTjj6tXVRjuW
|
|||
|
"text/plain": [
|
|||
|
"<matplotlib.figure.Figure at 0x7f4688b57e10>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"fig = plot_data_for_classification(X_outliers, Y_outliers, xlabel=u'dł. płatka', ylabel=u'szer. płatka')\n",
|
|||
|
"plot_new_example(fig, 2.8, 0.9)\n",
|
|||
|
"plot_voronoi(fig, X_outliers[:, 1:])"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Pojedyncza obserwacja odstająca dramatycznie zmienia granice klas."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Aby temu zaradzić, użyjemy więcej niż jednego najbliższego sąsiada ($k > 1$)."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"### Algorytm $k$ najbliższych sąsiadów dla problemu klasyfikacji\n",
|
|||
|
"\n",
|
|||
|
"1. Dany jest zbiór uczący zawierajacy przykłady $(x_i, y_i)$, gdzie: $x_i$ – zestaw cech, $y_i$ – klasa.\n",
|
|||
|
"1. Dany jest przykład testowy $x'$, dla którego chcemy określić klasę.\n",
|
|||
|
"1. Oblicz odległość $d(x', x_i)$ dla każdego przykładu $x_i$ ze zbioru uczącego.\n",
|
|||
|
"1. Wybierz $k$ przykładów $x_{i_1}, \\ldots, x_{i_k}$, dla których wyliczona odległość jest najmniejsza.\n",
|
|||
|
"1. Jako wynik $y'$ zwróć tę spośrod klas $y_{i_1}, \\ldots, y_{i_k}$, która występuje najczęściej."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"### Algorytm $k$ najbliższych sąsiadów dla problemu klasyfikacji – przykład"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 10,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Odległość euklidesowa\n",
|
|||
|
"def euclidean_distance(x1, x2):\n",
|
|||
|
" return np.linalg.norm(x1 - x2)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 11,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Algorytm k najbliższych sąsiadów\n",
|
|||
|
"def knn(X, Y, x_new, k, distance=euclidean_distance):\n",
|
|||
|
" data = np.concatenate((X, Y), axis=1)\n",
|
|||
|
" nearest = sorted(\n",
|
|||
|
" data, key=lambda xy:distance(xy[0, :-1], x_new))[:k]\n",
|
|||
|
" y_nearest = [xy[0, -1] for xy in nearest]\n",
|
|||
|
" return max(y_nearest, key=lambda y:y_nearest.count(y))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 12,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Wykres klas dla KNN\n",
|
|||
|
"def plot_knn(fig, X, Y, k, distance=euclidean_distance):\n",
|
|||
|
" ax = fig.axes[0]\n",
|
|||
|
" x1min, x2min = X.min(axis=0).tolist()[0]\n",
|
|||
|
" x1max, x2max = X.max(axis=0).tolist()[0]\n",
|
|||
|
" pad1 = (x1max - x1min) / 10\n",
|
|||
|
" pad2 = (x2max - x2min) / 10\n",
|
|||
|
" step1 = (x1max - x1min) / 50\n",
|
|||
|
" step2 = (x2max - x2min) / 50\n",
|
|||
|
" x1grid, x2grid = np.meshgrid(\n",
|
|||
|
" np.arange(x1min - pad1, x1max + pad1, step1),\n",
|
|||
|
" np.arange(x2min - pad2, x2max + pad2, step2))\n",
|
|||
|
" z = np.matrix([[knn(X, Y, [x1, x2], k, distance) \n",
|
|||
|
" for x1, x2 in zip(x1row, x2row)] \n",
|
|||
|
" for x1row, x2row in zip(x1grid, x2grid)])\n",
|
|||
|
" plt.contour(x1grid, x2grid, z, levels=[0.5]);"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 13,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Przygotowanie interaktywnego wykresu\n",
|
|||
|
"\n",
|
|||
|
"slider_k = widgets.IntSlider(min=1, max=10, step=1, value=1, description=r'$k$', width=300)\n",
|
|||
|
"\n",
|
|||
|
"def interactive_knn_1(k):\n",
|
|||
|
" fig = plot_data_for_classification(X_outliers, Y_outliers, xlabel=u'dł. płatka', ylabel=u'szer. płatka')\n",
|
|||
|
" plot_voronoi(fig, X_outliers[:, 1:])\n",
|
|||
|
" plot_knn(fig, X_outliers[:, 1:], Y_outliers, k)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 14,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"application/vnd.jupyter.widget-view+json": {
|
|||
|
"model_id": "652f2d8ba643479298bc4e252b59474f",
|
|||
|
"version_major": 2,
|
|||
|
"version_minor": 0
|
|||
|
},
|
|||
|
"text/html": [
|
|||
|
"<p>Failed to display Jupyter Widget of type <code>interactive</code>.</p>\n",
|
|||
|
"<p>\n",
|
|||
|
" If you're reading this message in Jupyter Notebook or JupyterLab, it may mean\n",
|
|||
|
" that the widgets JavaScript is still loading. If this message persists, it\n",
|
|||
|
" likely means that the widgets JavaScript library is either not installed or\n",
|
|||
|
" not enabled. See the <a href=\"https://ipywidgets.readthedocs.io/en/stable/user_install.html\">Jupyter\n",
|
|||
|
" Widgets Documentation</a> for setup instructions.\n",
|
|||
|
"</p>\n",
|
|||
|
"<p>\n",
|
|||
|
" If you're reading this message in another notebook frontend (for example, a static\n",
|
|||
|
" rendering on GitHub or <a href=\"https://nbviewer.jupyter.org/\">NBViewer</a>),\n",
|
|||
|
" it may mean that your frontend doesn't currently support widgets.\n",
|
|||
|
"</p>\n"
|
|||
|
],
|
|||
|
"text/plain": [
|
|||
|
"interactive(children=(IntSlider(value=1, description=u'$k$', max=10, min=1), Button(description=u'Run Interact', style=ButtonStyle()), Output()), _dom_classes=('widget-interact',))"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"<function __main__.interactive_knn_1>"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 14,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"widgets.interact_manual(interactive_knn_1, k=slider_k)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 15,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Wczytanie danych (inny przykład)\n",
|
|||
|
"\n",
|
|||
|
"alldata = pandas.read_csv('classification.tsv', sep='\\t')\n",
|
|||
|
"data = np.matrix(alldata)\n",
|
|||
|
"\n",
|
|||
|
"m, n_plus_1 = data.shape\n",
|
|||
|
"n = n_plus_1 - 1\n",
|
|||
|
"Xn = data[:, 1:].reshape(m, n)\n",
|
|||
|
"\n",
|
|||
|
"X2 = np.matrix(np.concatenate((np.ones((m, 1)), Xn), axis=1)).reshape(m, n_plus_1)\n",
|
|||
|
"Y2 = np.matrix(data[:, 0]).reshape(m, 1)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 16,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "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\nJ5xCBQAAQBMIcAAAAAV
|
|||
|
"text/plain": [
|
|||
|
"<matplotlib.figure.Figure at 0x7f4688384150>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"fig = plot_data_for_classification(X2, Y2, xlabel=r'$x_1$', ylabel=r'$x_2$')"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 17,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "notes"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"# Przygotowanie interaktywnego wykresu\n",
|
|||
|
"\n",
|
|||
|
"slider_k = widgets.IntSlider(min=1, max=10, step=1, value=1, description=r'$k$', width=300)\n",
|
|||
|
"\n",
|
|||
|
"def interactive_knn_2(k):\n",
|
|||
|
" fig = plot_data_for_classification(X2, Y2, xlabel=r'$x_1$', ylabel=r'$x_2$')\n",
|
|||
|
" plot_voronoi(fig, X2[:, 1:])\n",
|
|||
|
" plot_knn(fig, X2[:, 1:], Y2, k)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 18,
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"application/vnd.jupyter.widget-view+json": {
|
|||
|
"model_id": "a10b0ca5c82349b596c12857fda3cd55",
|
|||
|
"version_major": 2,
|
|||
|
"version_minor": 0
|
|||
|
},
|
|||
|
"text/html": [
|
|||
|
"<p>Failed to display Jupyter Widget of type <code>interactive</code>.</p>\n",
|
|||
|
"<p>\n",
|
|||
|
" If you're reading this message in Jupyter Notebook or JupyterLab, it may mean\n",
|
|||
|
" that the widgets JavaScript is still loading. If this message persists, it\n",
|
|||
|
" likely means that the widgets JavaScript library is either not installed or\n",
|
|||
|
" not enabled. See the <a href=\"https://ipywidgets.readthedocs.io/en/stable/user_install.html\">Jupyter\n",
|
|||
|
" Widgets Documentation</a> for setup instructions.\n",
|
|||
|
"</p>\n",
|
|||
|
"<p>\n",
|
|||
|
" If you're reading this message in another notebook frontend (for example, a static\n",
|
|||
|
" rendering on GitHub or <a href=\"https://nbviewer.jupyter.org/\">NBViewer</a>),\n",
|
|||
|
" it may mean that your frontend doesn't currently support widgets.\n",
|
|||
|
"</p>\n"
|
|||
|
],
|
|||
|
"text/plain": [
|
|||
|
"interactive(children=(IntSlider(value=1, description=u'$k$', max=10, min=1), Button(description=u'Run Interact', style=ButtonStyle()), Output()), _dom_classes=('widget-interact',))"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"<function __main__.interactive_knn_2>"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 18,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"widgets.interact_manual(interactive_knn_2, k=slider_k)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"### Algorytm $k$ najbliższych sąsiadów dla problemu regresji\n",
|
|||
|
"\n",
|
|||
|
"1. Dany jest zbiór uczący zawierajacy przykłady $(x_i, y_i)$, gdzie: $x_i$ – zestaw cech, $y_i$ – liczba rzeczywista.\n",
|
|||
|
"1. Dany jest przykład testowy $x'$, dla którego chcemy określić klasę.\n",
|
|||
|
"1. Oblicz odległość $d(x', x_i)$ dla każdego przykładu $x_i$ ze zbioru uczącego.\n",
|
|||
|
"1. Wybierz $k$ przykładów $x_{i_1}, \\ldots, x_{i_k}$, dla których wyliczona odległość jest najmniejsza.\n",
|
|||
|
"1. Jako wynik $y'$ zwróć średnią liczb $y_{i_1}, \\ldots, y_{i_k}$:\n",
|
|||
|
" $$ y' = \\frac{1}{k} \\sum_{j=1}^{k} y_{i_j} $$"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"### Wybór $k$\n",
|
|||
|
"\n",
|
|||
|
"* Wartość $k$ ma duży wpływ na wynik działania algorytmu KNN:\n",
|
|||
|
" * Jeżeli $k$ jest zbyt duże, wszystkie nowe przykłady są klasyfikowane jako klasa większościowa.\n",
|
|||
|
" * Jeżeli $k$ jest zbyt małe, granice klas są niestabilne, a algorytm jest bardzo podatny na obserwacje odstające.\n",
|
|||
|
"* Aby dobrać optymalną wartość $k$, najlepiej użyć zbioru walidacyjnego."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"### Miary podobieństwa"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"#### Odległość euklidesowa\n",
|
|||
|
"$$ d(x, x') = \\sqrt{ \\sum_{i=1}^n \\left( x_i - x'_i \\right) ^2 } $$"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Dobry wybór w przypadku numerycznych cech.\n",
|
|||
|
"* Symetryczna, traktuje wszystkie wymiary jednakowo.\n",
|
|||
|
"* Wrażliwa na duże wahania jednej cechy."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"#### Odległość Hamminga\n",
|
|||
|
"$$ d(x, x') = \\sum_{i=1}^n \\mathbf{1}_{x_i \\neq x'_i} $$"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Dobry wybór w przypadku cech zero-jedynkowych.\n",
|
|||
|
"* Liczba cech, którymi różnią się dane przykłady."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "subslide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"#### Odległość Minkowskiego ($p$-norma)\n",
|
|||
|
"$$ d(x, x') = \\sqrt[p]{ \\sum_{i=1}^n \\left| x_i - x'_i \\right| ^p } $$"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Dla $p = 2$ jest to odległość euklidesowa.\n",
|
|||
|
"* Dla $p = 1$ jest to odległość taksówkowa.\n",
|
|||
|
"* Jeżeli $p \\to \\infty$, to $p$-norma zbliża się do logicznej alternatywy.\n",
|
|||
|
"* Jeżeli $p \\to 0$, to $p$-norma zbliża się do logicznej koniunkcji."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "slide"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"### KNN – praktyczne porady"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* Co zrobić z remisami?\n",
|
|||
|
" * losowanie\n",
|
|||
|
" * prawdopodobieństwo _a priori_\n",
|
|||
|
" * 1NN"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {
|
|||
|
"slideshow": {
|
|||
|
"slide_type": "fragment"
|
|||
|
}
|
|||
|
},
|
|||
|
"source": [
|
|||
|
"* KNN źle radzi sobie z brakującymi wartościami cech (nie można wówczas sensownie wyznaczyć odległości)."
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"metadata": {
|
|||
|
"celltoolbar": "Slideshow",
|
|||
|
"kernelspec": {
|
|||
|
"display_name": "Python 3",
|
|||
|
"language": "python",
|
|||
|
"name": "python3"
|
|||
|
},
|
|||
|
"language_info": {
|
|||
|
"codemirror_mode": {
|
|||
|
"name": "ipython",
|
|||
|
"version": 2
|
|||
|
},
|
|||
|
"file_extension": ".py",
|
|||
|
"mimetype": "text/x-python",
|
|||
|
"name": "python",
|
|||
|
"nbconvert_exporter": "python",
|
|||
|
"pygments_lexer": "ipython2",
|
|||
|
"version": "2.7.15rc1"
|
|||
|
},
|
|||
|
"livereveal": {
|
|||
|
"start_slideshow_at": "selected",
|
|||
|
"theme": "amu"
|
|||
|
}
|
|||
|
},
|
|||
|
"nbformat": 4,
|
|||
|
"nbformat_minor": 2
|
|||
|
}
|