{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Линейные методы классификации\n",
"Шестаков А.В. Майнор по анализу данных 15/03/2016"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сегодня мы рассмотрим следующие темы\n",
"\n",
"1. Задача классификации\n",
"2. Методы линейной классификации\n",
"3. Регуляризация линейной регрессии и градиентный спуск"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Задача классификации"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"На прошлом семинаре мы рассматривали модели регрессии - случай, в котором необходимо было предсказать вещественную переменную $y \\in \\mathbb{R}^n$ (Стоимость автомобиля, стоимость жилья, размер мозга, объемы продаж и тп.)\n",
"\n",
"В задаче классификации переменная $y$ - содержит метку принадлежности к классу, как, например, это было в задаче с наивным байесом - категорию текстов. Частный случай задачи классификации - бинарная классификация $y = \\{-1, 1\\}$. Например: является ли клиент банка кредитоспособным, доброкачественная ли опухоль, сообщение - SPAM или HAM?\n",
"\n",
"Спрашивается, почему бы нам не взять, да и построить обычную регрессию на метки класса $y$?
\n",
"Загрузите [данные](https://www.dropbox.com/s/g3s1drtaxqwthw1/crx.data?dl=0) о кредитовании. Они достаточно сильно анонимизированны и еще не до конца подходят для применения, но сейчас это нам не помешает. Постройте график наблюдений в координатах `y` и `a15`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"plt.style.use('ggplot')\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"df = pd.read_csv('crx.data',index_col=None) \n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Your code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Почему бы не обучить по этим данным регрессию, предстказывающую значение $y$? Да потому что это ~~бред~~ не очень корректно!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Методы линейной классификации"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обратимся к слегка идеализированному варианту, линейно разделимой выборке:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Нам надо найти уравнение прямой (гиперплоскости), которая бы могла разделить два класса ($H_2$ и $H_3$ подходят). В данном случае, уравнение прямой задаётся как: $$g(x) = w_0 + w_1x_1 + w_2x_2 = \\langle w, x \\rangle = w^\\top x$$\n",
"\n",
"* Если $g(x^*) > 0$, то $y^* = \\text{'черный'}$\n",
"* Если $g(x^*) < 0$, то $y^* = \\text{'белый'}$\n",
"* Если $g(x^*) = 0$, то мы находимся на линии\n",
"* т.е. решающее правило: $y^* = sign(g(x^*))$\n",
"\n",
"Некоторые геометрические особенности\n",
"* $\\frac{w_0}{||w||}$ - расстояние от начала координат то прямой\n",
"* $\\frac{|g(x)|}{||w||}$ - степень \"уверенности\" в классификациий\n",
"* Величину $M = y\\langle w, x \\rangle = y \\cdot g(x)$ называют **отступом**(margin)\n",
"\n",
"Если для какого-то объекта $M \\geq 0$, то его классификация выполнена успешно."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Отлично! Значит нам надо просто минимизировать ошибки классификации для всех объектов:\n",
"\n",
"$$L(w) = \\sum_i [y^{(i)} \\langle w, x^{(i)} \\rangle < 0] \\rightarrow \\min_w$$\n",
"Проблема в том, что это будет комбинаторная оптимизация. Существуют различные аппроксимации этой функции ошибок:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Знакомьтесь - Перцептрон!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Это самая простая модель человеческой нейронной сети. В ней есть входы, которые взвешиваются и суммируются. Затем взвешенная сумма проходит через некую функцию активации (в данном случае $sign(\\cdot)$)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Перцептрон можно использовать для классификации.
\n",
"Существует итерационный алгоритм, который корректирует веса $w_0 \\cdots w_n$ до тех пор, пока ошибки имею место быть:\n",
" \n",
"```python\n",
"Randomly initialize weights: w=(w_0, \\dots, w_d)\n",
"Until no errors on train set:\n",
" for i in xrange(N):\n",
" if y_i * w.T * x_i < 0:\n",
" w = w + alpha * y_i * x_i\n",
"```\n",
"Этот алгоритм гарантированно сходится для линейно разделимой выборки.\n",
"А если это не наш случай?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Знакомьтесь - Логистическая регрессия!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Перед тем как мы начнем, рассмотрим функцию $$\\sigma(z) = \\frac{1}{1 + exp{(-z)}},$$она называется **сигмойда**. Постройте данную фукнцию."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Your code here\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можно несколькими способами представить линейную регрессию. Один из самых простых - вот какой.\n",
"\n",
"Рассмотрим принадлежность к классу $y=\\pm1$ некого объекта $x$: $p(y=\\pm1 | x,w)$ и выразим её через **сигмойду** от **отступа**:\n",
"$$p(y=\\pm1|x,w) = \\sigma(y \\langle w, x \\rangle) $$\n",
"\n",
"Будем максимизировать правдоподобие $$\\mathcal{L}(w) = \\prod_i p(y^{(i)}|x^{(i)},w) \\rightarrow \\max_w$$\n",
"Возьмем от этого логарифм и поставим минус - получится минимизация логарифмической функции потерь:\n",
"\n",
"$$L(w) = -\\sum_i \\log(\\sigma(y^{(i)} \\langle w, x^{(i)} \\rangle)) \\rightarrow \\min_w$$\n",
"\n",
"Посчитаем градиент этой функции потерь по $w$:\n",
"\n",
"$$ \\frac{\\partial L(w)}{\\partial w} = \\dots$$\n",
"\n",
"**История с градиентным спуском, регуляризацией, мультиколлинеарностью и шкалированием признаков здесь полностью повторяется!**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сгенерируем выборку и применим к ней линейную регрессию"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"np.random.seed(0)\n",
"X = np.r_[np.random.randn(20, 2) + [2, 2],\n",
" np.random.randn(20, 2) + [-2, -2]]\n",
"y = [-1] * 20 + [1] * 20"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(7, 7))\n",
"ax.scatter(X[:, 0],\n",
" X[:, 1],\n",
" c=y,\n",
" cmap=plt.cm.Paired)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from sklearn.linear_model import LogisticRegression"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обучите LogisticRegression() на данных `X` и `y`, изобразите разделяющую прямую"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"model = LogisticRegression()\n",
"## Your code here"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"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.11"
}
},
"nbformat": 4,
"nbformat_minor": 0
}