Меню

Обучение линейных классификаторов через минимизацию верхней оценки на долю ошибок

Материал из MachineLearning.

Перейти к: навигация, поиск

Содержание

  • 1 Определение
    • 1.1 Случай двух классов
    • 1.2 Случай произвольного числа классов
  • 2 Обучение линейного классификатора
    • 2.1 Метод минимизации эмпирического риска
    • 2.2 Понятие отступа
    • 2.3 Замена пороговой функции потерь
    • 2.4 Регуляризация
  • 3 Методы обучения линейных классификаторов
    • 3.1 Линейный дискриминант Фишера
    • 3.2 Однослойный перцептрон
    • 3.3 Метод опорных векторов
    • 3.4 Логистическая регрессия
    • 3.5 Пробит-аппроксимация
    • 3.6 Экспоненциальная аппроксимация
  • 4 Связь с другими методами
  • 5 Литература
  • 6 Ссылки

Линейный классификатор — алгоритм классификации, основанный на построении линейной разделяющей поверхности. В случае двух классов разделяющей поверхностью является гиперплоскость, которая делит пространство признаков на два полупространства.
В случае большего числа классов разделяющая поверхность кусочно-линейна.

Определение

Пусть объекты описываются n числовыми признаками
f_j:: Xtomathbb{R},; j=1,ldots,n.
Тогда пространство признаковых описаний объектов есть X=mathbb{R}^n.
Пусть Y — конечное множество номеров (имён, меток) классов.

Случай двух классов

Положим Y={-1,+1}.

Линейным классификатором называется алгоритм классификации a:; Xto Y вида

a(x,w) = mathrm{sign}left( sum_{j=1}^n w_j f_j(x) - w_0 right) = mathrm{sign}langle x,w rangle,

где
w_j — вес j-го признака,
w_0 — порог принятия решения,
w=(w_0,w_1,ldots,w_n) — вектор весов,
langle x,w rangle — скалярное произведение признакового описания объекта на вектор весов.
Предполагается, что искусственно введён «константный» нулевой признак: f_{0}(x)=-1.

Случай произвольного числа классов

Линейный классификатор определяется выражением

a(x,w) = mathrm{arg}max_{yin Y}, sum_{j=0}^n w_{yj} f_j(x) = mathrm{arg}max_{yin Y}, langle x,w_y rangle,

где каждому классу соотвествует свой вектор весов w_y=(w_{y0},w_{y1},ldots,w_{yn}).

Обучение линейного классификатора

Метод минимизации эмпирического риска

Обучение (настройка) линейного классификатора методом минимизации эмпирического риска заключается в том, чтобы по заданной обучающей выборке пар «объект, ответ»
X^m = {(x_1,y_1),dots,(x_m,y_m)}
построить алгоритм a:; Xto Y указанного вида,
минимизирующий фунционал эмпирического риска:

Q(w) = sum_{i=1}^m bigl[ a(x_i,w) neq y_i bigr] to min_w.

Методы обучения линейных классификаторов различаются подходами к решению данной оптимизационной задачи.

Понятие отступа

В случае двух классов, Y={-1,+1},
удобно определить для произвольного обучающего объекта x_iin X^m величину отступа (margin):

M(x_i) = y_i langle x_i,w rangle.

В случае произвольного числа классов отступ определяется выражением

M(x_i) = langle x_i,w_{y_i} rangle - !max_{yin Y,, yneq y_i}! langle x_i,w_y rangle.

Отступ можно понимать как «степень погруженности» объекта в свой класс.
Чем меньше значение отступа M(x_i), тем ближе объект подходит к границе классов, тем выше становится вероятность ошибки.
Отступ M(x_i) отрицателен тогда и только тогда, когда
алгоритм a(x) допускает ошибку на объекте x_i.
Это наблюдение позволяет записать фунционал эмпирического риска в следующем виде:

Q(w) = sum_{i=1}^m bigl[ M(x_i) < 0 bigr].

Замена пороговой функции потерь

Минимизация функционала Q(w) по вектору весов сводится к поиску максимальной совместной подсистемы в системе неравенств.
Эта задача является NP-полной и может иметь очень много решений, поскольку минимальное число ошибок может реализоваться на различных подмножествах объектов.
Однако абсолютно точное решение этой задачи, и, тем более, нахождение всех её решений, в большинстве приложений не представляет практического интереса.
Обычно вполне устраивает приближённое решение, достаточно близкое к точному.

Наиболее известные методы обучения линейного классификатора связаны с заменой пороговой функции потерь её различными непрерывными аппроксимациями:

bigl[ M < 0 bigr] leq L(M),

где
L::mathbb{R}tomathbb{R}_{+} — непрерывная или гладкая функция, как правило, невозрастающая.

После замены функции потерь минимизируется не сам функционал эмпирического риска, а его верхняя оценка.

Q(w) leq tilde Q(w) = sum_{i=1}^m Lbigl( M(x_i) bigr).

Применение аппроксимаций имеет ряд преимуществ.

  • Некоторые аппроксимации способны улучшать обобщающую способность классификатора. В частности, известно, что пробит-аппроксимация при некоторых условиях уменьшает вероятность ошибки [Langford, McAllester].
  • Непрерывные аппроксимации позволяют применять известные численные методы оптимизации для настройки весов w_j, в частности, градиентные методы и методы выпуклого программирования.

Регуляризация

Наряду с заменой пороговой функции потерь, рекомендуется добавлять к функционалу штрафное слагаемое, запрещающее слишком большие значения нормы вектора весов:

Q(w) leq tilde Q(w) = sum_{i=1}^m Lbigl( M(x_i) bigr) + gamma ||w||^p to min_w.

Добавление штрафного слагаемого или регуляризация снижает риск переобучения и повышает устойчивость вектора весов по отношению к малым изменениям обучающей выборки.
Идея регуляризации предлагалась разными авторами, в разные годы, для разных алгоритмов, и называлась, соотвественно, по разному:
сокращение весов (weght decay) — в нейронных сетях,
гребневая регрессия (ridge regression) — в регрессионном анализе,
сжатие весов (shrinkage).

Параметр регуляризации gamma подбирается исходя из априорных соображений, либо по скользящему контролю.
Существуют также теоретические оценки обобщающей способности линейного классификатора, позволяющие оценивать параметр регуляризации по явным формулам.

Степень регуляризатора p определяет класс методов оптимизации.

Методы обучения линейных классификаторов

Методы обучения линейных классификаторов различаются, главным образом, выбором функции L(M), способом регуляризации и выбором численного метода оптимизации.

Линейный дискриминант Фишера

Линейный дискриминант Фишера соответствует квадратичной аппроксимации при условии, что из каждого вектора признаков предварительно вычитается вектор центра класса:

bigl[ M < 0 bigr] leq (1-M)^2.

Задача обучения решается методом наименьших квадратов.

Однослойный перцептрон

Аппроксимация сигмоидной или логит-функцией иногда используется при настройке
однослойного перцептрона и нейронных сетей:

bigl[ M < 0 bigr] leq frac2{1+e^{alpha M}}.

где
параметр alpha задаётся априори.

Задача минимизации в общем случае многоэкстремальна, поскольку логит-функция не выпукла.
Кроме того, логит-функция имеет горизонтальные асимптоты,
что может приводить к проблеме паралича при использовании градиентных методов минимизации.
Применение логит-функции требует введения дополнительных эвристик для уменьшения переобучения
(регуляризация, стохастические шаги для выбивания из локальных минимумов).

Метод опорных векторов

Метод опорных векторов соответствует кусочно-линейной аппроксимации:

bigl[ M < 0 bigr] leq (1-M)_{+}.

При этом обязательно применяется регуляризация с квадратичной нормой.
Задача обучения решается специализированными методами квадратичного программирования.

Логистическая регрессия

Логистическая регрессия соответствует логарифмической аппроксимации:

bigl[ M < 0 bigr] leq log_2(1+e^{-M}).

При некоторых (достаточно сильных) предположениях о функциях правдоподобия классов минимизация эмпирического риска с такой функцией потерь эквивалентна максимизации правдоподобия. При этом линейный классификатор является оптимальным байесовским классификатором, а значение линейной дискриминантной функции связано с апостериорной вероятностью классов (для случая двух классов):

sigmaleft( M(x) right) = sigmaleft( ylangle w,x rangle right) = mathbb{P}{y|x},

где sigma(z) = frac1{1+e^{-z}} — сигмоидная функция.

Задача обучения решается градиентным методом второго порядка, что приводит к методу наименьших квадратов с итеративным пересчетом весов IRLS.

Логистическая регрессия является частным случаем обобщённой линейной модели регрессии.

Пробит-аппроксимация

Аппроксимация пробит-функцией обоснована в рамках байесовской теории вероятно приближённо корректного обучения (PAC-Bayesian approach) [Langford, McAllester]:

bigl[ M < 0 bigr] leq 2Phi(-alpha M),

где
Phi(z) — функция нормального распределения с нулевым средним и единичной дисперсией;
параметр alpha вычисляется по явным формулам.

Методы минимизации в теории не рассматриваются.
Однако очевидно, что задача в общем случае многоэкстремальна, поскольку пробит-функция не выпукла.
Кроме того, пробит-функция имеет горизонтальные асимптоты,
что может приводить к проблеме паралича при использовании градиентных методов минимизации.
Применение пробит-функции требует введения дополнительных эвристик для уменьшения переобучения
(регуляризация, стохастические шаги для выбивания из локальных минимумов).

Экспоненциальная аппроксимация

Экспоненциальная аппроксимация используется в алгоритмах бустинга, в частности, в алгоритме AdaBoost:

bigl[ M < 0 bigr] leq exp(-M).

Недостаток этой аппроксимации в том, что она слишком сильно штрафует большие по абсолютной величине отрицательные отступы. Если в данных есть объекты-выбросы, то основные усилия процедуры обучения будут сосредоточены на увеличении небольшого числа сильно отрицательных отступов — вместо того, чтобы уменьшать число ошибок классификации путём увеличения основной массы отступов, близких к нулю.

Связь с другими методами

Метод ближайшего соседа в пространстве признаков с евклидовой метрикой определяет границу между классами как кусочно-линейную поверхность. В частности, метод реализует линейный классификатор, если в обучающей выборке оставить по одному объекту от каждого класса.

Литература

  1. Айвазян С. А., Бухштабер В. М., Енюков И. С., Мешалкин Л. Д. Прикладная статистика: классификация и снижение размерности. — М.: Финансы и статистика, 1989.
  2. Вапник В. Н., Червоненкис А. Я. Теория распознавания образов. — М.: Наука, 1974. — 416 с.  (подробнее)
  3. Вапник В. Н. Восстановление зависимостей по эмпирическим данным. — М.: Наука, 1979. — 448 с.  (подробнее)
  4. Дуда Р., Харт П. Распознавание образов и анализ сцен. — М.: Мир, 1976.
  5. Hastie, T., Tibshirani, R., Friedman, J. The Elements of Statistical Learning, 2nd edition. — Springer, 2009. — 533 p.  (подробнее)
  6. Langford J. Tutorial on Practical Prediction Theory for Classification. — 2005. — 28 P.
  7. McAllester D. Simplified PAC-Bayesian Margin Bounds. — 2003.

Ссылки

  • Машинное обучение (курс лекций, К.В.Воронцов)

Всем привет!

Сегодня мы детально обсудим очень важный класс моделей машинного обучения – линейных. Ключевое отличие нашей подачи материала от аналогичной в курсах эконометрики и статистики – это акцент на практическом применении линейных моделей в реальных задачах (хотя и математики тоже будет немало).

Пример такой задачи – это соревнование Kaggle Inclass по идентификации пользователя в Интернете по его последовательности переходов по сайтам.

UPD 01.2022: С февраля 2022 г. ML-курс ODS на русском возрождается под руководством Петра Ермакова couatl. Для русскоязычной аудитории это предпочтительный вариант (c этими статьями на Хабре – в подкрепление), англоговорящим рекомендуется mlcourse.ai в режиме самостоятельного прохождения.

Все материалы доступны на GitHub.
А вот видеозапись лекции по мотивам этой статьи в рамках второго запуска открытого курса (сентябрь-ноябрь 2017). В ней, в частности, рассмотрены два бенчмарка соревнования, полученные с помощью логистической регрессии.

План этой статьи:

  1. Линейная регрессия
    • Метод наименьших квадратов
    • Метод максимального правдоподобия
    • Разложение ошибки на смещение и разброс (Bias-variance decomposition)
    • Регуляризация линейной регрессии
  2. Логистическая регрессия
    • Линейный классификатор
    • Логистическая регрессия как линейный классификатор
    • Принцип максимального правдоподобия и логистическая регрессия
    • L2-регуляризация логистической функции потерь
  3. Наглядный пример регуляризации логистической регрессии
  4. Где логистическая регрессия хороша и где не очень
    -Анализ отзывов IMDB к фильмам
    -XOR-проблема
  5. Кривые валидации и обучения
  6. Плюсы и минусы линейных моделей в задачах машинного обучения
  7. Домашнее задание №4
  8. Полезные ресурсы

1. Линейная регрессия

Метод наименьших квадратов

Рассказ про линейные модели мы начнем с линейной регрессии. В первую очередь, необходимо задать модель зависимости объясняемой переменной $y$ от объясняющих ее факторов, функция зависимости будет линейной: $y = w_0 + sum_{i=1}^m w_i x_i$. Если мы добавим фиктивную размерность $x_0 = 1$ для каждого наблюдения, тогда линейную форму можно переписать чуть более компактно, записав свободный член $w_0$ под сумму: $y = sum_{i=0}^m w_i x_i = vec{w}^T vec{x}$. Если рассматривать матрицу наблюдения-признаки, у которой в строках находятся примеры из набора данных, то нам необходимо добавить единичную колонку слева. Зададим модель следующим образом:

$large vec y = X vec w + epsilon,$

где

Можем выписать выражение для каждого конкретного наблюдения

$large y_i = sum_{j=0}^m w_j X_{ij} + epsilon_i$

Также на модель накладываются следующие ограничения (иначе это будет какая то другая регрессия, но точно не линейная):

Оценка $hat{w}_i$ весов $w_i$ называется линейной, если

$large hat{w}_i = omega_{1i}y_1 + omega_{2i}y_2 + cdots + omega_{ni}y_n,$

где $forall k omega_{ki}$ зависит только от наблюдаемых данных $X$ и почти наверняка нелинейно. Так как решением задачи поиска оптимальных весов будет именно линейная оценка, то и модель называется линейной регрессией. Введем еще одно определение. Оценка $hat{w}_i$ называется несмещенной тогда, когда матожидание оценки равно реальному, но неизвестному значению оцениваемого параметра:

$large mathbb{E}left[hat{w}_iright] = w_i$

Один из способов вычислить значения параметров модели является метод наименьших квадратов (МНК), который минимизирует среднеквадратичную ошибку между реальным значением зависимой переменной и прогнозом, выданным моделью:

$large begin{array}{rcl}mathcal{L}left(X, vec{y}, vec{w} right) &=& frac{1}{2n} sum_{i=1}^n left(y_i - vec{w}^T vec{x}_iright)^2 \ &=& frac{1}{2n} left| vec{y} - X vec{w} right|_2^2 \ &=& frac{1}{2n} left(vec{y} - X vec{w}right)^T left(vec{y} - X vec{w}right) end{array}$

Для решения данной оптимизационной задачи необходимо вычислить производные по параметрам модели, приравнять их к нулю и решить полученные уравнения относительно $vec w$ (матричное дифференцирование неподготовленному читателю может показаться затруднительным, попробуйте расписать все через суммы, чтобы убедиться в ответе):

Шпаргалка по матричным производным

$large begin{array}{rcl} frac{partial}{partial x} x^T a &=& a \ frac{partial}{partial x} x^T A x &=& left(A + A^Tright)x \ frac{partial}{partial A} x^T A y &=& xy^T\ frac{partial}{partial x} A^{-1} &=& -A^{-1} frac{partial A}{partial x} A^{-1} end{array}$

$large begin{array}{rcl} frac{partial mathcal{L}}{partial vec{w}} &=& frac{partial}{partial vec{w}} frac{1}{2n} left( vec{y}^T vec{y} -2vec{y}^T X vec{w} + vec{w}^T X^T X vec{w}right) \ &=& frac{1}{2n} left(-2 X^T vec{y} + 2X^T X vec{w}right) end{array}$

$large begin{array}{rcl} frac{partial mathcal{L}}{partial vec{w}} = 0 &Leftrightarrow& frac{1}{2n} left(-2 X^T vec{y} + 2X^T X vec{w}right) = 0 \ &Leftrightarrow& -X^T vec{y} + X^T X vec{w} = 0 \ &Leftrightarrow& X^T X vec{w} = X^T vec{y} \ &Leftrightarrow& vec{w} = left(X^T Xright)^{-1} X^T vec{y} end{array}$

Итак, имея в виду все определения и условия описанные выше, мы можем утверждать, опираясь на теорему Маркова-Гаусса, что оценка МНК является лучшей оценкой параметров модели, среди всех линейных и несмещенных оценок, то есть обладающей наименьшей дисперсией.

Метод максимального правдоподобия

У читателя вполне резонно могли возникнуть вопросы: например, почему мы минимизируем среднеквадратичную ошибку, а не что-то другое. Ведь можно минимизировать среднее абсолютное значение невязки или еще что-то. Единственное, что произойдёт в случае изменения минимизируемого значения, так это то, что мы выйдем из условий теоремы Маркова-Гаусса, и наши оценки перестанут быть лучшими среди линейных и несмещенных.

Давайте перед тем как продолжить, сделаем лирическое отступление, чтобы проиллюстрировать метод максимального правдоподобия на простом примере.

Как-то после школы я заметил, что все помнят формулу этилового спирта. Тогда я решил провести эксперимент: помнят ли люди более простую формулу метилового спирта: $CH_3OH$. Мы опросили 400 человек и оказалось, что формулу помнят всего 117 человек. Разумно предположить, что вероятность того, что следующий опрошенный знает формулу метилового спирта – $frac{117}{400} approx 0.29%$. Покажем, что такая интуитивно понятная оценка не просто хороша, а еще и является оценкой максимального правдоподобия.

Разберемся, откуда берется эта оценка, а для этого вспомним определение распределения Бернулли: случайная величина $X$ имеет распределение Бернулли, если она принимает всего два значения ($1$ и $0$ с вероятностями $theta$ и $1 - theta$ соответственно) и имеет следующую функцию распределения вероятности:

$large pleft(theta, xright) = theta^{x} left(1 - thetaright)^left(1 - xright), x in left{0, 1right}$

Похоже, это распределение – то, что нам нужно, а параметр распределения $theta$ и есть та оценка вероятности того, что человек знает формулу метилового спирта. Мы проделали $400$ независимых экспериментов, обозначим их исходы как $vec{x} = left(x_1, x_2, ldots, x_{400}right)$. Запишем правдоподобие наших данных (наблюдений), то есть вероятность наблюдать 117 реализаций случайной величины $X = 1$ и 283 реализации $X = 0$:

$large p(vec{x} mid theta) = prod_{i=1}^{400} theta^{x_i} left(1 - thetaright)^{left(1 - x_iright)} = theta^{117} left(1 - thetaright)^{283}$

Далее будем максимизировать это выражение по $theta$, и чаще всего это делают не с правдоподобием $p(vec{x} mid theta)$, а с его логарифмом (применение монотонного преобразования не изменит решение, но упростит вычисления):

$large log p(vec{x} mid theta) = log prod_{i=1}^{400} theta^{x_i} left(1 - thetaright)^{left(1 - x_iright)} = $

$ large = log theta^{117} left(1 - thetaright)^{283} = 117 log theta + 283 log left(1 - thetaright)$

Теперь мы хотим найти такое значение $theta$, которое максимизирует правдоподобие, для этого мы возьмем производную по $theta$, приравняем к нулю и решим полученное уравнение:

$large frac{partial p(vec{x} mid theta)}{partial theta} = frac{partial}{partial theta} left(117 log theta + 283 log left(1 - thetaright)right) = frac{117}{theta} - frac{283}{1 - theta};$

$large begin{array}{rcl} frac{117}{theta} - frac{283}{1 - theta} = 0 Rightarrow theta = frac{117}{400} end{array}.$

Получается, что наша интуитивная оценка – это и есть оценка максимального правдоподобия. Применим теперь те же рассуждения для задачи линейной регрессии и попробуем выяснить, что лежит за среднеквадратичной ошибкой. Для этого нам придется посмотреть на линейную регрессию с вероятностной точки зрения. Модель, естественно, остается такой же:

$large vec y = X vec w + epsilon,$

но будем теперь считать, что случайные ошибки берутся из центрированного нормального распределения:

$large epsilon_i sim mathcal{N}left(0, sigma^2right)$

Перепишем модель в новом свете:

$large begin{array}{rcl} pleft(y_i mid X, vec{w}right) &=& sum_{j=1}^m w_j X_{ij} + mathcal{N}left(0, sigma^2right) \ &=& mathcal{N}left(sum_{j=1}^m w_j X_{ij}, sigma^2right) end{array}$

Так как примеры берутся независимо (ошибки не скоррелированы – одно из условий теоремы Маркова-Гаусса), то полное правдоподобие данных будет выглядеть как произведение функций плотности $pleft(y_iright)$. Рассмотрим логарифм правдоподобия, что позволит нам перейти от произведения к сумме:

$large begin{array}{rcl} log pleft(vec{y} mid X, vec{w}right) &=& log prod_{i=1}^n mathcal{N}left(sum_{j=1}^m w_j X_{ij}, sigma^2right) \ &=& sum_{i=1}^n log mathcal{N}left(sum_{j=1}^m w_j X_{ij}, sigma^2right) \ &=& -frac{n}{2}log 2pisigma^2 -frac{1}{2sigma^2} sum_{i=1}^n left(y_i - vec{w}^T vec{x}_iright)^2 end{array}$

Мы хотим найти гипотезу максимального правдоподобия, т.е. нам нужно максимизировать выражение $pleft(vec{y} mid X, vec{w}right)$, а это то же самое, что и максимизация его логарифма. Обратите внимание, что при максимизации функции по какому-то параметру можно выкинуть все члены, не зависящие от этого параметра:

$large begin{array}{rcl} hat{w} &=& arg max_{w} pleft(vec{y} mid X, vec{w}right) \ &=& arg max_{w} -frac{n}{2}log 2pisigma^2 -frac{1}{2sigma^2} sum_{i=1}^n left(y_i - vec{w}^T vec{x}_iright)^2 \ &=& arg max_{w} -frac{1}{2sigma^2} sum_{i=1}^n left(y_i - vec{w}^T vec{x}_iright)^2 \ &=& arg max_{w} -mathcal{L}left(X, vec{y}, vec{w} right) end{array}$

Таким образом, мы увидели, что максимизация правдоподобия данных – это то же самое, что и минимизация среднеквадратичной ошибки (при справедливости указанных выше предположений). Получается, что именно такая функция стоимости является следствием того, что ошибка распределена нормально, а не как-то по-другому.

Разложение ошибки на смещение и разброс (Bias-variance decomposition)

Поговорим немного о свойствах ошибки прогноза линейной регрессии (в принципе эти рассуждения верны для всех алгоритмов машинного обучения). В свете предыдущего пункта мы выяснили, что:

Тогда ошибка в точке $vec{x}$ раскладывается следующим образом:

$large begin{array}{rcl} text{Err}left(vec{x}right) &=& mathbb{E}left[left(y - hat{f}left(vec{x}right)right)^2right] \ &=& mathbb{E}left[y^2right] + mathbb{E}left[left(hat{f}left(vec{x}right)right)^2right] - 2mathbb{E}left[yhat{f}left(vec{x}right)right] \ &=& mathbb{E}left[y^2right] + mathbb{E}left[hat{f}^2right] - 2mathbb{E}left[yhat{f}right] \ end{array}$

Для наглядности опустим обозначение аргумента функций. Рассмотрим каждый член в отдельности, первые два расписываются легко по формуле $text{Var}left(zright) = mathbb{E}left[z^2right] - mathbb{E}left[zright]^2$:

$large begin{array}{rcl} mathbb{E}left[y^2right] &=& text{Var}left(yright) + mathbb{E}left[yright]^2 = sigma^2 + f^2\ mathbb{E}left[hat{f}^2right] &=& text{Var}left(hat{f}right) + mathbb{E}left[hat{f}right]^2 \ end{array}$

Пояснения:

$large begin{array}{rcl} text{Var}left(yright) &=& mathbb{E}left[left(y - mathbb{E}left[yright]right)^2right] \ &=& mathbb{E}left[left(y - fright)^2right] \ &=& mathbb{E}left[left(f + epsilon - fright)^2right] \ &=& mathbb{E}left[epsilon^2right] = sigma^2 end{array}$

$large mathbb{E}[y] = mathbb{E}[f + epsilon] = mathbb{E}[f] + mathbb{E}[epsilon] = f$

И теперь последний член суммы. Мы помним, что ошибка и целевая переменная независимы друг от друга:

$large begin{array}{rcl} mathbb{E}left[yhat{f}right] &=& mathbb{E}left[left(f + epsilonright)hat{f}right] \ &=& mathbb{E}left[fhat{f}right] + mathbb{E}left[epsilonhat{f}right] \ &=& fmathbb{E}left[hat{f}right] + mathbb{E}left[epsilonright] mathbb{E}left[hat{f}right] = fmathbb{E}left[hat{f}right] end{array}$

Наконец, собираем все вместе:

$large begin{array}{rcl} text{Err}left(vec{x}right) &=& mathbb{E}left[left(y - hat{f}left(vec{x}right)right)^2right] \ &=& sigma^2 + f^2 + text{Var}left(hat{f}right) + mathbb{E}left[hat{f}right]^2 - 2fmathbb{E}left[hat{f}right] \ &=& left(f - mathbb{E}left[hat{f}right]right)^2 + text{Var}left(hat{f}right) + sigma^2 \ &=& text{Bias}left(hat{f}right)^2 + text{Var}left(hat{f}right) + sigma^2 end{array}$

Итак, мы достигли цели всех вычислений, описанных выше, последняя формула говорит нам, что ошибка прогноза любой модели вида $y = fleft(vec{x}right) + epsilon$ складывается из:

Если с последней мы ничего сделать не можем, то на первые два слагаемых мы можем как-то влиять. В идеале, конечно же, хотелось бы свести на нет оба этих слагаемых (левый верхний квадрат рисунка), но на практике часто приходится балансировать между смещенными и нестабильными оценками (высокая дисперсия).

Как правило, при увеличении сложности модели (например, при увеличении количества свободных параметров) увеличивается дисперсия (разброс) оценки, но уменьшается смещение. Из-за того что тренировочный набор данных полностью запоминается вместо обобщения, небольшие изменения приводят к неожиданным результатам (переобучение). Если же модель слабая, то она не в состоянии выучить закономерность, в результате выучивается что-то другое, смещенное относительно правильного решения.

Теорема Маркова-Гаусса как раз утверждает, что МНК-оценка параметров линейной модели является самой лучшей в классе несмещенных линейных оценок, то есть с наименьшей дисперсией. Это значит, что если существует какая-либо другая несмещенная модель $g$ тоже из класса линейных моделей, то мы можем быть уверены, что $Varleft(hat{f}right) leq Varleft(gright)$.

Регуляризация линейной регрессии

Иногда бывают ситуации, когда мы намеренно увеличиваем смещенность модели ради ее стабильности, т.е. ради уменьшения дисперсии модели $text{Var}left(hat{f}right)$. Одним из условий теоремы Маркова-Гаусса является полный столбцовый ранг матрицы $X$. В противном случае решение МНК $vec{w} = left(X^T Xright)^{-1} X^T vec{y}$ не существует, т.к. не будет существовать обратная матрица $left(X^T Xright)^{-1}.$ Другими словами, матрица $X^T X$ будет сингулярна, или вырожденна. Такая задача называется некорректно поставленной. Задачу нужно скорректировать, а именно, сделать матрицу $X^TX$ невырожденной, или регулярной (именно поэтому этот процесс называется регуляризацией). Чаще в данных мы можем наблюдать так называемую мультиколлинеарность — когда два или несколько признаков сильно коррелированы, в матрице $X$ это проявляется в виде «почти» линейной зависимости столбцов. Например, в задаче прогнозирования цены квартиры по ее параметрам «почти» линейная зависимость будет у признаков «площадь с учетом балкона» и «площадь без учета балкона». Формально для таких данных матрица $X^T X$ будет обратима, но из-за мультиколлинеарности у матрицы $X^T X$ некоторые собственные значения будут близки к нулю, а в обратной матрице $left(X^T Xright)^{-1}$ появятся экстремально большие собственные значения, т.к. собственные значения обратной матрицы – это $frac{1}{lambda_i}$. Итогом такого шатания собственных значений станет нестабильная оценка параметров модели, т.е. добавление нового наблюдения в набор тренировочных данных приведёт к совершенно другому решению. Иллюстрации роста коэффициентов вы найдете в одном из наших прошлых постов. Одним из способов регуляризации является регуляризация Тихонова, которая в общем виде выглядит как добавление нового члена к среднеквадратичной ошибке:

$large begin{array}{rcl} mathcal{L}left(X, vec{y}, vec{w} right) &=& frac{1}{2n} left| vec{y} - X vec{w} right|_2^2 + left|Gamma vec{w}right|^2\ end{array}$

Часто матрица Тихонова выражается как произведение некоторого числа на единичную матрицу: $Gamma = frac{lambda}{2} E$. В этом случае задача минимизации среднеквадратичной ошибки становится задачей с ограничением на $L_2$ норму. Если продифференцировать новую функцию стоимости по параметрам модели, приравнять полученную функцию к нулю и выразить $vec{w}$, то мы получим точное решение задачи.

$large begin{array}{rcl} vec{w} &=& left(X^T X + lambda Eright)^{-1} X^T vec{y} end{array}$

Такая регрессия называется гребневой регрессией (ridge regression). А гребнем является как раз диагональная матрица, которую мы прибавляем к матрице $X^T X$, в результате получается гарантированно регулярная матрица.

Такое решение уменьшает дисперсию, но становится смещенным, т.к. минимизируется также и норма вектора параметров, что заставляет решение сдвигаться в сторону нуля. На рисунке ниже на пересечении белых пунктирных линий находится МНК-решение. Голубыми точками обозначены различные решения гребневой регрессии. Видно, что при увеличении параметра регуляризации $lambda$ решение сдвигается в сторону нуля.

Советуем обратиться в наш прошлый пост за примером того, как $L_2$ регуляризация справляется с проблемой мультиколлинеарности, а также чтобы освежить в памяти еще несколько интерпретаций регуляризации.

2. Логистическая регрессия

Линейный классификатор

Основная идея линейного классификатора заключается в том, что признаковое пространство может быть разделено гиперплоскостью на два полупространства, в каждом из которых прогнозируется одно из двух значений целевого класса.
Если это можно сделать без ошибок, то обучающая выборка называется линейно разделимой.

Мы уже знакомы с линейной регрессией и методом наименьших квадратов. Рассмотрим задачу бинарной классификации, причем метки целевого класса обозначим «+1» (положительные примеры) и «-1» (отрицательные примеры).
Один из самых простых линейных классификаторов получается на основе регрессии вот таким образом:

$large a(vec{x}) = sign(vec{w}^Tx),$

где

Логистическая регрессия как линейный классификатор

Логистическая регрессия является частным случаем линейного классификатора, но она обладает хорошим «умением» – прогнозировать вероятность $p_+$ отнесения примера $vec{x_i}$ к классу «+»:

$large p_+ = Pleft(y_i = 1 mid vec{x_i}, vec{w}right) $

Прогнозирование не просто ответа («+1» или «-1»), а именно вероятности отнесения к классу «+1» во многих задачах является очень важным бизнес-требованием. Например, в задаче кредитного скоринга, где традиционно применяется логистическая регрессия, часто прогнозируют вероятность невозврата кредита ($p_+$). Клиентов, обратившихся за кредитом, сортируют по этой предсказанной вероятности (по убыванию), и получается скоркарта — по сути, рейтинг клиентов от плохих к хорошим. Ниже приведен игрушечный пример такой скоркарты.

Банк выбирает для себя порог $p_*$ предсказанной вероятности невозврата кредита (на картинке – $0.15$) и начиная с этого значения уже не выдает кредит. Более того, можно умножить предсказанную вероятность на выданную сумму и получить матожидание потерь с клиента, что тоже будет хорошей бизнес-метрикой (Далее в комментариях специалисты по скорингу могут поправить, но главная суть примерно такая).

Итак, мы хотим прогнозировать вероятность $p_+ in [0,1]$, а пока умеем строить линейный прогноз с помощью МНК: $b(vec{x}) = vec{w}^T vec{x} in mathbb{R}$. Каким образом преобразовать полученное значение в вероятность, пределы которой – [0, 1]? Очевидно, для этого нужна некоторая функция $f: mathbb{R} rightarrow [0,1].$ В модели логистической регрессии для этого берется конкретная функция: $sigma(z) = frac{1}{1 + exp^{-z}}$. И сейчас разберемся, каковы для этого предпосылки.

Обозначим $P(X)$ вероятностью происходящего события $X$. Тогда отношение вероятностей $OR(X)$ определяется из $frac{P(X)}{1-P(X)}$, а это — отношение вероятностей того, произойдет ли событие или не произойдет. Очевидно, что вероятность и отношение шансов содержат одинаковую информацию. Но в то время как $P(X)$ находится в пределах от 0 до 1, $OR(X)$ находится в пределах от 0 до $infty$.

Если вычислить логарифм $OR(X)$ (то есть называется логарифм шансов, или логарифм отношения вероятностей), то легко заметить, что $log{OR(X)} in mathbb{R}$. Его-то мы и будем прогнозировать с помощью МНК.

Посмотрим, как логистическая регрессия будет делать прогноз $p_+ = Pleft(y_i = 1 mid vec{x_i}, vec{w}right)$ (пока считаем, что веса $vec{w}$ мы как-то получили (т.е. обучили модель), далее разберемся, как именно).

  • Шаг 1. Вычислить значение $w_{0}+w_{1}x_1 + w_{2}x_2 + ... = vec{w}^Tvec{x}$. (уравнение $vec{w}^Tvec{x} = 0$ задает гиперплоскость, разделяющую примеры на 2 класса);

  • Шаг 2. Вычислить логарифм отношения шансов: $ log(OR_{+}) = vec{w}^Tvec{x}$.

  • Шаг 3. Имея прогноз шансов на отнесение к классу «+» – $OR_{+}$, вычислить $p_{+}$ с помощью простой зависимости:

$large p_{+} = frac{OR_{+}}{1 + OR_{+}} = frac{exp^{vec{w}^Tvec{x}}}{1 + exp^{vec{w}^Tvec{x}}} = frac{1}{1 + exp^{-vec{w}^Tvec{x}}} = sigma(vec{w}^Tvec{x})$

В правой части мы получили как раз сигмоид-функцию.

Итак, логистическая регрессия прогнозирует вероятность отнесения примера к классу «+» (при условии, что мы знаем его признаки и веса модели) как сигмоид-преобразование линейной комбинации вектора весов модели и вектора признаков примера:

$large p_+(x_i) = Pleft(y_i = 1 mid vec{x_i}, vec{w}right) = sigma(vec{w}^Tvec{x_i}). $

Следующий вопрос: как модель обучается? Тут мы опять обращаемся к принципу максимального правдоподобия.

Принцип максимального правдоподобия и логистическая регрессия

Теперь посмотрим, как из принципа максимального правдоподобия получается оптимизационная задача, которую решает логистическая регрессия, а именно, – минимизация логистической функции потерь.
Только что мы увидели, что логистическая регрессия моделирует вероятность отнесения примера к классу «+» как

$large p_+(vec{x_i}) = Pleft(y_i = 1 mid vec{x_i}, vec{w}right) = sigma(vec{w}^Tvec{x_i})$

Тогда для класса «-» аналогичная вероятность:

$large p_-(vec{x_i}) = Pleft(y_i = -1 mid vec{x_i}, vec{w}right) = 1 - sigma(vec{w}^Tvec{x_i}) = sigma(-vec{w}^Tvec{x_i}) $

Оба этих выражения можно ловко объединить в одно (следите за моими руками – не обманывают ли вас):

$large Pleft(y = y_i mid vec{x_i}, vec{w}right) = sigma(y_ivec{w}^Tvec{x_i})$

Выражение $M(vec{x_i}) = y_ivec{w}^Tvec{x_i}$ называется отступом (margin) классификации на объекте $vec{x_i}$ (не путать с зазором (тоже margin), про который чаще всего говорят в контексте SVM). Если он неотрицателен, модель не ошибается на объекте $vec{x_i}$, если же отрицателен – значит, класс для $vec{x_i}$ спрогнозирован неправильно.
Заметим, что отступ определен для объектов именно обучающей выборки, для которых известны реальные метки целевого класса $y_i$.

Чтобы понять, почему это мы сделали такие выводы, обратимся к геометрической интерпретации линейного классификатора. Подробно про это можно почитать в материалах Евгения Соколова.

Рекомендую решить почти классическую задачу из начального курса линейной алгебры: найти расстояние от точки с радиус-вектором $vec{x_A}$ до плоскости, которая задается уравнением $vec{w}^Tvec{x} = 0.$

Ответ

$large rho(vec{x_A}, vec{w}^Tvec{x} = 0) = frac{vec{w}^Tvec{x_A}}{||vec{w}||}$

Когда получим (или посмотрим) ответ, то поймем, что чем больше по модулю выражение $vec{w}^Tvec{x_i}$, тем дальше точка $vec{x_i}$ находится от плоскости $vec{w}^Tvec{x} = 0.$

Значит, выражение $M(vec{x_i}) = y_ivec{w}^Tvec{x_i}$ – это своего рода «уверенность» модели в классификации объекта $vec{x_i}$:

  • если отступ большой (по модулю) и положительный, это значит, что метка класса поставлена правильно, а объект находится далеко от разделяющей гиперплоскости (такой объект классифицируется уверенно). На рисунке – $x_3$.
  • если отступ большой (по модулю) и отрицательный, значит метка класса поставлена неправильно, а объект находится далеко от разделяющей гиперплоскости (скорее всего такой объект – аномалия, например, его метка в обучающей выборке поставлена неправильно). На рисунке – $x_1$.
  • если отступ малый (по модулю), то объект находится близко к разделяющей гиперплоскости, а знак отступа определяет, правильно ли объект классифицирован. На рисунке – $x_2$ и $x_4$.

Теперь распишем правдоподобие выборки, а именно, вероятность наблюдать данный вектор $vec{y}$ у выборки $X$. Делаем сильное предположение: объекты приходят независимо, из одного распределения (i.i.d.). Тогда

$large Pleft(vec{y} mid X, vec{w}right) = prod_{i=1}^{ell} Pleft(y = y_i mid vec{x_i}, vec{w}right),$

где $ell$ – длина выборки $X$ (число строк).

Как водится, возьмем логарифм данного выражения (сумму оптимизировать намного проще, чем произведение):

$large begin{array}{rcl} log Pleft(vec{y} mid X, vec{w}right) &=& log prod_{i=1}^{ell} Pleft(y = y_i mid vec{x_i}, vec{w}right) \ &=& log prod_{i=1}^{ell} sigma(y_ivec{w}^Tvec{x_i}) \ &=& sum_{i=1}^{ell} log sigma(y_ivec{w}^Tvec{x_i}) \ &=& sum_{i=1}^{ell} log frac{1}{1 + exp^{-y_ivec{w}^Tvec{x_i}}} \ &=& - sum_{i=1}^{ell} log (1 + exp^{-y_ivec{w}^Tvec{x_i}}) end{array}$

То есть в даном случае принцип максимизации правдоподобия приводит к минимизации выражения

$large mathcal{L_{log}} (X, vec{y}, vec{w}) = sum_{i=1}^{ell} log (1 + exp^{-y_ivec{w}^Tvec{x_i}}).$

Это логистическая функция потерь, просуммированная по всем объектам обучающей выборки.

Посмотрим на новую фунцию как на функцию от отступа: $L(M) = log (1 + exp^{-M})$. Нарисуем ее график, а также график 1/0 функциий потерь (zero-one loss), которая просто штрафует модель на 1 за ошибку на каждом объекте (отступ отрицательный): $L_{1/0}(M) = [M < 0]$.

Картинка отражает общую идею, что в задаче классификации, не умея напрямую минимизировать число ошибок (по крайней мере, градиентными методами это не сделать – производная 1/0 функциий потерь в нуле обращается в бесконечность), мы минимизируем некоторую ее верхнюю оценку. В данном случае это логистическая функция потерь (где логарифм двоичный, но это не принципиально), и справедливо

$large begin{array}{rcl} mathcal{L_{1/0}} (X, vec{y}, vec{w}) &=& sum_{i=1}^{ell} [M(vec{x_i}) < 0] \ &leq& sum_{i=1}^{ell} log (1 + exp^{-y_ivec{w}^Tvec{x_i}}) \ &=& mathcal{L_{log}} (X, vec{y}, vec{w}) end{array}$

где $mathcal{L_{1/0}} (X, vec{y}, vec{w})$ – попросту число ошибок логистической регрессии с весами $vec{w}$ на выборке $(X, vec{y})$.

То есть уменьшая верхнюю оценку $mathcal{L_{log}}$ на число ошибок классификации, мы таким образом надеемся уменьшить и само число ошибок.

$L_2$-регуляризация логистических потерь

L2-регуляризация логистической регрессии устроена почти так же, как и в случае с гребневой (Ridge регрессией). Вместо функционала $mathcal{L_{log}} (X, vec{y}, vec{w})$ минимизируется следующий:

$large J(X, vec{y}, vec{w}) = mathcal{L_{log}} (X, vec{y}, vec{w}) + lambda |vec{w}|^2$

В случае логистической регрессии принято введение обратного коэффициента регуляризации $C = frac{1}{lambda}$. И тогда решением задачи будет

$large hat{w} = arg min_{vec{w}} J(X, vec{y}, vec{w}) = arg min_{vec{w}} (Csum_{i=1}^{ell} log (1 + exp^{-y_ivec{w}^Tvec{x_i}})+ |vec{w}|^2)$

Далее рассмотрим пример, позволяющий интуитивно понять один из смыслов регуляризации.

3. Наглядный пример регуляризации логистической регрессии

В 1 статье уже приводился пример того, как полиномиальные признаки позволяют линейным моделям строить нелинейные разделяющие поверхности. Покажем это в картинках.

Посмотрим, как регуляризация влияет на качество классификации на наборе данных по тестированию микрочипов из курса Andrew Ng по машинному обучению.
Будем использовать логистическую регрессию с полиномиальными признаками и варьировать параметр регуляризации C.
Сначала посмотрим, как регуляризация влияет на разделяющую границу классификатора, интуитивно распознаем переобучение и недообучение.
Потом численно установим близкий к оптимальному параметр регуляризации с помощью кросс-валидации (cross-validation) и перебора по сетке (GridSearch).

Подключение библиотек

from __future__ import division, print_function
# отключим всякие предупреждения Anaconda
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
from matplotlib import pyplot as plt
import seaborn as sns

import numpy as np
import pandas as pd
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LogisticRegression, LogisticRegressionCV
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.model_selection import GridSearchCV

Загружаем данные с помощью метода read_csv библиотеки pandas. В этом наборе данных для 118 микрочипов (объекты) указаны результаты двух тестов по контролю качества (два числовых признака) и сказано, пустили ли микрочип в производство. Признаки уже центрированы, то есть из всех значений вычтены средние по столбцам. Таким образом, «среднему» микрочипу соответствуют нулевые значения результатов тестов.

Загрузка данных

data = pd.read_csv('../../data/microchip_tests.txt',
header=None, names = ('test1','test2','released'))
# информация о наборе данных
data.info()

<class ‘pandas.core.frame.DataFrame’>
RangeIndex: 118 entries, 0 to 117
Data columns (total 3 columns):
test1 118 non-null float64
test2 118 non-null float64
released 118 non-null int64
dtypes: float64(2), int64(1)
memory usage: 2.8 KB

Посмотрим на первые и последние 5 строк.

Сохраним обучающую выборку и метки целевого класса в отдельных массивах NumPy. Отобразим данные. Красный цвет соответствует бракованным чипам, зеленый – нормальным.

Код

X = data.ix[:,:2].values
y = data.ix[:,2].values

plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов')
plt.legend();

Определяем функцию для отображения разделяющей кривой классификатора

Код

def plot_boundary(clf, X, y, grid_step=.01, poly_featurizer=None):
x_min, x_max = X[:, 0].min() - .1, X[:, 0].max() + .1
y_min, y_max = X[:, 1].min() - .1, X[:, 1].max() + .1
xx, yy = np.meshgrid(np.arange(x_min, x_max, grid_step),
np.arange(y_min, y_max, grid_step))

# каждой точке в сетке [x_min, m_max]x[y_min, y_max]
# ставим в соответствие свой цвет
Z = clf.predict(poly_featurizer.transform(np.c_[xx.ravel(), yy.ravel()]))
Z = Z.reshape(xx.shape)
plt.contour(xx, yy, Z, cmap=plt.cm.Paired)

Полиномиальными признаками до степени $d$ для двух переменных $x_1$ и $x_2$ мы называем следующие:

$large {x_1^d, x_1^{d-1}x_2, ldots x_2^d} = {x_1^ix_2^j}_{i+j leq d, i,j in mathbb{N}}$

Например, для $d=3$ это будут следующие признаки:

$large 1, x_1, x_2, x_1^2, x_1x_2, x_2^2, x_1^3, x_1^2x_2, x_1x_2^2, x_2^3$

Нарисовав треугольник Пифагора, Вы сообразите, сколько таких признаков будет для $d=4,5...$ и вообще для любого $d$.
Попросту говоря, таких признаков экспоненциально много, и строить, скажем, для 100 признаков полиномиальные степени 10 может оказаться затратно (а более того, и не нужно).

Создадим объект sklearn, который добавит в матрицу $X$ полиномиальные признаки вплоть до степени 7 и обучим логистическую регрессию с параметром регуляризации $C = 10^{-2}$. Изобразим разделяющую границу.
Также проверим долю правильных ответов классификатора на обучающей выборке. Видим, что регуляризация оказалась слишком сильной, и модель «недообучилась». Доля правильных ответов классификатора на обучающей выборке оказалась равной 0.627.

Код

poly = PolynomialFeatures(degree=7)
X_poly = poly.fit_transform(X)

C = 1e-2
logit = LogisticRegression(C=C, n_jobs=-1, random_state=17)
logit.fit(X_poly, y)

plot_boundary(logit, X, y, grid_step=.01, poly_featurizer=poly)

plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов. Логит с C=0.01')
plt.legend();

print("Доля правильных ответов классификатора на обучающей выборке:", 
round(logit.score(X_poly, y), 3))

Увеличим $C$ до 1. Тем самым мы ослабляем регуляризацию, теперь в решении значения весов логистической регрессии могут оказаться больше (по модулю), чем в прошлом случае. Теперь доля правильных ответов классификатора на обучающей выборке – 0.831.

Код

C = 1
logit = LogisticRegression(C=C, n_jobs=-1, random_state=17)
logit.fit(X_poly, y)

plot_boundary(logit, X, y, grid_step=.005, poly_featurizer=poly)

plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов. Логит с C=1')
plt.legend();

print("Доля правильных ответов классификатора на обучающей выборке:", 
round(logit.score(X_poly, y), 3))

Еще увеличим $C$ – до 10 тысяч. Теперь регуляризации явно недостаточно, и мы наблюдаем переобучение. Можно заметить, что в прошлом случае (при $C$=1 и «гладкой» границе) доля правильных ответов модели на обучающей выборке не намного ниже, чем в 3 случае, зато на новой выборке, можно себе представить, 2 модель сработает намного лучше.
Доля правильных ответов классификатора на обучающей выборке – 0.873.

Код

C = 1e4
logit = LogisticRegression(C=C, n_jobs=-1, random_state=17)
logit.fit(X_poly, y)

plot_boundary(logit, X, y, grid_step=.005, poly_featurizer=poly)

plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов. Логит с C=10k')
plt.legend();

print("Доля правильных ответов классификатора на обучающей выборке:", 
round(logit.score(X_poly, y), 3))

Чтоб обсудить результаты, перепишем формулу для функционала, который оптимизируется в логистической регрессии, в таком виде:

$large J(X,y,w) = mathcal{L} + frac{1}{C}||w||^2,$

где

Промежуточные выводы:

  • чем больше параметр $C$, тем более сложные зависимости в данных может восстанавливать модель (интуитивно $C$ соответствует «сложности» модели (model capacity))
  • если регуляризация слишком сильная (малые значения $C$), то решением задачи минимизации логистической функции потерь может оказаться то, когда многие веса занулились или стали слишком малыми. Еще говорят, что модель недостаточно «штрафуется» за ошибки (то есть в функционале $J$ «перевешивает» сумма квадратов весов, а ошибка $mathcal{L}$ может быть относительно большой). В таком случае модель окажется недообученной (1 случай)
  • наоборот, если регуляризация слишком слабая (большие значения $C$), то решением задачи оптимизации может стать вектор $w$ с большими по модулю компонентами. В таком случае больший вклад в оптимизируемый функционал $J$ имеет $mathcal{L}$ и, вольно выражаясь, модель слишком «боится» ошибиться на объектах обучающей выборки, поэтому окажется переобученной (3 случай)
  • то, какое значение $C$ выбрать, сама логистическая регрессия «не поймет» (или еще говорят «не выучит»), то есть это не может быть определено решением оптимизационной задачи, которой является логистическая регрессия (в отличие от весов $w$). Так же точно, дерево решений не может «само понять», какое ограничение на глубину выбрать (за один процесс обучения). Поэтому $C$ – это гиперпараметр модели, который настраивается на кросс-валидации, как и max_depth для дерева.

Настройка параметра регуляризации

Теперь найдем оптимальное (в данном примере) значение параметра регуляризации $C$. Сделать это можно с помощью LogisticRegressionCV – перебора параметров по сетке с последующей кросс-валидацией. Этот класс создан специально для логистической регрессии (для нее известны эффективные алгоритмы перебора параметров), для произвольной модели мы бы использовали GridSearchCV, RandomizedSearchCV или, например, специальные алгоритмы оптимизации гиперпараметров, реализованные в hyperopt.

Код


skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=17)

c_values = np.logspace(-2, 3, 500)

logit_searcher = LogisticRegressionCV(Cs=c_values, cv=skf, verbose=1, n_jobs=-1)
logit_searcher.fit(X_poly, y)

Посмотрим, как качество модели (доля правильных ответов на обучающей и валидационной выборках) меняется при изменении гиперпараметра $C$.

Выделим участок с «лучшими» значениями C.

Как мы помним, такие кривые называются валидационными, раньше мы их строили вручную, но в sklearn для них их построения есть специальные методы, которые мы тоже сейчас будем использовать.

4. Где логистическая регрессия хороша и где не очень

Анализ отзывов IMDB к фильмам

Будем решать задачу бинарной классификации отзывов IMDB к фильмам. Имеется обучающая выборка с размеченными отзывами, по 12500 отзывов известно, что они хорошие, еще про 12500 – что они плохие. Здесь уже не так просто сразу приступить к машинному обучению, потому что готовой матрицы $X$ нет – ее надо приготовить. Будем использовать самый простой подход – мешок слов («Bag of words»). При таком подходе признаками отзыва будут индикаторы наличия в нем каждого слова из всего корпуса, где корпус – это множество всех отзывов. Идея иллюстрируется картинкой

Импорт библиотек и загрузка данных

from __future__ import division, print_function
# отключим всякие предупреждения Anaconda
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
import numpy as np
from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer, TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC

Загрузим данные отсюда (краткое описание — тут). В обучающей и тестовой выборках по 12500 тысяч хороших и плохих отзывов к фильмам.

reviews_train = load_files("YOUR PATH")
text_train, y_train = reviews_train.data, reviews_train.target

print("Number of documents in training data: %d" % len(text_train))
print(np.bincount(y_train))

# поменяйте путь к файлу
reviews_test = load_files("YOUR PATH")
text_test, y_test = reviews_test.data, reviews_test.target
print("Number of documents in test data: %d" % len(text_test))
print(np.bincount(y_test))

Пример плохого отзыва:

‘Words can’t describe how bad this movie is. I can’t explain it by writing only. You have too see it for yourself to get at grip of how horrible a movie really can be. Not that I recommend you to do that. There are so many clichxc3xa9s, mistakes (and all other negative things you can imagine) here that will just make you cry. To start with the technical first, there are a LOT of mistakes regarding the airplane. I won’t list them here, but just mention the coloring of the plane. They didn’t even manage to show an airliner in the colors of a fictional airline, but instead used a 747 painted in the original Boeing livery. Very bad. The plot is stupid and has been done many times before, only much, much better. There are so many ridiculous moments here that i lost count of it really early. Also, I was on the bad guys’ side all the time in the movie, because the good guys were so stupid. «Executive Decision» should without a doubt be you’re choice over this one, even the «Turbulence»-movies are better. In fact, every other movie in the world is better than this one.’

Пример хорошего отзыва:

‘Everyone plays their part pretty well in this «little nice movie». Belushi gets the chance to live part of his life differently, but ends up realizing that what he had was going to be just as good or maybe even better. The movie shows us that we ought to take advantage of the opportunities we have, not the ones we do not or cannot have. If U can get this movie on video for around $10, itxc2xb4d be an investment!’

Простой подсчет слов

Составим словарь всех слов с помощью CountVectorizer. Всего в выборке 74849 уникальных слов. Если посмотреть на примеры полученных «слов» (лучше их называть токенами), то можно увидеть, что многие важные этапы обработки текста мы тут пропустили (автоматическая обработка текстов – это могло бы быть темой отдельной серии статей).

Код

cv = CountVectorizer()
cv.fit(text_train)

print(len(cv.vocabulary_)) #74849

print(cv.get_feature_names()[:50])
print(cv.get_feature_names()[50000:50050])

[’00’, ‘000’, ‘0000000000001’, ‘00001’, ‘00015’, ‘000s’, ‘001’, ‘003830’, ‘006’, ‘007’, ‘0079’, ‘0080’, ‘0083’, ‘0093638’, ’00am’, ’00pm’, ’00s’, ’01’, ’01pm’, ’02’, ‘020410’, ‘029’, ’03’, ’04’, ‘041’, ’05’, ‘050’, ’06’, ’06th’, ’07’, ’08’, ‘087’, ‘089’, ’08th’, ’09’, ‘0f’, ‘0ne’, ‘0r’, ‘0s’, ’10’, ‘100’, ‘1000’, ‘1000000’, ‘10000000000000’, ‘1000lb’, ‘1000s’, ‘1001’, ‘100b’, ‘100k’, ‘100m’]
[‘pincher’, ‘pinchers’, ‘pinches’, ‘pinching’, ‘pinchot’, ‘pinciotti’, ‘pine’, ‘pineal’, ‘pineapple’, ‘pineapples’, ‘pines’, ‘pinet’, ‘pinetrees’, ‘pineyro’, ‘pinfall’, ‘pinfold’, ‘ping’, ‘pingo’, ‘pinhead’, ‘pinheads’, ‘pinho’, ‘pining’, ‘pinjar’, ‘pink’, ‘pinkerton’, ‘pinkett’, ‘pinkie’, ‘pinkins’, ‘pinkish’, ‘pinko’, ‘pinks’, ‘pinku’, ‘pinkus’, ‘pinky’, ‘pinnacle’, ‘pinnacles’, ‘pinned’, ‘pinning’, ‘pinnings’, ‘pinnochio’, ‘pinnocioesque’, ‘pino’, ‘pinocchio’, ‘pinochet’, ‘pinochets’, ‘pinoy’, ‘pinpoint’, ‘pinpoints’, ‘pins’, ‘pinsent’]

Закодируем предложения из текстов обучающей выборки индексами входящих слов. Используем разреженный формат. Преобразуем так же тестовую выборку.

X_train = cv.transform(text_train)
X_test = cv.transform(text_test)

Обучим логистическую регрессию и посмотрим на доли правильных ответов на обучающей и тестовой выборках. Получается, на тестовой выборке мы правильно угадываем тональность примерно 86.7% отзывов.

Код

%%time
logit = LogisticRegression(n_jobs=-1, random_state=7)
logit.fit(X_train, y_train)
print(round(logit.score(X_train, y_train), 3), round(logit.score(X_test, y_test), 3))

Коэффициенты модели можно красиво отобразить.

Код визуализации коэффициентов модели

def visualize_coefficients(classifier, feature_names, n_top_features=25):
# get coefficients with large absolute values 
coef = classifier.coef_.ravel()
positive_coefficients = np.argsort(coef)[-n_top_features:]
negative_coefficients = np.argsort(coef)[:n_top_features]
interesting_coefficients = np.hstack([negative_coefficients, positive_coefficients])
# plot them
plt.figure(figsize=(15, 5))
colors = ["red" if c < 0 else "blue" for c in coef[interesting_coefficients]]
plt.bar(np.arange(2 * n_top_features), coef[interesting_coefficients], color=colors)
feature_names = np.array(feature_names)
plt.xticks(np.arange(1, 1 + 2 * n_top_features), feature_names[interesting_coefficients], rotation=60, ha="right");

def plot_grid_scores(grid, param_name):
plt.plot(grid.param_grid[param_name], grid.cv_results_['mean_train_score'],
color='green', label='train')
plt.plot(grid.param_grid[param_name], grid.cv_results_['mean_test_score'],
color='red', label='test')
plt.legend();

visualize_coefficients(logit, cv.get_feature_names())

Подберем коэффициент регуляризации для логистической регрессии. Используем sklearn.pipeline, поскольку CountVectorizer правильно применять только на тех данных, на которых в текущий момент обучается модель (чтоб не «подсматривать» в тестовую выборку и не считать по ней частоты вхождения слов). В данном случае pipeline задает последовательность действий: применить CountVectorizer, затем обучить логистическую регрессию. Так мы поднимаем долю правильных ответов до 88.5% на кросс-валидации и 87.9% – на отложенной выборке.

Код

from sklearn.pipeline import make_pipeline

text_pipe_logit = make_pipeline(CountVectorizer(), 
LogisticRegression(n_jobs=-1, random_state=7))

text_pipe_logit.fit(text_train, y_train)
print(text_pipe_logit.score(text_test, y_test))

from sklearn.model_selection import GridSearchCV

param_grid_logit = {'logisticregression__C': np.logspace(-5, 0, 6)}
grid_logit = GridSearchCV(text_pipe_logit, param_grid_logit, cv=3, n_jobs=-1)

grid_logit.fit(text_train, y_train)
grid_logit.best_params_, grid_logit.best_score_
plot_grid_scores(grid_logit, 'logisticregression__C')
grid_logit.score(text_test, y_test)

Теперь то же самое, но со случайным лесом. Видим, что с логистической регрессией мы достигаем большей доли правильных ответов меньшими усилиями. Лес работает дольше, на отложенной выборке 85.5% правильных ответов.

Код для обучения случайного леса

from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(n_estimators=200, n_jobs=-1, random_state=17)
forest.fit(X_train, y_train)
print(round(forest.score(X_test, y_test), 3))

XOR-проблема

Теперь рассмотрим пример, где линейные модели справляются хуже.

Линейные методы классификации строят все же очень простую разделяющую поверхность – гиперплоскость. Самый известный игрушечный пример, в котором классы нельзя без ошибок поделить гиперплоскостью (то есть прямой, если это 2D), получил имя «the XOR problem».

XOR – это «исключающее ИЛИ», булева функция со следующей таблицей истинности:

XOR дал имя простой задаче бинарной классификации, в которой классы представлены вытянутыми по диагоналям и пересекающимися облаками точек.

Код, рисующий следующие 3 картинки

# порождаем данные
rng = np.random.RandomState(0)
X = rng.randn(200, 2)
y = np.logical_xor(X[:, 0] > 0, X[:, 1] > 0)

plt.scatter(X[:, 0], X[:, 1], s=30, c=y, cmap=plt.cm.Paired);

def plot_boundary(clf, X, y, plot_title):
xx, yy = np.meshgrid(np.linspace(-3, 3, 50),
np.linspace(-3, 3, 50))
clf.fit(X, y)
# plot the decision function for each datapoint on the grid
Z = clf.predict_proba(np.vstack((xx.ravel(), yy.ravel())).T)[:, 1]
Z = Z.reshape(xx.shape)

image = plt.imshow(Z, interpolation='nearest',
extent=(xx.min(), xx.max(), yy.min(), yy.max()),
aspect='auto', origin='lower', cmap=plt.cm.PuOr_r)
contours = plt.contour(xx, yy, Z, levels=[0], linewidths=2,
linetypes='--')
plt.scatter(X[:, 0], X[:, 1], s=30, c=y, cmap=plt.cm.Paired)
plt.xticks(())
plt.yticks(())
plt.xlabel(r'$<!-- math>$inline$x_1$inline$</math -->$')
plt.ylabel(r'$<!-- math>$inline$x_2$inline$</math -->$')
plt.axis([-3, 3, -3, 3])
plt.colorbar(image)
plt.title(plot_title, fontsize=12);

plot_boundary(LogisticRegression(), X, y,
"Logistic Regression, XOR problem")

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline

logit_pipe = Pipeline([('poly', PolynomialFeatures(degree=2)), 
('logit', LogisticRegression())])

plot_boundary(logit_pipe, X, y,
"Logistic Regression + quadratic features. XOR problem")

Очевидно, нельзя провести прямую так, чтобы без ошибок отделить один класс от другого. Поэтому логистическая регрессия плохо справляется с такой задачей.

А вот если на вход подать полиномиальные признаки, в данном случае до 2 степени, то проблема решается.

Здесь логистическая регрессия все равно строила гиперплоскость, но в 6-мерном пространстве признаков $1, x_1, x_2, x_1^2, x_1x_2$ и $x_2^2$. В проекции на исходное пространство признаков $x_1, x_2$ граница получилась нелинейной.

На практике полиномиальные признаки действительно помогают, но строить их явно – вычислительно неэффективно. Гораздо быстрее работает SVM с ядровым трюком. При таком подходе в пространстве высокой размерности считается только расстояние между объектами (задаваемое функцией-ядром), а явно плодить комбинаторно большое число признаков не приходится. Про это подробно можно почитать в курсе Евгения Соколова (математика уже серьезная).

5. Кривые валидации и обучения

Мы уже получили представление о проверке модели, кросс-валидации и регуляризации.
Теперь рассмотрим главный вопрос:

Если качество модели нас не устраивает, что делать?

  • Сделать модель сложнее или упростить?
  • Добавить больше признаков?
  • Или нам просто нужно больше данных для обучения?

Ответы на данные вопросы не всегда лежат на поверхности. В частности, иногда использование более сложной модели приведет к ухудшению показателей. Либо добавление наблюдений не приведет к ощутимым изменениям. Способность принять правильное решение и выбрать правильный способ улучшения модели, собственно говоря, и отличает хорошего специалиста от плохого.

Будем работать со знакомыми данными по оттоку клиентов телеком-оператора.

Импорт библиотек и чтение данных

from __future__ import division, print_function
# отключим всякие предупреждения Anaconda
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
from matplotlib import pyplot as plt
import seaborn as sns

import numpy as np
import pandas as pd
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression, LogisticRegressionCV, SGDClassifier
from sklearn.model_selection import validation_curve

data = pd.read_csv('../../data/telecom_churn.csv').drop('State', axis=1)
data['International plan'] = data['International plan'].map({'Yes': 1, 'No': 0})
data['Voice mail plan'] = data['Voice mail plan'].map({'Yes': 1, 'No': 0})

y = data['Churn'].astype('int').values
X = data.drop('Churn', axis=1).values

Логистическую регрессию будем обучать стохастическим градиентным спуском. Пока объясним это тем, что так быстрее, но далее в программе у нас отдельная статья про это дело. Построим валидационные кривые, показывающие, как качество (ROC AUC) на обучающей и проверочной выборке меняется с изменением параметра регуляризации.

Код

alphas = np.logspace(-2, 0, 20)
sgd_logit = SGDClassifier(loss='log', n_jobs=-1, random_state=17)
logit_pipe = Pipeline([('scaler', StandardScaler()), ('poly', PolynomialFeatures(degree=2)), 
('sgd_logit', sgd_logit)])
val_train, val_test = validation_curve(logit_pipe, X, y,
'sgd_logit__alpha', alphas, cv=5,
scoring='roc_auc')

def plot_with_err(x, data, **kwargs):
mu, std = data.mean(1), data.std(1)
lines = plt.plot(x, mu, '-', **kwargs)
plt.fill_between(x, mu - std, mu + std, edgecolor='none',
facecolor=lines[0].get_color(), alpha=0.2)

plot_with_err(alphas, val_train, label='training scores')
plot_with_err(alphas, val_test, label='validation scores')
plt.xlabel(r'$alpha$'); plt.ylabel('ROC AUC')
plt.legend();

Тенденция видна сразу, и она очень часто встречается.

  • Для простых моделей тренировочная и валидационная ошибка находятся где-то рядом, и они велики. Это говорит о том, что модель недообучилась: то есть она не имеет достаточное кол-во параметров.

  • Для сильно усложненных моделей тренировочная и валидационная ошибки значительно отличаются. Это можно объяснить переобучением: когда параметров слишком много либо не хватает регуляризации, алгоритм может «отвлекаться» на шум в данных и упускать основной тренд.

Сколько нужно данных?

Известно, что чем больше данных использует модель, тем лучше. Но как нам понять в конкретной ситуации, помогут ли новые данные? Скажем, целесообразно ли нам потратить N$ на труд асессоров, чтобы увеличить выборку вдвое?

Поскольку новых данных пока может и не быть, разумно поварьировать размер имеющейся обучающей выборки и посмотреть, как качество решения задачи зависит от объема данных, на котором мы обучали модель. Так получаются кривые обучения (learning curves).

Идея простая: мы отображаем ошибку как функцию от количества примеров, используемых для обучения. При этом параметры модели фиксируются заранее.

Давайте посмотрим, что мы получим для линейной модели. Коэффициент регуляризации выставим большим.

Код

from sklearn.model_selection import learning_curve

def plot_learning_curve(degree=2, alpha=0.01):
train_sizes = np.linspace(0.05, 1, 20)
logit_pipe = Pipeline([('scaler', StandardScaler()), ('poly', PolynomialFeatures(degree=degree)), 
('sgd_logit', SGDClassifier(n_jobs=-1, random_state=17, alpha=alpha))])
N_train, val_train, val_test = learning_curve(logit_pipe,
X, y, train_sizes=train_sizes, cv=5,
scoring='roc_auc')
plot_with_err(N_train, val_train, label='training scores')
plot_with_err(N_train, val_test, label='validation scores')
plt.xlabel('Training Set Size'); plt.ylabel('AUC')
plt.legend()

plot_learning_curve(degree=2, alpha=10)

Типичная ситуация: для небольшого объема данных ошибки на обучающей выборке и в процессе кросс-валидации довольно сильно отличаются, что указывает на переобучение. Для той же модели, но с большим объемом данных ошибки «сходятся», что указывается на недообучение.

Если добавить еще данные, ошибка на обучающей выборке не будет расти, но с другой стороны, ошибка на тестовых данных не будет уменьшаться.

Получается, ошибки «сошлись», и добавление новых данных не поможет. Собственно, это случай – самый интересный для бизнеса. Возможна ситуация, когда мы увеличиваем выборку в 10 раз. Но если не менять сложность модели, это может и не помочь. То есть стратегия «настроил один раз – дальше использую 10 раз» может и не работать.

Что будет, если изменить коэффициент регуляризации (уменьшить до 0.05)?

Видим хорошую тенденцию – кривые постепенно сходятся, и если дальше двигаться направо (добавлять в модель данные), можно еще повысить качество на валидации.

А если усложнить модель ещё больше ($alpha=10^{-4}$)?

Проявляется переобучение – AUC падает как на обучении, так и на валидации.

Строя подобные кривые, можно понять, в какую сторону двигаться, и как правильно настроить сложность модели на новых данных.

Выводы по кривым валидации и обучения

  • Ошибка на обучающей выборке сама по себе ничего не говорит о качестве модели
  • Кросс-валидационная ошибка показывает, насколько хорошо модель подстраивается под данные (имеющийся тренд в данных), сохраняя при этом способность обобщения на новые данные
  • Валидационная кривая представляет собой график, показывающий результат на тренировочной и валидационной выборке в зависимости от сложности модели:
  • если две кривые распологаются близко, и обе ошибки велики, — это признак недообучения
  • если две кривые далеко друг от друга, — это показатель переобучения
  • Кривая обучения — это график, показывающий результаты на валидации и тренировочной подвыборке в зависимости от количества наблюдений:
  • если кривые сошлись друг к другу, добавление новых данных не поможет – надо менять сложность модели
  • если кривые еще не сошлись, добавление новых данных может улучшить результат.

6. Плюсы и минусы линейных моделей в задачах машинного обучения

Плюсы:

Минусы:

  • Плохо работают в задачах, в которых зависимость ответов от признаков сложная, нелинейная
  • На практике предположения теоремы Маркова-Гаусса почти никогда не выполняются, поэтому чаще линейные методы работают хуже, чем, например, SVM и ансамбли (по качеству решения задачи классификации/регрессии)

7. Домашнее задание № 4

В качестве закрепления изученного материала предлагаем следующее задание: разобраться с тем, как работает TfidfVectorizer и DictVectorizer, обучить и настроить модель линейной регрессии Ridge на данных о публикациях на Хабрахабре и воспроизвести бенчмарк в соревновании. Проверить себя можно отправив ответы в веб-форме (там же найдете и решение).

Актуальные и обновляемые версии демо-заданий – на английском на сайте курса. Также по подписке на Patreon («Bonus Assignments» tier) доступны расширенные домашние задания по каждой теме (только на англ.)

8. Полезные ресурсы

  • Перевод материала этой статьи на английский – Jupyter notebooks в репозитории курса
  • Видеозаписи лекций по мотивам этой статьи: классификация, регрессия
  • Основательный обзор классики машинного обучения и, конечно же, линейных моделей сделан в книге «Deep Learning» (I. Goodfellow, Y. Bengio, A. Courville, 2016);
  • Реализация многих алгоритмов машинного обучения с нуля – репозиторий rushter. Рекомендуем изучить реализацию логистической регрессии;
  • Курс Евгения Соколова по машинному обучению (материалы на GitHub). Хорошая теория, нужна неплохая математическая подготовка;
  • Курс Дмитрия Ефимова на GitHub (англ.). Тоже очень качественные материалы.

Статья написана в соавторстве с mephistopheies (Павлом Нестеровым). Он же – автор домашнего задания. Авторы домашнего задания в первой сессии курса (февраль-май 2017)– aiho (Ольга Дайховская) и das19 (Юрий Исаков). Благодарю bauchgefuehl (Анастасию Манохину) за редактирование.

Макеты страниц

Рассмотренный в 1.2 линейный классификатор на два класса легко может быть осуществлен с помощью одного порогового логического элемента. Если образы различных классов линейно разделимы (могут быть разделены гиперплоскостью в пространстве признаков то при правильных значениях весовых коэффициентов в (1.5) можно получить вполне правильное распознавание. Практически, однако, нужные значения весов отсутствуют. В этих условиях предполагается, что классификатор построен так, что способен устанавливать лучшие значения весов по входным образам. Основная идея заключается в том, что, «осматривая» образ известных классов, классификатор может автоматически определять веса, необходимые для правильного распознавания.

Предполагается, что с увеличением числа «показанных» образов способность распознавания классификатора становится все лучше и лучше. Этот процесс называется тренировкой или обучением, а вводимые при этом образы называются обучающими образами. Несколько простых правил обучения кратко рассматриваются в данном параграфе.

Пусть обозначает дополненный вектор признаков, равный

где X — вектор признаков образа. Рассмотрим два множества обучающих образов и принадлежащих двум различным классам образов Соответственно этим двум обучающим множествам есть два множества дополненных векторов элементы получены путем дополнения векторов, принадлежащих множествам и , что два обучающих множества линейно разделимы, означает существование вектора (называемого вектором весов решения) такого, что

или

где

Процедуру обучения («исправление ошибок») для линейного классификатора можно сформулировать следующим образом. Для любого произведение должно быть положительным, т.е. Если классификатор дает ошибочный (т.е. или неопределенный результат (т. е. то надо взять новый вектор весов

где называется поправочным дополнением. С другой стороны, для Если выход прибора ошибочный (т. е. или неопределенный, то

принимаем

В начале обучения для принимаются любые удобные значения. Для выбора а можно предложить три правила:

(1) Правило фиксированного дополнения-, а является любым фиксированным положительным числом.

(2) Правило абсолютной поправки: а берется равным наименьшему целому числу, при котором значение переходит порог, равный нулю. Это означает, что

(3) Правило дробной поправки а выбирается так, что

или эквивалентно,

Сходимость этих трех правил исправления ошибок может быть доказана [1]. Под сходимостью понимается следующее: если два обучающих множества линейно разделимы, то последовательность весовых векторов, построенная по правилам обучения, сходится к вектору весов решения за конечное число шагов обучения или итераций.

documentclass[12pt,fleqn]{article} usepackage{vkCourseML} hypersetup{unicode=true} %usepackage[a4paper]{geometry} usepackage[hyphenbreaks]{breakurl} interfootnotelinepenalty=10000 begin{document} title{Лекция 5\Линейная классификация} author{Е.,А.,Соколов\ФКН ВШЭ} maketitle Ранее мы изучили общий подход к обучению линейных классификаторов, основанный на минимизации верхней оценки: [ frac{1}{ell} sum_{i = 1}^{ell} L(y_i, langle w, x_i rangle) to min_{w} ] При этом мы привели примеры нескольких верхних оценок~$tilde L(M)$, среди которых были begin{itemize} item $L(y, z) = log(1 + exp(-yz))$~— логистическая функция потерь; item $L(y, z) = (1 — yz)_+$~— кусочно-линейная функция потерь~(hinge loss). end{itemize} В этой лекции мы выясним, откуда взялись эти функции потерь, и изучим некоторые их важные свойства. section{Логистическая регрессия} subsection{Оценивание вероятностей} Метод обучения, которые получается при использовании логистической функции потерь, называется логистической регрессией. Основным его свойством является тот факт, что он корректно оценивает вероятность принадлежности объекта к каждому из классов. Пусть в каждой точке пространства объектов~$x in XX$ задана вероятность~$p(y = +1 cond x)$ того, что объект~$x$ будет принадлежать классу~$+1$. Это означает, что мы допускаем наличие в выборке нескольких объектов с одинаковым признаковым описанием, но с разными значениями целевой переменной; причём если устремить количество объекта~$x$ в выборке к бесконечности, то доля положительных объектов среди них будет стремиться к~$p(y = +1 cond x)$. Примером может служить задача предсказания кликов по рекламным баннерам. При посещении одного и того же сайта один и тот же пользователь может как кликнуть, так и не кликнуть по одному и тому же баннеру, из-за чего в выборке могут появиться одинаковые объекты с разными ответами. При этом важно, чтобы классификатор предсказывал именно вероятности классов~— если домножить вероятность первого класса на сумму, которую заплатит заказчик в случае клика, то мы получим матожидание прибыли при показе этого баннера. На основе таких матожиданий можно построить алгоритм, выбирающий баннеры для показа пользователю. Итак, рассмотрим точку~$x$ пространства объектов. Как мы договорились, в ней имеется распределение на ответах~$p(y = +1 cond x)$. Допустим, алгоритм~$b(x)$ возвращает числа из отрезка~$[0, 1]$. Наша задача~— выбрать для него такую процедуру обучения, что в точке~$x$ ему будет оптимально выдавать число~$p(y = +1 cond x)$. Если в выборке объект~$x$ встречается~$n$ раз с ответами~${y_1, dots, y_n}$, то получаем следующее требование: [ argmin_{b in RR} frac{1}{n} sum_{i = 1}^{n} L(y_i, b) approx p(y = +1 cond x). ] При стремлении~$n$ к бесконечности получим, что функционал стремится к матожиданию ошибки: [ argmin_{b in RR} EE left[ L(y, b) cond x right] = p(y = +1 cond x). ] На семинаре будет показано, что этим свойством обладает, например, квадратичная функция потерь~$L(y, z) = (y — z)^2$, если в ней для положительных объектов использовать истинную метку~$y = 1$, а для отрицательных брать~$y = 0$. Примером функции потерь, которая не позволяет оценивать вероятности, является модуль отклонения~$L(y, x) = |y — z|$. Можно показать, что с точки зрения данной функции оптимальным ответом всегда будет либо ноль, либо единица. Это требование можно воспринимать более просто. Пусть один и тот же объект встречается в выборке 1000 раз, из которых 100 раз он относится к классу $+1$, и 900 раз~— к классу $1$. Поскольку это один и тот же объект, классификатор должен выдавать один ответ для каждого из тысячи случаев. Можно оценить матожидание функции потерь в данной точке по 1000 примеров при прогнозе~$b$: [ EE biggl[ L(y, b) cond x biggr] approx frac{100}{1000} L(1, b) + frac{900}{1000} L(-1, b). ] Наше требование, по сути, означает, что оптимальный ответ с точки зрения этой оценки должен быть равен~$1/10$: [ argmin_{b in RR} left( frac{100}{1000} L(1, b) + frac{900}{1000} L(-1, b) right) = frac{1}{10}. ] subsection{Правдоподобие и логистические потери} Хотя квадратичная функция потерь и приводит к корректному оцениванию вероятностей, она не очень хорошо подходит для решения задачи классификации. Причиной этому в том числе являются и слишком низкие штрафы за ошибку~— так, если объект положительный, а модель выдаёт для него вероятность первого класса~$b(x) = 0$, то штраф за это равен всего лишь единице:~$(10)^2 = 1$. Попробуем сконструировать функцию потерь из других соображений. Если алгоритм~$b(x) in [0, 1]$ действительно выдает вероятности, то они должны согласовываться с выборкой. С точки зрения алгоритма вероятность того, что в выборке встретится объект~$x_i$ с классом~$y_i$, равна~$b(x_i)^{[y_i = +1]} (1 — b(x_i))^{[y_i = -1]}$. Исходя из этого, можно записать правдоподобие выборки (т.е. вероятность получить такую выборку с точки зрения алгоритма): [ Q(a, X) = prod_{i = 1}^{ell} b(x_i)^{[y_i = +1]} (1 — b(x_i))^{[y_i = -1]}. ] Данное правдоподобие можно использовать как функционал для обучения алгоритма~— с той лишь оговоркой, что удобнее оптимизировать его логарифм: [ sum_{i = 1}^{ell} left( [y_i = +1] log b(x_i) + [y_i = -1] log (1 — b(x_i)) right) to min ] Данная функция потерь называется логарифмической~(log-loss). Покажем, что она также позволяет корректно предсказывать вероятности. Запишем матожидание функции потерь в точке~$x$: begin{align*} EE biggl[ L(y, b) cond x biggr] &= EE biggl[ -[y = +1] log b — [y = -1] log(1 — b) cond x biggr] =\ &= -p(y = +1 cond x) log b (1 — p(y = +1 cond x)) log(1 — b). end{align*} Продифференцируем по~$b$: begin{align*} frac{partial}{partial b} EE biggl[ L(y, b) cond x biggr] &= frac{p(y = +1 cond x)}{b} + frac{1 — p(y = +1 cond x)}{1 — b} = 0. end{align*} Легко видеть, что оптимальный ответ алгоритма равен вероятности положительного класса: [ b_* = p(y = +1 cond x). ] subsection{Логистическая регрессия} Везде выше мы требовали, чтобы алгоритм~$b(x)$ возвращал числа из отрезка~$[0, 1]$. Этого легко достичь, если положить~$b(x) = sigma(langle w, x rangle)$, где в качестве~$sigma$ может выступать любая монотонно неубывающая функция с областью значений~$[0, 1]$. Мы будем использовать сигмоидную функцию: $sigma(z) = frac{1}{1 + exp(-z)}$. Таким образом, чем больше скалярное произведение~$langle w, x rangle$, тем больше будет предсказанная вероятность. Как при этом можно интерпретировать данное скалярное произведение? Чтобы ответить на этот вопрос, преобразуем уравнение [ p(y = 1 cond x) = frac{1}{1 + exp(-langle w, x rangle)}. ] Выражая из него скалярное произведение, получим [ langle w, x rangle = log frac{ p(y = +1 cond x) }{ p(y = -1 cond x) }. ] Получим, что скалярное произведение будет равно логарифму отношения вероятностей классов~(log-odds). Как уже упоминалось выше, при использовании квадратичной функции потерь алгоритм будет пытаться предсказывать вероятности, но данная функция потерь является далеко не самой лучшей, поскольку слабо штрафует за грубые ошибки. Логарифмическая функция потерь подходит гораздо лучше, поскольку не позволяет алгоритму сильно ошибаться в вероятностях. Подставим трансформированный ответ линейной модели в логарифмическую функцию потерь: begin{align*} sum_{i = 1}^{ell} &left( [y_i = +1] log frac{1}{1 + exp(-langle w, x_i rangle)} + [y_i = -1] log frac{exp(-langle w, x_i rangle)}{1 + exp(-langle w, x_i rangle)} right) =\ &= sum_{i = 1}^{ell} left( [y_i = +1] log frac{1}{1 + exp(-langle w, x_i rangle)} + [y_i = -1] log frac{1}{1 + exp(langle w, x_i rangle)} right) =\ &= sum_{i = 1}^{ell} log left( 1 + exp(-y_i langle w, x_i rangle) right). end{align*} Полученная функция в точности представляет собой логистические потери, упомянутые в начале. Линейная модель классификации, настроенная путём минимизации данного функционала, называется логистической регрессией. Как видно из приведенных рассуждений, она оптимизирует правдоподобие выборки и дает корректные оценки вероятности принадлежности к положительному классу. section{Метод опорных векторов} Рассмотрим теперь другой подход к построению функции потерь, основанный на максимизации зазора между классами. Будем рассматривать линейные классификаторы вида [ a(x) = sign (langle w, x rangle + b), qquad w in RR^d, b in RR. ] subsection{Разделимый случай} Будем считать, что существуют такие параметры~$w_*$ и~$b_*$, что соответствующий им классификатор~$a(x)$ не допускает ни одной ошибки на обучающей выборке. В этом случае говорят, что выборка~emph{линейно разделима}. Пусть задан некоторый классификатор~$a(x) = sign (langle w, x rangle + b)$. Заметим, что если одновременно умножить параметры~$w$ и~$b$ на одну и ту же положительную константу, то классификатор не изменится. Распорядимся этой свободой выбора и отнормируем параметры так, что begin{equation} label{eq:svmNormCond} min_{x in X} | langle w, x rangle + b| = 1. end{equation} Можно показать, что расстояние от произвольной точки~$x_0 in RR^d$ до гиперплоскости, определяемой данным классификатором, равно [ rho(x_0, a) = frac{ |langle w, x rangle + b| }{ |w| }. ] Тогда расстояние от гиперплоскости до ближайшего объекта обучающей выборки равно [ min_{x in X} frac{ |langle w, x rangle + b| }{ |w| } = frac{1}{|w|} min_{x in X} |langle w, x rangle + b| = frac{1}{|w|}. ] Данная величина также называется~emph{отступом~(margin)}. Таким образом, если классификатор без ошибок разделяет обучающую выборку, то ширина его разделяющей полосы равна~$frac{2}{|w|}$. Известно, что максимизация ширины разделяющей полосы приводит к повышению обобщающей способности классификатора~cite{mohri12foundations}. Вспомним также, что на повышение обобщающей способности направлена и регуляризация, которая штрафует большую норму весов~— а чем больше норма весов, тем меньше ширина разделяющей полосы. Итак, требуется построить классификатор, идеально разделяющий обучающую выборку, и при этом имеющий максимальный отступ. Запишем соответствующую оптимизационную задачу, которая и будет определять метод опорных векторов для линейно разделимой выборки~(hard margin support vector machine): begin{equation} label{eq:svmSep} left{ begin{aligned} & frac{1}{2} |w|^2 to min_{w, b} \ & y_i left( langle w, x_i rangle + b right) geq 1, quad i = 1, dots, ell. end{aligned} right. end{equation} Здесь мы воспользовались тем, что линейный классификатор дает правильный ответ на объекте~$x_i$ тогда и только тогда, когда~$y_i (langle w, x_i rangle + b) geq 0$. Более того, из условия нормировки~eqref{eq:svmNormCond} следует, что~$y_i (langle w, x_i rangle + b) geq 1$. В данной задаче функционал является строго выпуклым, а ограничения линейными, поэтому сама задача является выпуклой и имеет единственное решение. Более того, задача является квадратичной и может быть решена крайне эффективно. subsection{Неразделимый случай} Рассмотрим теперь общий случай, когда выборку невозможно идеально разделить гиперплоскостью. Это означает, что какие бы~$w$ и~$b$ мы не взяли, хотя бы одно из ограничений в задаче~eqref{eq:svmSep} будет нарушено: [ exists x_i in X: y_i left( langle w, x_i rangle + b right) < 1. ] Сделаем эти ограничения <<мягкими>>, введя штраф~$xi_i geq 0$ за их нарушение: [ y_i left( langle w, x_i rangle + b right) geq 1 — xi_i, quad i = 1, dots, ell. ] Отметим, что если отступ объекта лежит между нулем и единицей~($0 leq y_i left( langle w, x_i rangle + b right) < 1$), то объект верно классифицируется, но имеет ненулевой штраф~$xi > 0$. Таким образом, мы штрафуем объекты за попадание внутрь разделяющей полосы. Величина~$frac{1}{|w|}$ в данном случае называется~emph{мягким отступом~(soft margin)}. С одной стороны, мы хотим максимизировать отступ, с другой~— минимизировать штраф за неидеальное разделение выборки~$sum_{i = 1}^{ell} xi_i$. Эти две задачи противоречат друг другу: как правило, излишняя подгонка под выборку приводит к маленькому отступу, и наоборот~— максимизация отступа приводит к большой ошибке на обучении. В качестве компромисса будем минимизировать взвешенную сумму двух указанных величин. Приходим к оптимизационной задаче, соответствующей методу опорных векторов для линейно неразделимой выборки~(soft margin support vector machine) begin{equation} label{eq:svmUnsep} left{ begin{aligned} & frac{1}{2} |w|^2 + C sum_{i = 1}^{ell} xi_i to min_{w, b, xi} \ & y_i left( langle w, x_i rangle + b right) geq 1 — xi_i, quad i = 1, dots, ell, \ & xi_i geq 0, quad i = 1, dots, ell. end{aligned} right. end{equation} Чем больше здесь параметр~$C$, тем сильнее мы будем настраиваться на обучающую выборку. Данная задача также является выпуклой и имеет единственное решение. subsection{Сведение к безусловной задаче} В начале лекции мы планировали разобраться с двумя функциями потерь: логистической и кусочно-линейной. Функционал логистической регрессии действительно имеет вид верхней оценки на долю неправильных ответов, а вот задача метода опорных векторов~eqref{eq:svmUnsep} пока выглядит совершенно иначе. Попробуем свести её к задаче безусловной оптимизации. Перепишем условия задачи: [ left{ begin{aligned} &xi_i geq 1 — y_i (langle w, x_i rangle + b) \ &xi_i geq 0 end{aligned} right. ] Поскольку при этом в функционале требуется, чтобы штрафы~$xi_i$ были как можно меньше, то можно получить следующую явную формулу для них: [ xi_i = max(0, 1 — y_i (langle w, x_i rangle + b)). ] Данной выражение для~$xi_i$ уже учитывает в себе все ограничения задачи~eqref{eq:svmUnsep}. Значит, если подставить его в функционал, то получим безусловную задачу оптимизации: [ frac{1}{2} |w|^2 + C sum_{i = 1}^{ell} max(0, 1 — y_i (langle w, x_i rangle + b)) to min_{w, b} ] Эта задача является негладкой, поэтому решать её может быть достаточно тяжело. Тем не менее, она показывает, что метод опорных векторов, по сути, тоже строит верхнюю оценку вида~$L(y, z) = max(0, 1 — yz)$ на долю ошибок, и добавляет к ней стандартную квадратичную регуляризацию. begin{thebibliography}{1} bibitem{mohri12foundations} emph{Mohri, M., Rostamizadeh, A., Talwalkar, A.} Foundations of Machine Learning.~// MIT Press, 2012. end{thebibliography} end{document}
  • Inclab

  • Scilab для продвинутых

  • Настройка линейного классификатора Scilab

Рассмотрим задачу классификации данных на примере разделения садовых жуков.

Будем рассматривать гусениц и божьих коровок, разделяя их в зависимости от размера.

Определим шкалу, где по вертикали будет откладываться длина жука, а по горизонтали ширина.

Тогда на введённой шкале всех жуков можно условно разделить следующим образом:

Жуки в системе координат. Изображение из (1)

Жуки в системе координат. Изображение из (1)

Попробуем разделить наших жуков с помощью прямой. Уравнение прямой имеет вид:

( y = Ax, )

где A это коэффициент наклона.

Проведём пару разделительных линий:

Попытка разделить жуков 1. Изображение из (1)

Попытка разделить жуков 1. Изображение из (1)

Попытка разделить жуков 2. Изображение из (1)

Попытка разделить жуков 2. Изображение из (1)

Тут мы попали в гусениц. То, что выше линии гусеницы, то, что ниже линии — гусеницы и божьи коровки. Плохо разделили 🤨 Тут мы ни в кого не попали, однако, выше линии оказались и гусеницы, и божьи коровки, а снизу никого. Совсем не разделили жуков 🤔

Итак, нам надо подобрать коэффициент наклона прямой таким образом, чтобы снизу были божьи коровки, а сверху — гусеницы:

Идеальный классификатор. Изображение из (1)

Идеальный классификатор. Изображение из (1)

Тогда, выбирая некоторого жука на анализ, по его координатам (длине и ширине), мы поймём, где, относительно разделителя, он находится, а значит, сможем сказать, божья коровка это или гусеница.

Вот как-то, как на графике:

Определение типа жука по его положению. Изображение из (1)

Определение типа жука по его положению. Изображение из (1)

Тренировочные данные

Сейчас мы займемся тренировкой (обучением) нашего линейного классификатора и научим его правильно классифицировать жуков, относя их к гусеницам или божьим коровкам.

Первое, что нам понадобится — это эталонные данные, на основе которых мы будет тренировать классификатор.

Чтобы не усложнять себе жизнь, мы ограничимся двумя простыми примерами, приведенными ниже.

Пример Ширина Длина Жук
1 3.0 1.0 Божья коровка
2 1.0 3.0 Гусеница

Итак, для обучения классификатора у нас в арсенале имеются:

  • жук, имеющий ширину 3.0 и длину 1.0, который, как нам известно, является божьей коровкой;
  • жук, имеющий ширину 1.0 и длину 3.0, которым является гусеницей.

Изобразим их на нашей шкале:

Положение эталонных жуков на координатной сетке. Изображение из (1)

Положение эталонных жуков на координатной сетке. Изображение из (1)

И попробуем построить классификатор. То есть, провести прямую ( y=Ax ) с некоторым коэффициентом наклона ( A ).

Возьмём ( А=0.25). Тогда уравнение прямой будет иметь вид ( y=0.25x). Изобразим наш классификатор на графике с жуками и посмотрим, каких результатов мы достигли:

 Классификатор с А=0.25. Изображение из (1)

Классификатор с А=0.25. Изображение из (1)

Так себе классификатор, честно говоря.

С таким классификатором мы не можем делать выводы вида: «Если точка данных располагается над линией, то она соответствует гусенице».

А именно к этому мы и стремимся: по графику понять, что за жук перед нами. Если он выше прямой — гусеница, ниже — коровка.

Процесс настройки классификатора

Приступим к выработке алгоритма, который бы подбирал оптимальный коэффициент наклона прямой.

Шаг 1

Возьмём первого эталонного жука — божью коровку: у неё ширина 3 (это х), длина 1 (это у). Подставим ширину жука в наш классификатор:

( y = 0.25 cdot 3 = 0.75 )

Получили (у=0.75 ), а по эталону должно было получиться ( y_э = 1 ). Налицо отклонение от эталона.

Шаг 2

Считаем ошибку которая вычисляется, как разница между желаемым значением и фактическим результатом.

(e = y_э — y = 1 — 0.75 = 0.25 )

Давайте подумаем, каким должно быть подходящее желаемое значение ( y ).

Если положить его равным 1, как в эталоне, то линия пройдет через точку с координатами (х, у) = (3; 1), соответствующую божьей коровке. Само по себе это неплохо, но это не совсем то, что нам нужно.

Нам желательно, чтобы линия проходила над этой точкой. Почему? Да потому, что мы хотим, чтобы точки данных божьей коровки лежали под линией, а не нанизывались на неё.

Поэтому, мы немного приподнимем классификатор, т.е.

отступим от ( y_э = 1 ) на небольшое значение ( D=0.1)

Тогда ошибка будет вычисляться следующим образом:

(e = y_э — y = 1.1 — 0.75 = 0.35 )

На графике наши манипуляции с углом наклона прямой будут выглядеть так:

Немного корректируем угол наклона классификатора. Изображение из (1)

Немного корректируем угол наклона классификатора. Изображение из (1)

Шаг 3

Выясним как связаны (A) и (D).

Так как брать величину поправки с потолка нехорошо, формализуем поиск этого самого (D) — величины, на которую мы хотим изменить наклон классификатора.

Изначально классификатор имел уравнение

(y=Ax )

Приподняв его, мы произвели изменение угла наклона, получив прямую

(y=(A+D)x )

А теперь подставим эти данные в ошибку ( e ):

(e = y_э — y = (A + D)x — Aх = Aх + Dx — Ax = Dx. )

Итак, ошибка ( e ) связана с ( D ) очень простым соотношением. Используем информацию об ошибку для определения величины поправки ( D ):

( D = frac{e}{x} )

Теперь мы можем использовать ошибку ( e ) для вычисления величины, на которую следует изменить наклон классификатора. В нашем случае:

( D = frac{0.35}{3}=0.1167 )

Шаг 4

Корректируем наклон классификатора. Текущее значение (А=0.25) необходимо изменить на величину ( D = 0.1167 ), стало быть, улучшенное уравнение классификатора примет вид:

( y = (0.25+0.1167)x=0.3667x )

Итак, новый классификатор ( у=0,3667х ) получен на основе всего одного эталонного значения.

Проделаем те же манипуляции для второго жука, но уже с подстроенным классификатором ( у=0,3667х ).

Шаг 1

Подставим гусеницу ( (x,y) = (1, 3) ) в классификатор:

( y = 0.3667 cdot 1 = 0.3667 )

Шаг 2

Посмотрим на эталон:

( y_э = 3 )

Отступим от эталона на (D=0.1) и посчитаем ошибку:

(e = 2.9 — 0.3667 = 2.5333 )

Шаг 3

Вычислим величину ( D ), на которую нужно изменить наклон классификатора: .

( D = frac{2.5333}{1}=2.5333 )

Шаг 4

Корректируем наклон классификатора:

( y = (0.3667 + 2.5333)x=2,9x )

Отобразим на графике проделанные манипуляции:

Процесс настройки классификатора по двум эталонным данным. Изображение из (1)

Процесс настройки классификатора по двум эталонным данным. Изображение из (1)

Глядя на график, мы видим, что нам не удалось добиться того наклона прямой, которого мы хотели.

Линия обновляется каждый раз, подстраиваясь под то целевое значение у, которое мы задаем. В результате этого мы отбрасываем весь предыдущий опыт обучения, который могли бы использовать, и учимся лишь на самом последнем примере.

Давайте это исправим.

Сглаживание поправки

Воспользуемся идеей, которая играет ключевую роль в машинном обучении.

Вместо того чтобы каждый раз с энтузиазмом заменять (А ) новым значением, мы используем лишь некоторую долю поправки (D ) , а не всю ее целиком.

Ну что ж, сделаем перерасчет шагов 1-3 для обоих жуков, на этот раз добавив сглаживание в формулу обновления коэффициента наклона:

( D = L frac{e}{х} )

Фактор сглаживания, обозначенный здесь как ( L), часто называют коэффициентом скорости обучения.

Выберем ( L=0,5 ) в качестве разумного начального приближения. Это означает, что мы собираемся использовать поправку вдвое меньшей величины, чем без сглаживания.

Повторим шаги 1-4 для обоих жуков, используя начальное значение ( А=0,25 ).

Тестирование божьей коровки ( (x,y) = (3, 1) ) дает нам:

  1. Вычисленное значение

    (у = 0.25 cdot 3 = 0.75 )

  2. При целевом значении (y_э = 1.1 ) ошибка ( e = 0.35 )

  3. Поправка равна

    ( D = L frac{e}{х} = 0.5 frac{0,35}{3} = 0.0583 )

  4. Обновленное значение

    ( А = 0.25 + 0.0583 = 0.3083 )

    В итоге на первом жуке уравнение прямой преобразуется к виду

    ( y = 0.3083x)

Проведём расчеты с новым значением ( А ) для гусеницы ( (x,y) = (1, 3) ).

  1. Вычисленное значение

    (у = 0.3083 cdot 1 = 0.3083 )

  2. При целевом значении (y_э = 2.9 ) ошибка ( e = 2.9 — 0.3083 = 2.5917 )

  3. Поправка равна

    ( D = L frac{e}{х} = 0.5 frac{2.5917}{1} = 1.2958 )

  4. Теперь обновленное значение

    ( А = 0.3083 + 1.2958 = 1.6042 )

    В итоге на втором жуке уравнение прямой преобразуется к виду

    ( y = 1.6042x)

Отобразим на графике начальный, улучшенный и окончательный варианты классификатора, чтобы убедиться в том, что сглаживание обновлений приводит к более удовлетворительному расположению разделительной линии между областями данных божьих коровок и гусениц:

Результат настройки классификатора с коэффициентов обучения=0.5. Изображение из (1)

Результат настройки классификатора с коэффициентов обучения=0.5. Изображение из (1)

Это действительно отличный результат!

Всего лишь с двумя простыми тренировочными данными и относительно простым методом обновления мы, используя сглаживание поправки на основе скорости обучения, смогли очень быстро получить хорошую разделительную линию ( у=Ах ).

Теперь подав на вход данного классификатора некоторого жука ( (x,y) ), мы сможем определить, гусеница он или божья коровка, лишь взглянув на график.
Стоит отметить, что классификатор будет тем лучше настроен, чем больше эталонных данных он обработает.

Реализация на Scilab настройки линейного классификатора по эталонной выборке

Для начала, создадим массив с жуками


// полная выборка
data = [3 1; 
        1 3; 
        2.5 2; 
        1.5 2.5; 
        2.9 1.5;
        0.5 2;
        0.83   2.45;
        1.93   2.85;
        2.91   1.15;
        2.36   0.32];

Матрица выборки в Scilab.

Далее, чтобы не привязываться к размерностям и без опаски добавлятьудалять элементы выборки, узнаем число строк в матрице:


n = size(data, "r");

узнаем размер выборки.

Пусть тренировочная выборка составляет 40% от всей выборки — на ней будем настраивать классификатор, на остальных 60% будем проверять классификатор:


dataTrainSize = round( 0.4 * n );
dataExpSize = n - dataTrainSize;

// выберем из исходной выборки с 1-го по dataTrainSize элемент
dataTrain = data(1:dataTrainSize, :);
// остальные элементы пойдут в матрицу для экспериментов
dataExp   = data(dataTrainSize+1:n, :);

обучающая и эксериментальная выборки

Зададим начальный коэффициент классификатора ( A ), скорость обучения ( L ), величину поправки ( d ):


k = .25;
L = .5;
d = .1;

обучающая и эксериментальная выборки

Проведём в цикле обучение на тренировочной выборке:


for i = 1:dataTrainSize        
    // берём первую эталонную координату
    x = dataTrain(i, 1);
    
    //сичтаем для неё у
    y = k * x;

    //посмотрим, какой должен быть у эталонный  
    yEtalon = dataTrain(i, 2);
     
    // эталонный у нужно подкорректировать - 
    // поднять, если это божья коровка
    // и опустить, если это гусеница    
    if isLadyBug(x, yEtalon) then
        yEtalon = yEtalon + d;
    else 
        yEtalon = yEtalon - d;
    end;
     
    // считаем ошибку
    e = yEtalon - y;
     
    // счиатем корректирующий коэффициент    
    dk = L*e/x;
    
    // корректируем классификатор
    k = k + dk;       
end

обучающая и эксериментальная выборки

Функция проверки «божья ли коровка попалась» имеет вид:


function lb = isLadyBug(x, y)
    lb = %T;
    
    if (x < y) then
        lb = %F;
    end
endfunction

проверяем жука на коровкость

Чтобы посмотреть, как прошла тренировка классификатора, нарисуем жуков, покрасив божьих коровок красным, на которых тренировались и сам классификатор:


subplot(121);
xgrid;
xtitle('Тренировочная выборка', 'x', 'y');

for i = 1:dataTrainSize
    plot(dataTrain(i, 1), dataTrain(i, 2), 'o');
    
    if isLadyBug(dataTrain(i, 1), dataTrain(i, 2)) then
        gce().children.mark_foreground = 5;
    end
end

t = 0:3;
plot(t, k*t);
gca().data_bounds = [0,0; 3.2, 3.2];

Вывод тренировочной выборки и классификатора

Результат настройки классифкатора и данные из обучающей выборки.

Результат настройки классифкатора и данные из обучающей выборки.

А теперь посмотрим, как классификатор разделяет оставшихся жуков:


subplot(122);
xgrid;
xtitle('Экспериментальная выборка', 'x', 'y');

plot(t, k*t)  
gca().data_bounds = [0,0; 3.2, 3.2];

for i = 1:dataExpSize
    plot(dataExp(i, 1), dataExp(i, 2), '*');
    if isLadyBug(dataExp(i, 1), dataExp(i, 2)) then
        gce().children.mark_foreground = 5;
    end
end

Разделение классификатором экспериментальной выборки

Результат настройки классифкатора и данные из экспериментальной выборки.

Результат настройки классифкатора и данные из экспериментальной выборки.

Прекрасно справляется. В конец выборки можно подобавлять значения и посмотреть, как справляется классификатор. А также, рекомендуется поизменять размер тренировочной выборки и параметры ( d ) и ( L ) .

Данная статья создана на основе чудесной книги(1) с реализацией автором приведённых примеров на Scilab.

Нравится
1
(лайкай без регистрации)

Линейные модели широко используются в машинном обучении благодаря их относительной простоте, в некоторых случаях хорошей интерпретируемости и наличию глубоко проработанных численных методов. Простейшим обоснованием линейного классификатора служит его аналогия с нервной клеткой — нейроном. Персептронные принципы обучения, первоначально заимствованные из нейрофизиологии, затем нашли математические обоснования и с точки зрения градиентных методов минимизации эмпирического риска, и с точки зрения байесовской теории классификации, и с точки зрения статистических оценок обобщающей способности.

4.1. Аппроксимация и регуляризация эмпирического риска

Рассмотрим задачу классификации с двумя классами, Y ={1,+1}. Пусть

модель алгоритмов представляет собой параметрическое семейство отображенийa(x,w) = sign[ f (x,w)], где w — вектор параметров. Функция f (x,w)

называется дискриминантной функцией. Пока мы не будем предполагать, что она линейна по параметрам. Если f (x,w) > 0, то алгоритм a относит объект к

x классу +1, иначе к классу -1. Уравнение f (x,w) = 0 описывает разделяющую поверхность. Как обычно, задача обучения классификатора a(x,w) заключается в том, чтобы настроить вектор параметров w, имея обучающую выборку пар

X l = (x , y )l

.

i

i i=1

Определение. 4.1.

Величина Mi (w) = yi f (xi,w) называется отступом

(margin)

объекта

xi ,

относительно

алгоритма

классификации

a(x,w) = sign[ f (x,w)].

ЕслиMi (w) < 0 , то алгоритм a(x,w) допускает ошибку на объекте xi . Чем больше отступ Mi (w) , тем правильнее и надёжнее классификация объекта xi .

Минимизация аппроксимированного эмпирического риска. Определим функцию потерь вида L(Mi (w)) , где L(M ) — монотонно невозрастающая

функция отступа, мажорирующая пороговую функцию потерь: [M < 0] L(M ) .

Тогда минимизацию суммарных потерь можно рассматривать как приближённый метод минимизации эмпирического риска — числа ошибок на обучающей выборке:

l

l

l

l

Q(w, X

) = [Mi (w) < 0]

) = L(Mi (w)) min .

(4.1)

Q(w, X

i=1

i=1

w

Некоторые применяемые на практике функции потерь показаны на рис. 7. Квадратичная функция потерь не является монотонной, тем не менее она соответствует линейному дискриминанту Фишера. Кусочно-линейная функция потерь соответствует методу опорных векторов (SVM), сигмоидная используется в нейронных сетях, логистическая — в логистической регрессии, экспоненци-

65

альная — в алгоритме бустинга AdaBoost. Каждый из перечисленных методов имеет свою разумную мотивацию, однако все они приводят к разным функциям потерь. Все эти методы будут рассмотрены далее. Исходя из эвристического принципа максимизации отступов, невозможно ответить на ряд вопросов: какие ещё функции L(M ) допустимы, какие из них более предпочтительны и в каких

ситуациях.

Q(M ) = (1M )2

— квадратичная

V (M ) = (1M )+

— кусочно-линейная

S(M) = 2(1+ eM )1

— сигмоидальная

L(M ) = log2(1+ eM )

— логистическая

E(M ) = eM

— экспоненциальная

Рис.7. Непрерывные аппроксимации пороговой функции потерь [M < 0]

Вероятностная модель данных позволяет по-другому взглянуть на задачу. Допустим, множество X ×Y является вероятностным пространством, и вместо модели разделяющей поверхности f (x,w) задана параметрическая модель сов-

местной плотности распределения объектов и классов p(x, y | w).

Для настройки вектора параметров w по обучающей выборке X l применим принцип максимума правдоподобия. Найдём такое значение вектора пара-

метров w, при котором наблюдаемая выборка X l максимально правдоподобна (совместная плотность распределения объектов выборки максимальна). Если

выборка X l простая (состоит из независимых наблюдений, взятых из одного и того же распределения p(x, y | w), то правдоподобие представляется в виде про-

изведения:

p(Xl |w) =

l

p(x

,y

|w) →max.

i

i

w

i=1

Удобнее рассмотреть логарифм правдоподобия:

l

L(w, X l ) = ln[ p(X l | w)] = ln[ p(xi, yi | w)] max .

(4.2)

i=1

w

Сопоставляя (4.2) с правой частью (4.1), легко заключить, что эти две задачи эквивалентны, если положить ln[ p(xi, yi | w)] = L[yi f (xi,w)]. Зная модель

плотности p(x, y | w), можно выписать вид разделяющей поверхности f и

функцию L . С другой стороны, задавая вид разделяющей поверхности и функцию потерь L , казалось бы, из чисто эвристических соображений, мы тем самым неявно принимаем некоторую вероятностную модель данных.

66

Принцип максимума совместного правдоподобия данных и модели. Допу-

стим, что наряду с параметрической моделью плотности распределения p(x, y | w), имеется ещё априорное распределение в пространстве параметров

модели p(w) . Никакая модель не может быть идеальной, поэтому вряд ли параметрическое семейство плотностей p(x, y | w) содержит ту самую неизвестную

плотность, которая породила выборку. Будем считать, что выборка может быть порождена каждой из плотностей p(x, y | w) с вероятностью p(w) .

Чтобы ослабить априорные ограничения, вместо фиксированной функции p(w) вводится параметрическое семейство априорных распределений p(w,γ ),

где γ — неизвестная и не случайная величина, называемая гиперпараметром.

Исследователю разрешается варьировать значение гиперпараметра. При этом свойства модели могут изменяться радикальным образом, и появляется возможность найти такое значение гиперпараметра, при котором модель наиболее адекватна.

Принцип максимума правдоподобия теперь будет записываться по-

другому, поскольку не только появление выборки X l , но и появление модели w также является случайным. Их совместное появление описывается, согласно формуле условной вероятности, плотностью распределения

p(X l ,w;γ ) = p(X l | w) p(w;γ ) . Таким образом, приходим к принципу максимума совместного правдоподобия данных и модели:

l

Lγ (w, X l ) = ln[ p(X l ,w;γ ) = ln[ p(xi, yi | w)] + ln[p(w;γ )] max . (4.3)

i=1

w

Функционал Ly распадается на два слагаемых: логарифм правдоподобия

(4.2) и регуляризатор, не зависящий от данных. Второе слагаемое ограничивает вектор параметров модели, не позволяя ему быть каким угодно.

Нормальный регуляризатор. Пусть вектор w n имеет нормальное распределение, все его компоненты независимы и имеют равные дисперсии σ . Будем считать σ гиперпараметром. Логарифмируя, получаем квадратичный регуляризатор:

ln[ p(w;σ)] =ln(

1

exp(

w

2

)) = −

1

w

2 +const(w),

(2πσ)n/2

2σ

2σ

где const(w) — слагаемое, не зависящее от w, которым можно пренебречь, по-

скольку оно не влияет на решение оптимизационной задачи (4.3). Минимизация регуляризованного эмпирического риска приводит в данном случае к выбору такого решения w, которое не слишком сильно отклоняется от нуля. В линейных классификаторах это позволяет избежать проблем мультиколлинеарности

67

и переобучения.

Лапласовский регуляризатор. Пусть вектор w n имеет априорное распределение Лапласа, все его компоненты независимы и имеют равные дисперсии. Тогда

1

w

1

1

n

ln[p(w;C)] = ln(

exp(

)) = −

w

1

+ const(w) ,

w

=

wj

.

(2C)n

1

C

C

j=1

Распределение Лапласа имеет более острый пик и более тяжёлые «хво-

сты», по сравнению с нормальным распределением. Его дисперсия равна 2C2 . Самое интересное и полезное для практики свойство этого регуляризатора заключается в том, что он приводит к отбору признаков. Это происходит из-за того, что априорная плотность не является гладкой в точке w = 0. Запишем оп-

тимизационную задачу настройки вектора параметров w:

l

1

n

Q(w) = Li (w) +

wj

max ,

C

i=1

j=1

w

где Li (w) = L[yi f (xi,w)] — некоторая ограниченная гладкая функция потерь.

Сделаем замену переменных, чтобы функционал стал гладким. Каждой переменной wj поставим в соответствие две новые неотрицательные переменные

u j =

1

+ wj ) и v j =

1

(

wj

(

wj

wj ). Тогда wj = u j v j и

wj

= u j + v j .

2

2

В новых переменных функционал становится гладким, но добавляются ограни- чения-неравенства:

l

1

n

Q(u,v) = Li (u v) +

(u j + v j ) min ;

C

i=1

j=1

u,v

u j 0; v j 0 ; j =1,…,n .

Для любого j хотя бы одно из ограничений u j 0 и v j 0 является актив-

ным, то есть обращается в равенство, иначе второе слагаемое в Q(u,v) можно

было бы уменьшить, не изменив первое. Если гиперпараметр C устремить к нулю, то активными в какой-то момент станут все 2n ограничений. Постепенное уменьшение гиперпараметра C приводит к увеличению числа таких j, для которых оба ограничения активны, u j = v j = 0, откуда следует, что wj = 0. В л и-

нейных моделях это приводит к тому, что значения j-го признака игнорируются и его можно исключить из модели. Таким образом, для тех моделей, в которых обнуление коэффициента wj означает исключение j-го признака, регуляриза-

ция Лапласа автоматически приводит к отбору признаков (features selection). Параметр C позволяет регулировать селективность метода. Чем меньше C, тем больше коэффициентов wj окажутся нулевыми.

68

Независимые параметры с неравными дисперсиями. Возьмём гауссовскую

модель априорного распределения

p(w) ,

w n с независимыми параметрами

wj , но теперь не будем предполагать, что дисперсии C j

параметров wj одина-

ковы:

w2j

1

n

p(w) =

exp(

) .

(4.4)

(2π)n/2

2C j

C

C

j=1

1

n

Будем считать дисперсии C j

неизвестными и определять их наравне с са-

мими параметрами wj исходя из принципа максимума совместного правдоподобия:

l

1

n

w2j

Q(w) = Li (w) +

(lnC j +

) min .

C j

i=1

2 j=1

w,C

Результатом такой модификации также является отбор признаков. ЕслиC j 0 , то параметр wj стремится к нулю и на практике часто достигает

машинного нуля. Если C j → ∞, то на параметр wj фактически не накладывается никаких ограничений, и он может принимать любые значения.

69

Это продолжение увлекательной статьи про линейные модели классификации.

сигмоид-функцию.

Итак, логистическая регрессия прогнозирует вероятность отнесения примера к классу «+» (при условии, что мы знаем его признаки и веса модели) как сигмоид-преобразование линейной комбинации вектора весов модели и вектора признаков примера:

4. Линейные модели классификации и регрессии

Следующий вопрос: как модель обучается? Тут мы опять обращаемся к принципу максимального правдоподобия.

Принцип максимального правдоподобия и логистическая регрессия

Теперь посмотрим, как из принципа максимального правдоподобия получается оптимизационная задача, которую решает логистическая регрессия, а именно, – минимизация логистической функции потерь.
Только что мы увидели, что логистическая регрессия моделирует вероятность отнесения примера к классу «+» как

4. Линейные модели классификации и регрессии

Тогда для класса «-» аналогичная вероятность:

4. Линейные модели классификации и регрессии

Оба этих выражения можно ловко объединить в одно (следите за моими руками – не обманывают ли вас):

4. Линейные модели классификации и регрессии

Выражение 4. Линейные модели классификации и регрессии называется отступом (margin) классификации на объекте 4. Линейные модели классификации и регрессии (не путать с зазором (тоже margin), про который чаще всего говорят в контексте SVM). Если он неотрицателен, модель не ошибается на объекте 4. Линейные модели классификации и регрессии, если же отрицателен – значит, класс для 4. Линейные модели классификации и регрессии спрогнозирован неправильно.
Заметим, что отступ определен для объектов именно обучающей выборки, для которых известны реальные метки целевого класса 4. Линейные модели классификации и регрессии.

Чтобы понять, почему это мы сделали такие выводы, обратимся к геометрической интерпретации линейного классификатора. Подробно про это можно почитать в материалах Евгения Соколова.

Рекомендую решить почти классическую задачу из начального курса линейной алгебры: найти расстояние от точки с радиус-вектором 4. Линейные модели классификации и регрессии до плоскости, которая задается уравнением 4. Линейные модели классификации и регрессии

Ответ

4. Линейные модели классификации и регрессии

4. Линейные модели классификации и регрессии

Когда получим (или посмотрим) ответ, то поймем, что чем больше по модулю выражение 4. Линейные модели классификации и регрессии, тем дальше точка 4. Линейные модели классификации и регрессии находится от плоскости 4. Линейные модели классификации и регрессии

Значит, выражение 4. Линейные модели классификации и регрессии – это своего рода «уверенность» модели в классификации объекта 4. Линейные модели классификации и регрессии:

  • если отступ большой (по модулю) и положительный, это значит, что метка класса поставлена правильно, а объект находится далеко от разделяющей гиперплоскости (такой объект классифицируется уверенно). На рисунке – 4. Линейные модели классификации и регрессии.
  • если отступ большой (по модулю) и отрицательный, значит метка класса поставлена неправильно, а объект находится далеко от разделяющей гиперплоскости (скорее всего такой объект – аномалия, например, его метка в обучающей выборке поставлена неправильно). На рисунке – 4. Линейные модели классификации и регрессии.
  • если отступ малый (по модулю), то объект находится близко к разделяющей гиперплоскости, а знак отступа определяет, правильно ли объект классифицирован. На рисунке – 4. Линейные модели классификации и регрессии и 4. Линейные модели классификации и регрессии.

4. Линейные модели классификации и регрессии

Теперь распишем правдоподобие выборки, а именно, вероятность наблюдать данный вектор 4. Линейные модели классификации и регрессии у выборки 4. Линейные модели классификации и регрессии. Делаем сильное предположение: объекты приходят независимо, из одного распределения (i.i.d.). Тогда

4. Линейные модели классификации и регрессии

где 4. Линейные модели классификации и регрессии – длина выборки 4. Линейные модели классификации и регрессии (число строк).

Как водится, возьмем логарифм данного выражения (сумму оптимизировать намного проще, чем произведение):

4. Линейные модели классификации и регрессии

То есть в даном случае принцип максимизации правдоподобия приводит к минимизации выражения

4. Линейные модели классификации и регрессии

Это логистическая функция потерь, просуммированная по всем объектам обучающей выборки.

Посмотрим на новую фунцию как на функцию от отступа: 4. Линейные модели классификации и регрессии. Нарисуем ее график, а также график 1/0 функциий потерь (zero-one loss), которая просто штрафует модель на 1 за ошибку на каждом объекте (отступ отрицательный): 4. Линейные модели классификации и регрессии.

4. Линейные модели классификации и регрессии

Картинка отражает общую идею, что в задаче классификации, не умея напрямую минимизировать число ошибок (по крайней мере, градиентными методами это не сделать – производная 1/0 функциий потерь в нуле обращается в бесконечность), мы минимизируем некоторую ее верхнюю оценку. В данном случае это логистическая функция потерь (где логарифм двоичный, но это не принципиально), и справедливо

4. Линейные модели классификации и регрессии

где 4. Линейные модели классификации и регрессии – попросту число ошибок логистической регрессии с весами 4. Линейные модели классификации и регрессии на выборке 4. Линейные модели классификации и регрессии.

То есть уменьшая верхнюю оценку 4. Линейные модели классификации и регрессии на число ошибок классификации, мы таким образом надеемся уменьшить и само число ошибок.

4. Линейные модели классификации и регрессии-регуляризация логистических потерь

L2-
регуляризация логистической регрессии
устроена почти так же, как и в случае с гребневой (Ridge регрессией). Вместо функционала 4. Линейные модели классификации и регрессии минимизируется следующий:

4. Линейные модели классификации и регрессии

В случае логистической регрессии принято введение обратного коэффициента регуляризации 4. Линейные модели классификации и регрессии. И тогда решением задачи будет

4. Линейные модели классификации и регрессии

Далее рассмотрим пример, позволяющий интуитивно понять один из смыслов регуляризации.

3. Наглядный пример регуляризации логистической регрессии

В 1 статье уже приводился пример того, как полиномиальные признаки позволяют линейным моделям строить нелинейные разделяющие поверхности. Покажем это в картинках.

Посмотрим, как регуляризация влияет на качество классификации на наборе данных по тестированию микрочипов из курса Andrew Ng по машинному обучению.
Будем использовать логистическую регрессию с полиномиальными признаками и варьировать параметр регуляризации C.
Сначала посмотрим, как регуляризация влияет на разделяющую границу классификатора, интуитивно распознаем переобучение и недообучение.
Потом численно установим близкий к оптимальному параметр регуляризации с помощью кросс-валидации (cross-validation) и перебора по сетке (GridSearch).

Подключение библиотек

from __future__ import division, print_function
# отключим всякие предупреждения Anaconda
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
from matplotlib import pyplot as plt
import seaborn as sns

import numpy as np
import pandas as pd
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LogisticRegression, LogisticRegressionCV
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.model_selection import GridSearchCV

Загружаем данные с помощью метода read_csv библиотеки pandas. В этом наборе данных для 118 микрочипов (объекты) указаны результаты двух тестов по контролю качества (два числовых признака) и сказано, пустили ли микрочип в производство. Признаки уже центрированы, то есть из всех значений вычтены средние по столбцам. Таким образом, «среднему» микрочипу соответствуют нулевые значения результатов тестов.

Загрузка данных

data = pd.read_csv('../../data/microchip_tests.txt',
header=None, names = ('test1','test2','released'))
# информация о наборе данных
data.info()

RangeIndex: 118 entries, 0 to 117
Data columns (total 3 columns):
test1 118 non-null float64
test2 118 non-null float64
released 118 non-null int64
dtypes: float64(2), int64(1)
memory usage: 2.8 KB

Посмотрим на первые и последние 5 строк.

4. Линейные модели классификации и регрессии

4. Линейные модели классификации и регрессии

Сохраним обучающую выборку и метки целевого класса в отдельных массивах NumPy. Отобразим данные. Красный цвет соответствует бракованным чипам, зеленый – нормальным.

Код

X = data.ix[:,:2].values
y = data.ix[:,2].values
plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов')
plt.legend();

4. Линейные модели классификации и регрессии

Определяем функцию для отображения разделяющей кривой классификатора

Код

def plot_boundary(clf, X, y, grid_step=.01, poly_featurizer=None):
x_min, x_max = X[:, 0].min() - .1, X[:, 0].max() + .1
y_min, y_max = X[:, 1].min() - .1, X[:, 1].max() + .1
xx, yy = np.meshgrid(np.arange(x_min, x_max, grid_step),
np.arange(y_min, y_max, grid_step))

# каждой точке в сетке [x_min, m_max]x[y_min, y_max]
# ставим в соответствие свой цвет
Z = clf.predict(poly_featurizer.transform(np.c_[xx.ravel(), yy.ravel()]))
Z = Z.reshape(xx.shape)
plt.contour(xx, yy, Z, cmap=plt.cm.Paired)

Полиномиальными признаками до степени 4. Линейные модели классификации и регрессии для двух переменных 4. Линейные модели классификации и регрессии и 4. Линейные модели классификации и регрессии мы называем следующие:

4. Линейные модели классификации и регрессии

Например, для 4. Линейные модели классификации и регрессии это будут следующие признаки:

4. Линейные модели классификации и регрессии

Нарисовав треугольник Пифагора, Вы сообразите, сколько таких признаков будет для 4. Линейные модели классификации и регрессии и вообще для любого 4. Линейные модели классификации и регрессии.
Попросту говоря, таких признаков экспоненциально много, и строить, скажем, для 100 признаков полиномиальные степени 10 может оказаться затратно (а более того, и не нужно).

Создадим объект sklearn, который добавит в матрицу 4. Линейные модели классификации и регрессии полиномиальные признаки вплоть до степени 7 и обучим логистическую регрессию с параметром регуляризации 4. Линейные модели классификации и регрессии. Изобразим разделяющую границу.
Также проверим долю правильных ответов классификатора на обучающей выборке. Видим, что регуляризация оказалась слишком сильной, и модель «недообучилась». Доля правильных ответов классификатора на обучающей выборке оказалась равной 0.627.

Код

poly = PolynomialFeatures(degree=7)
X_poly = poly.fit_transform(X)
C = 1e-2
logit = LogisticRegression(C=C, n_jobs=-1, random_state=17)
logit.fit(X_poly, y)

plot_boundary(logit, X, y, grid_step=.01, poly_featurizer=poly)

plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов. Логит с C=0.01')
plt.legend();

print("Доля правильных ответов классификатора на обучающей выборке:", 
round(logit.score(X_poly, y), 3))

4. Линейные модели классификации и регрессии

Увеличим 4. Линейные модели классификации и регрессии до 1. Тем самым мы ослабляем регуляризацию, теперь в решении значения весов логистической регрессии могут оказаться больше (по модулю), чем в прошлом случае. Теперь доля правильных ответов классификатора на обучающей выборке – 0.831.

Код

C = 1
logit = LogisticRegression(C=C, n_jobs=-1, random_state=17)
logit.fit(X_poly, y)

plot_boundary(logit, X, y, grid_step=.005, poly_featurizer=poly)

plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов. Логит с C=1')
plt.legend();

print("Доля правильных ответов классификатора на обучающей выборке:", 
round(logit.score(X_poly, y), 3))

4. Линейные модели классификации и регрессии

Еще увеличим 4. Линейные модели классификации и регрессии – до 10 тысяч. Теперь регуляризации явно недостаточно, и мы наблюдаем переобучение. Можно заметить, что в прошлом случае (при 4. Линейные модели классификации и регрессии=1 и «гладкой» границе) доля правильных ответов модели на обучающей выборке не намного ниже, чем в 3 случае, зато на новой выборке, можно себе представить, 2 модель сработает намного лучше.
Доля правильных ответов классификатора на обучающей выборке – 0.873.

Код

C = 1e4
logit = LogisticRegression(C=C, n_jobs=-1, random_state=17)
logit.fit(X_poly, y)

plot_boundary(logit, X, y, grid_step=.005, poly_featurizer=poly)

plt.scatter(X[y == 1, 0], X[y == 1, 1], c='green', label='Выпущен')
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red', label='Бракован')
plt.xlabel("Тест 1")
plt.ylabel("Тест 2")
plt.title('2 теста микрочипов. Логит с C=10k')
plt.legend();

print("Доля правильных ответов классификатора на обучающей выборке:", 
round(logit.score(X_poly, y), 3))

4. Линейные модели классификации и регрессии

Чтоб обсудить результаты, перепишем формулу для функционала, который оптимизируется в логистической регрессии, в таком виде:

4. Линейные модели классификации и регрессии

где

Промежуточные выводы:

  • чем больше параметр 4. Линейные модели классификации и регрессии, тем более сложные зависимости в данных может восстанавливать модель (интуитивно 4. Линейные модели классификации и регрессии соответствует «сложности» модели (model capacity))
  • если регуляризация слишком сильная (малые значения 4. Линейные модели классификации и регрессии), то решением задачи минимизации логистической функции потерь может оказаться то, когда многие веса занулились или стали слишком малыми. Еще говорят, что модель недостаточно «штрафуется» за ошибки (то есть в функционале 4. Линейные модели классификации и регрессии «перевешивает» сумма квадратов весов, а ошибка 4. Линейные модели классификации и регрессии может быть относительно большой). В таком случае модель окажется недообученной (1 случай)
  • наоборот, если регуляризация слишком слабая (большие значения 4. Линейные модели классификации и регрессии), то решением задачи оптимизации может стать вектор 4. Линейные модели классификации и регрессии с большими по модулю компонентами. В таком случае больший вклад в оптимизируемый функционал 4. Линейные модели классификации и регрессии имеет 4. Линейные модели классификации и регрессии и, вольно выражаясь, модель слишком «боится» ошибиться на объектах обучающей выборки, поэтому окажется переобученной (3 случай)
  • то, какое значение 4. Линейные модели классификации и регрессии выбрать, сама логистическая регрессия «не поймет» (или еще говорят «не выучит»), то есть это не может быть определено решением оптимизационной задачи, которой является логистическая регрессия (в отличие от весов 4. Линейные модели классификации и регрессии). Так же точно, дерево решений не может «само понять», какое ограничение на глубину выбрать (за один процесс обучения). Поэтому 4. Линейные модели классификации и регрессии – это гиперпараметр модели, который настраивается на кросс-валидации, как и max_depth для дерева.

Настройка параметра регуляризации

Теперь найдем оптимальное (в данном примере) значение параметра регуляризации 4. Линейные модели классификации и регрессии. Сделать это можно с помощью LogisticRegressionCV – перебора параметров по сетке с последующей кросс-валидацией. Этот класс создан специально для логистической регрессии (для нее известны эффективные алгоритмы перебора параметров), для произвольной модели мы бы использовали GridSearchCV, RandomizedSearchCV или, например, специальные алгоритмы оптимизации гиперпараметров, реализованные в hyperopt.

Код

skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=17)

c_values = np.logspace(-2, 3, 500)

logit_searcher = LogisticRegressionCV(Cs=c_values, cv=skf, verbose=1, n_jobs=-1)
logit_searcher.fit(X_poly, y)

Посмотрим, как качество модели (доля правильных ответов на обучающей и валидационной выборках) меняется при изменении гиперпараметра 4. Линейные модели классификации и регрессии.

4. Линейные модели классификации и регрессии

Выделим участок с «лучшими» значениями C.

4. Линейные модели классификации и регрессии

Как мы помним, такие кривые называются валидационными, раньше мы их строили вручную, но в sklearn для них их построения есть специальные методы, которые мы тоже сейчас будем использовать.

4. Где логистическая регрессия хороша и где не очень

Анализ отзывов IMDB к фильмам

Будем решать задачу бинарной классификации отзывов IMDB к фильмам. Имеется обучающая выборка с размеченными отзывами, по 12500 отзывов известно, что они хорошие, еще про 12500 – что они плохие. Здесь уже не так просто сразу приступить к машинному обучению, потому что готовой матрицы 4. Линейные модели классификации и регрессии нет – ее надо приготовить. Будем использовать самый простой подход – мешок слов («Bag of words»). При таком подходе признаками отзыва будут индикаторы наличия в нем каждого слова из всего корпуса, где корпус – это множество всех отзывов. Идея иллюстрируется картинкой

4. Линейные модели классификации и регрессии

Импорт библиотек и загрузка данных

from __future__ import division, print_function
# отключим всякие предупреждения Anaconda
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
import numpy as np
from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer, TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC

Загрузим данные отсюда (краткое описание — тут). В обучающей и тестовой выборках по 12500 тысяч хороших и плохих отзывов к фильмам.

reviews_train = load_files("YOUR PATH")
text_train, y_train = reviews_train.data, reviews_train.target
print("Number of documents in training data: %d" % len(text_train))
print(np.bincount(y_train))
# поменяйте путь к файлу
reviews_test = load_files("YOUR PATH")
text_test, y_test = reviews_test.data, reviews_test.target
print("Number of documents in test data: %d" % len(text_test))
print(np.bincount(y_test))

Пример плохого отзыва:

‘Words can’t describe how bad this movie is. I can’t explain it by writing only. You have too see it for yourself to get at grip of how horrible a movie really can be. Not that I recommend you to do that. There are so many clich , mistakes (and all other negative things you can imagine) here that will just make you cry. To start with the technical first, there are a LOT of mistakes regarding the airplane. I won’t list them here, but just mention the coloring of the plane. They didn’t even manage to show an airliner in the colors of a fictional airline, but instead used a 7479 painted in the original Boeing livery. Very bad. The plot is stupid and has been done many times before, only much, much better. There are so many ridiculous moments here that i lost count of it really early. Also, I was on the bad guys’ side all the time in the movie, because the good guys were so stupid. «Executive Decision» should without a doubt be you’re choice over this one, even the «Turbulence»-movies are better. In fact, every other movie in the world is better than this one.’

Невозможно описать словами, насколько плох этот фильм. Я не могу объяснить это только письмом. Вы тоже должны убедиться в этом сами, чтобы понять, насколько ужасным может быть фильм. Не то чтобы я рекомендовал вам это делать. Здесь так много клише , ошибок (и всего прочего негативного, что вы можете себе представить), что заставит вас плакать. Начнем с технических вопросов. В отношении самолета есть МНОГО ошибок. Я не буду их здесь перечислять, а упомяну лишь расцветку самолета. Им даже не удалось показать авиалайнер в цветах вымышленной авиакомпании, а вместо этого использовали 7479, окрашенный в оригинальную ливрею Boeing. Очень плохо. Сюжет тупой, и раньше его делали много раз, только намного лучше. Здесь так много смешных моментов, что я очень рано потерял счет. Кроме того, я все время был на стороне плохих парней в фильме, потому что хорошие парни были такими глупыми. «Исполнительное решение», без сомнения, должно быть вашим выбором вместо этого, даже фильмы «Турбулентность» лучше. Фактически, любой другой фильм в мире лучше, чем этот ».

Пример хорошего отзыва:

‘Everyone plays their part pretty well in this «little nice movie». Belushi gets the chance to live part of his life differently, but ends up realizing that what he had was going to be just as good or maybe even better. The movie shows us that we ought to take advantage of the opportunities we have, not the ones we do not or cannot have. If U can get this movie on video for around $10, itxc2xb4d be an investment!’

«Каждый хорошо играет свою роль в этом« маленьком красивом фильме ». Белуши получает шанс прожить часть своей жизни по-другому, но в итоге понимает, что то, что у него было, будет таким же хорошим, а может быть, даже лучше. Фильм показывает нам, что мы должны использовать возможности, которые у нас есть, а не те, которых у нас нет или не может быть. Если вы сможете снять этот фильм на видео примерно за 10 долларов, это будет вложением денег! ‘

Простой подсчет слов

Составим словарь всех слов с помощью CountVectorizer. Всего в выборке 74849 уникальных слов. Если посмотреть на примеры полученных «слов» (лучше их называть токенами), то можно увидеть, что многие важные этапы обработки текста мы тут пропустили (автоматическая обработка текстов – это могло бы быть темой отдельной серии статей).

Код

cv = CountVectorizer()
cv.fit(text_train)

print(len(cv.vocabulary_)) #74849
print(cv.get_feature_names()[:50])
print(cv.get_feature_names()[50000:50050])

[’00’, ‘000’, ‘0000000000001’, ‘00001’, ‘00015’, ‘000s’, ‘001’, ‘003830’, ‘006’, ‘007’, ‘0079’, ‘0080’, ‘0083’, ‘0093638’, ’00am’, ’00pm’, ’00s’, ’01’, ’01pm’, ’02’, ‘020410’, ‘029’, ’03’, ’04’, ‘041’, ’05’, ‘050’, ’06’, ’06th’, ’07’, ’08’, ‘087’, ‘089’, ’08th’, ’09’, ‘0f’, ‘0ne’, ‘0r’, ‘0s’, ’10’, ‘100’, ‘1000’, ‘1000000’, ‘10000000000000’, ‘1000lb’, ‘1000s’, ‘1001’, ‘100b’, ‘100k’, ‘100m’]
[‘pincher’, ‘pinchers’, ‘pinches’, ‘pinching’, ‘pinchot’, ‘pinciotti’, ‘pine’, ‘pineal’, ‘pineapple’, ‘pineapples’, ‘pines’, ‘pinet’, ‘pinetrees’, ‘pineyro’, ‘pinfall’, ‘pinfold’, ‘ping’, ‘pingo’, ‘pinhead’, ‘pinheads’, ‘pinho’, ‘pining’, ‘pinjar’, ‘pink’, ‘pinkerton’, ‘pinkett’, ‘pinkie’, ‘pinkins’, ‘pinkish’, ‘pinko’, ‘pinks’, ‘pinku’, ‘pinkus’, ‘pinky’, ‘pinnacle’, ‘pinnacles’, ‘pinned’, ‘pinning’, ‘pinnings’, ‘pinnochio’, ‘pinnocioesque’, ‘pino’, ‘pinocchio’, ‘pinochet’, ‘pinochets’, ‘pinoy’, ‘pinpoint’, ‘pinpoints’, ‘pins’, ‘pinsent’]

Закодируем предложения из текстов обучающей выборки индексами входящих слов. Используем разреженный формат. Преобразуем так же тестовую выборку.

X_train = cv.transform(text_train)
X_test = cv.transform(text_test)

Обучим логистическую регрессию и посмотрим на доли правильных ответов на обучающей и тестовой выборках. Получается, на тестовой выборке мы правильно угадываем тональность примерно 86.7% отзывов.

Код

%%time
logit = LogisticRegression(n_jobs=-1, random_state=7)
logit.fit(X_train, y_train)
print(round(logit.score(X_train, y_train), 3), round(logit.score(X_test, y_test), 3))

Коэффициенты модели можно красиво отобразить.

Код визуализации коэффициентов модели

def visualize_coefficients(classifier, feature_names, n_top_features=25):
# get coefficients with large absolute values 
coef = classifier.coef_.ravel()
positive_coefficients = np.argsort(coef)[-n_top_features:]
negative_coefficients = np.argsort(coef)[:n_top_features]
interesting_coefficients = np.hstack([negative_coefficients, positive_coefficients])
# plot them
plt.figure(figsize=(15, 5))
colors = ["red" if c < 0 else "blue" for c in coef[interesting_coefficients]]
plt.bar(np.arange(2 * n_top_features), coef[interesting_coefficients], color=colors)
feature_names = np.array(feature_names)
plt.xticks(np.arange(1, 1 + 2 * n_top_features), feature_names[interesting_coefficients], rotation=60, ha="right");
def plot_grid_scores(grid, param_name):
plt.plot(grid.param_grid[param_name], grid.cv_results_['mean_train_score'],
color='green', label='train')
plt.plot(grid.param_grid[param_name], grid.cv_results_['mean_test_score'],
color='red', label='test')
plt.legend();
visualize_coefficients(logit, cv.get_feature_names())

4. Линейные модели классификации и регрессии

Подберем коэффициент регуляризации для логистической регрессии. Используем sklearn.pipeline, поскольку CountVectorizer правильно применять только на тех данных, на которых в текущий момент обучается модель (чтоб не «подсматривать» в тестовую выборку и не считать по ней частоты вхождения слов). В данном случае pipeline задает последовательность действий: применить CountVectorizer, затем обучить логистическую регрессию. Так мы поднимаем долю правильных ответов до 88.5% на кросс-валидации и 87.9% – на отложенной выборке.

Код

from sklearn.pipeline import make_pipeline

text_pipe_logit = make_pipeline(CountVectorizer(), 
LogisticRegression(n_jobs=-1, random_state=7))

text_pipe_logit.fit(text_train, y_train)
print(text_pipe_logit.score(text_test, y_test))

from sklearn.model_selection import GridSearchCV

param_grid_logit = {'logisticregression__C': np.logspace(-5, 0, 6)}
grid_logit = GridSearchCV(text_pipe_logit, param_grid_logit, cv=3, n_jobs=-1)

grid_logit.fit(text_train, y_train)
grid_logit.best_params_, grid_logit.best_score_
plot_grid_scores(grid_logit, 'logisticregression__C')
grid_logit.score(text_test, y_test)

4. Линейные модели классификации и регрессии

Теперь то же самое, но со случайным лесом. Видим, что с логистической регрессией мы достигаем большей доли правильных ответов меньшими усилиями. Лес работает дольше, на отложенной выборке 85.5% правильных ответов.

Код для обучения случайного леса

from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(n_estimators=200, n_jobs=-1, random_state=17)
forest.fit(X_train, y_train)
print(round(forest.score(X_test, y_test), 3))

XOR-проблема

Теперь рассмотрим пример, где линейные модели справляются хуже.

Линейные методы классификации строят все же очень простую разделяющую поверхность – гиперплоскость. Самый известный игрушечный пример, в котором классы нельзя без ошибок поделить гиперплоскостью (то есть прямой, если это 2D), получил имя «the XOR problem».

XOR – это «исключающее ИЛИ», булева функция со следующей таблицей истинности:

4. Линейные модели классификации и регрессии

XOR дал имя простой задаче бинарной классификации, в которой классы представлены вытянутыми по диагоналям и пересекающимися облаками точек.

Код, рисующий следующие 3 картинки

# порождаем данные
rng = np.random.RandomState(0)
X = rng.randn(200, 2)
y = np.logical_xor(X[:, 0] > 0, X[:, 1] > 0)
plt.scatter(X[:, 0], X[:, 1], s=30, c=y, cmap=plt.cm.Paired);
def plot_boundary(clf, X, y, plot_title):
xx, yy = np.meshgrid(np.linspace(-3, 3, 50),
np.linspace(-3, 3, 50))
clf.fit(X, y)
# plot the decision function for each datapoint on the grid
Z = clf.predict_proba(np.vstack((xx.ravel(), yy.ravel())).T)[:, 1]
Z = Z.reshape(xx.shape)

image = plt.imshow(Z, interpolation='nearest',
extent=(xx.min(), xx.max(), yy.min(), yy.max()),
aspect='auto', origin='lower', cmap=plt.cm.PuOr_r)
contours = plt.contour(xx, yy, Z, levels= , linewidths=2,
linetypes='--')
plt.scatter(X[:, 0], X[:, 1], s=30, c=y, cmap=plt.cm.Paired)
plt.xticks(())
plt.yticks(())
plt.xlabel(r'$$')
plt.ylabel(r'$$')
plt.axis([-3, 3, -3, 3])
plt.colorbar(image)
plt.title(plot_title, fontsize=12);
plot_boundary(LogisticRegression(), X, y,
"Logistic Regression, XOR problem")
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
logit_pipe = Pipeline([('poly', PolynomialFeatures(degree=2)), 
('logit', LogisticRegression())])
plot_boundary(logit_pipe, X, y,
"Logistic Regression + quadratic features. XOR problem")

4. Линейные модели классификации и регрессии

Очевидно, нельзя провести прямую так, чтобы без ошибок отделить один класс от другого. Поэтому логистическая регрессия плохо справляется с такой задачей.

4. Линейные модели классификации и регрессии

А вот если на вход подать полиномиальные признаки, в данном случае до 2 степени, то проблема решается.

4. Линейные модели классификации и регрессии

Здесь логистическая регрессия все равно строила гиперплоскость, но в 6-мерном

продолжение следует…

Продолжение:

Часть 1 4. Линейные модели классификации и регрессии
Часть 2 . Наглядный пример регуляризации логистической регрессии — . Линейные модели…
Часть 3 . Кривые валидации и обучения — . Линейные модели классификации…

См.также

  • Регрессия
  • Принцип Харди – Вайнберга
  • Внутренняя валидность
  • Закон больших чисел
  • Мартингейл
  • Разбавление регрессии
  • Критерий отбора
  • Метод наименьших квадратов

Надеюсь, эта статья об линейные модели классификации, была вам интересна и не так слона для восприятия как могло показаться, удачи в ваших начинаниях! Надеюсь, что теперь ты понял что такое линейные модели классификации, линейная регрессия, логическая регрессия, регуляризация логистической регрессии
и для чего все это нужно, а если не понял, или есть замечания,
то нестесняся пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории
Машинное обучение

Мы начнем с самых простых и понятных моделей машинного обучения: линейных. В этой главе мы разберёмся, что это такое, почему они работают и в каких случаях их стоит использовать. Так как это первый класс моделей, с которым вы столкнётесь, мы постараемся подробно проговорить все важные моменты. Заодно объясним, как работает машинное обучение, на сравнительно простых примерах.

Почему модели линейные?

Представьте, что у вас есть множество объектов $mathbb{X}$, а вы хотели бы каждому объекту сопоставить какое-то значение. К примеру, у вас есть набор операций по банковской карте, а вы бы хотели, понять, какие из этих операций сделали мошенники. Если вы разделите все операции на два класса и нулём обозначите законные действия, а единицей мошеннические, то у вас получится простейшая задача классификации. Представьте другую ситуацию: у вас есть данные геологоразведки, по которым вы хотели бы оценить перспективы разных месторождений. В данном случае по набору геологических данных ваша модель будет, к примеру, оценивать потенциальную годовую доходность шахты. Это пример задачи регрессии. Числа, которым мы хотим сопоставить объекты из нашего множества иногда называют таргетами (от английского target).

Таким образом, задачи классификации и регрессии можно сформулировать как поиск отображения из множества объектов $mathbb{X}$ в множество возможных таргетов.

Математически задачи можно описать так:

  • классификация: $mathbb{X} to {0,1,ldots,K}$, где $0, ldots, K$ – номера классов,
  • регрессия: $mathbb{X} to mathbb{R}$.

Очевидно, что просто сопоставить какие-то объекты каким-то числам — дело довольно бессмысленное. Мы же хотим быстро обнаруживать мошенников или принимать решение, где строить шахту. Значит нам нужен какой-то критерий качества. Мы бы хотели найти такое отображение, которое лучше всего приближает истинное соответствие между объектами и таргетами. Что значит «лучше всего» – вопрос сложный. Мы к нему будем много раз возвращаться. Однако, есть более простой вопрос: среди каких отображений мы будем искать самое лучшее? Возможных отображений может быть много, но мы можем упростить себе задачу и договориться, что хотим искать решение только в каком-то заранее заданном параметризированном семействе функций. Вся эта глава будет посвящена самому простому такому семейству — линейным функциям вида

$$
y = w_1 x_1 + ldots + w_D x_D + w_0,
$$

где $y$ – целевая переменная (таргет), $(x_1, ldots, x_D)$ – вектор, соответствующий объекту выборки (вектор признаков), а $w_1, ldots, w_D, w_0$ – параметры модели. Признаки ещё называют фичами (от английского features). Вектор $w = (w_1,ldots,w_D)$ часто называют вектором весов, так как на предсказание модели можно смотреть как на взвешенную сумму признаков объекта, а число $w_0$ – свободным коэффициентом, или сдвигом (bias). Более компактно линейную модель можно записать в виде

$$y = langle x, wrangle + w_0$$

Теперь, когда мы выбрали семейство функций, в котором будем искать решение, задача стала существенно проще. Мы теперь ищем не какое-то абстрактное отображение, а конкретный вектор $(w_0,w_1,ldots,w_D)inmathbb{R}^{D+1}$.

Замечание. Чтобы применять линейную модель, нужно, чтобы каждый объект уже был представлен вектором численных признаков $x_1,ldots,x_D$. Конечно, просто текст или граф в линейную модель не положить, придётся сначала придумать для него численные фичи. Модель называют линейной, если она является линейной по этим численным признакам.

Разберёмся, как будет работать такая модель в случае, если $D = 1$. То есть у наших объектов есть ровно один численный признак, по которому они отличаются. Теперь наша линейная модель будет выглядеть совсем просто: $y = w_1 x_1 + w_0$. Для задачи регрессии мы теперь пытаемся приблизить значение игрек какой-то линейной функцией от переменной икс. А что будет значить линейность для задачи классификации? Давайте вспомним про пример с поиском мошеннических транзакций по картам. Допустим, нам известна ровно одна численная переменная — объём транзакции. Для бинарной классификации транзакций на законные и потенциально мошеннические мы будем искать так называемое разделяющее правило: там, где значение функции положительно, мы будем предсказывать один класс, где отрицательно – другой. В нашем примере простейшим правилом будет какое-то пороговое значение объёма транзакций, после которого есть смысл пометить транзакцию как подозрительную.

1_1.png

В случае более высоких размерностей вместо прямой будет гиперплоскость с аналогичным смыслом.

Вопрос на подумать. Если вы посмотрите содержание учебника, то не найдёте в нём ни «полиномиальных» моделей, ни каких-нибудь «логарифмических», хотя, казалось бы, зависимости бывают довольно сложными. Почему так?

Ответ (не открывайте сразу; сначала подумайте сами!)Линейные зависимости не так просты, как кажется. Пусть мы решаем задачу регрессии. Если мы подозреваем, что целевая переменная $y$ не выражается через $x_1, x_2$ как линейная функция, а зависит ещё от логарифма $x_1$ и ещё как-нибудь от того, разные ли знаки у признаков, то мы можем ввести дополнительные слагаемые в нашу линейную зависимость, просто объявим эти слагаемые новыми переменными и добавив перед ними соответствующие регрессионные коэффициенты

$$y approx w_1 x_1 + w_2 x_2 + w_3log{x_1} + w_4text{sgn}(x_1x_2) + w_0,$$

и в итоге из двумерной нелинейной задачи мы получили четырёхмерную линейную регрессию.

Вопрос на подумать. А как быть, если одна из фичей является категориальной, то есть принимает значения из (обычно конечного числа) значений, не являющихся числами? Например, это может быть время года, уровень образования, марка машины и так далее. Как правило, с такими значениями невозможно производить арифметические операции или же результаты их применения не имеют смысла.

Ответ (не открывайте сразу; сначала подумайте сами!)В линейную модель можно подать только численные признаки, так что категориальную фичу придётся как-то закодировать. Рассмотрим для примера вот такой датасет

1_2.png

Здесь два категориальных признака – pet_type и color. Первый принимает четыре различных значения, второй – пять.

Самый простой способ – использовать one-hot кодирование (one-hot encoding). Пусть исходный признак мог принимать $M$ значений $c_1,ldots, c_M$. Давайте заменим категориальный признак на $M$ признаков, которые принимают значения $0$ и $1$: $i$-й будет отвечать на вопрос «принимает ли признак значение $c_i$?». Иными словами, вместо ячейки со значением $c_i$ у объекта появляется строка нулей и единиц, в которой единица стоит только на $i$-м месте.

В нашем примере получится вот такая табличка:

1_3.png

Можно было бы на этом остановиться, но добавленные признаки обладают одним неприятным свойством: в каждом из них ровно одна единица, так что сумма соответствующих столбцов равна столбцу из единиц. А это уже плохо. Представьте, что у нас есть линейная модель

$$y sim w_1x_1 + ldots + w_{D-1}x_{d-1} + w_{c_1}x_{c_1} + ldots + w_{c_M}x_{c_M} + w_0$$

Преобразуем немного правую часть:

$$ysim w_1x_1 + ldots + w_{D-1}x_{d-1} + underbrace{(w_{c_1} — w_{c_M})}_{=:w’_{c_1}}x_{c_1} + ldots + underbrace{(w_{c_{M-1}} — w_{c_M})}_{=:w’_{C_{M-1}}}x_{c_{M-1}} + w_{c_M}underbrace{(x_{c_1} + ldots + x_{c_M})}_{=1} + w_0 = $$

$$ = w_1x_1 + ldots + w_{D-1}x_{d-1} + w’_{c_1}x_{c_1} + ldots + w’_{c_{M-1}}x_{c_{M-1}} + underbrace{(w_{c_M} + w_0)}_{=w’_{0}}$$

Как видим, от одного из новых признаков можно избавиться, не меняя модель. Больше того, это стоит сделать, потому что наличие «лишних» признаков ведёт к переобучению или вовсе ломает модель – подробнее об этом мы поговорим в разделе про регуляризацию. Поэтому при использовании one-hot-encoding обычно выкидывают признак, соответствующий одному из значений. Например, в нашем примере итоговая матрица объекты-признаки будет иметь вид:

1_4.png

Конечно, one-hot кодирование – это самый наивный способ работы с категориальными признаками, и для более сложных фичей или фичей с большим количеством значений оно плохо подходит. С рядом более продвинутых техник вы познакомитесь в разделе про обучение представлений.

Помимо простоты, у линейных моделей есть несколько других достоинств. К примеру, мы можем достаточно легко судить, как влияют на результат те или иные признаки. Скажем, если вес $w_i$ положителен, то с ростом $i$-го признака таргет в случае регрессии будет увеличиваться, а в случае классификации наш выбор будет сдвигаться в пользу одного из классов. Значение весов тоже имеет прозрачную интерпретацию: чем вес $w_i$ больше, тем «важнее» $i$-й признак для итогового предсказания. То есть, если вы построили линейную модель, вы неплохо можете объяснить заказчику те или иные её результаты. Это качество моделей называют интерпретируемостью. Оно особенно ценится в индустриальных задачах, цена ошибки в которых высока. Если от работы вашей модели может зависеть жизнь человека, то очень важно понимать, как модель принимает те или иные решения и какими принципами руководствуется. При этом не все методы машинного обучения хорошо интерпретируемы, к примеру, поведение искусственных нейронных сетей или градиентного бустинга интерпретировать довольно сложно.

В то же время слепо доверять весам линейных моделей тоже не стоит по целому ряду причин:

  • Линейные модели всё-таки довольно узкий класс функций, они неплохо работают для небольших датасетов и простых задач. Однако, если вы решаете линейной моделью более сложную задачу, то вам, скорее всего, придётся выдумывать дополнительные признаки, являющиеся сложными функциями от исходных. Поиск таких дополнительных признаков называется feature engineering, технически он устроен примерно так, как мы описали в вопросе про «полиномиальные модели». Вот только поиском таких искусственных фичей можно сильно увлечься, так что осмысленность интерпретации будет сильно зависеть от здравого смысла эксперта, строившего модель.
  • Если между признаками есть приближённая линейная зависимость, коэффициенты в линейной модели могут совершенно потерять физический смысл (об этой проблеме и о том, как с ней бороться, мы поговорим дальше, когда будем обсуждать регуляризацию).
  • Особенно осторожно стоит верить в утверждения вида «этот коэффициент маленький, значит, этот признак не важен». Во-первых, всё зависит от масштаба признака: вдруг коэффициент мал, чтобы скомпенсировать его. Во-вторых, зависимость действительно может быть слабой, но кто знает, в какой ситуации она окажется важна. Такие решения принимаются на основе данных, например, путём проверки статистического критерия (об этом мы коротко упомянем в разделе про вероятностные модели).
  • Конкретные значения весов могут меняться в зависимости от обучающей выборки, хотя с ростом её размера они будут потихоньку сходиться к весам «наилучшей» линейной модели, которую можно было бы построить по всем-всем-всем данным на свете.

Обсудив немного общие свойства линейных моделей, перейдём к тому, как их всё-таки обучать. Сначала разберёмся с регрессией, а затем настанет черёд классификации.

Линейная регрессия и метод наименьших квадратов (МНК)

Мы начнём с использования линейных моделей для решения задачи регрессии. Простейшим примером постановки задачи линейной регрессии является метод наименьших квадратов (Ordinary least squares).

Пусть у нас задан датасет $(X, y)$, где $y=(y_i)_{i=1}^N in mathbb{R}^N$ – вектор значений целевой переменной, а $X=(x_i)_{i = 1}^N in mathbb{R}^{N times D}, x_i in mathbb{R}^D$ – матрица объекты-признаки, в которой $i$-я строка – это вектор признаков $i$-го объекта выборки. Мы хотим моделировать зависимость $y_i$ от $x_i$ как линейную функцию со свободным членом. Общий вид такой функции из $mathbb{R}^D$ в $mathbb{R}$ выглядит следующим образом:

$$color{#348FEA}{f_w(x_i) = langle w, x_i rangle + w_0}$$

Свободный член $w_0$ часто опускают, потому что такого же результата можно добиться, добавив ко всем $x_i$ признак, тождественно равный единице; тогда роль свободного члена будет играть соответствующий ему вес:

$$begin{pmatrix}x_{i1} & ldots & x_{iD} end{pmatrix}cdotbegin{pmatrix}w_1\ vdots \ w_Dend{pmatrix} + w_0 =
begin{pmatrix}1 & x_{i1} & ldots & x_{iD} end{pmatrix}cdotbegin{pmatrix}w_0 \ w_1\ vdots \ w_D end{pmatrix}$$

Поскольку это сильно упрощает запись, в дальнейшем мы будем считать, что это уже сделано и зависимость имеет вид просто $f_w(x_i) = langle w, x_i rangle$.

Сведение к задаче оптимизации

Мы хотим, чтобы на нашем датасете (то есть на парах $(x_i, y_i)$ из обучающей выборки) функция $f_w$ как можно лучше приближала нашу зависимость.

1_5.png

Для того, чтобы чётко сформулировать задачу, нам осталось только одно: на математическом языке выразить желание «приблизить $f_w(x)$ к $y$». Говоря простым языком, мы должны научиться измерять качество модели и минимизировать её ошибку, как-то меняя обучаемые параметры. В нашем примере обучаемые параметры — это веса $w$. Функция, оценивающая то, как часто модель ошибается, традиционно называется функцией потерь, функционалом качества или просто лоссом (loss function). Важно, чтобы её было легко оптимизировать: скажем, гладкая функция потерь – это хорошо, а кусочно постоянная – просто ужасно.

Функции потерь бывают разными. От их выбора зависит то, насколько задачу в дальнейшем легко решать, и то, в каком смысле у нас получится приблизить предсказание модели к целевым значениям. Интуитивно понятно, что для нашей текущей задачи нам нужно взять вектор $y$ и вектор предсказаний модели и как-то сравнить, насколько они похожи. Так как эти вектора «живут» в одном векторном пространстве, расстояние между ними вполне может быть функцией потерь. Более того, положительная непрерывная функция от этого расстояния тоже подойдёт в качестве функции потерь. При этом способов задать расстояние между векторами тоже довольно много. От всего этого разнообразия глаза разбегаются, но мы обязательно поговорим про это позже. Сейчас давайте в качестве лосса возьмём квадрат $L^2$-нормы вектора разницы предсказаний модели и $y$. Во-первых, как мы увидим дальше, так задачу будет нетрудно решить, а во-вторых, у этого лосса есть ещё несколько дополнительных свойств:

  • $L^2$-норма разницы – это евклидово расстояние $|y — f_w(x)|_2$ между вектором таргетов и вектором ответов модели, то есть мы их приближаем в смысле самого простого и понятного «расстояния».

  • Как мы увидим в разделе про вероятностные модели, с точки зрения статистики это соответствует гипотезе о том, что наши данные состоят из линейного «сигнала» и нормально распределенного «шума».

Так вот, наша функция потерь выглядит так:

$$L(f, X, y) = |y — f(X)|_2^2 = $$

$$= |y — Xw|_2^2 = sum_{i=1}^N(y_i — langle x_i, w rangle)^2$$

Такой функционал ошибки не очень хорош для сравнения поведения моделей на выборках разного размера. Представьте, что вы хотите понять, насколько качество модели на тестовой выборке из $2500$ объектов хуже, чем на обучающей из $5000$ объектов. Вы измерили $L^2$-норму ошибки и получили в одном случае $300$, а в другом $500$. Эти числа не очень интерпретируемы. Гораздо лучше посмотреть на среднеквадратичное отклонение

$$L(f, X, y) = frac1Nsum_{i=1}^N(y_i — langle x_i, w rangle)^2$$

По этой метрике на тестовой выборке получаем $0,12$, а на обучающей $0,1$.

Функция потерь $frac1Nsum_{i=1}^N(y_i — langle x_i, w rangle)^2$ называется Mean Squared Error, MSE или среднеквадратическим отклонением. Разница с $L^2$-нормой чисто косметическая, на алгоритм решения задачи она не влияет:

$$color{#348FEA}{text{MSE}(f, X, y) = frac{1}{N}|y — X w|_2^2}$$

В самом широком смысле, функции работают с объектами множеств: берут какой-то входящий объект из одного множества и выдают на выходе соответствующий ему объект из другого. Если мы имеем дело с отображением, которое на вход принимает функции, а на выходе выдаёт число, то такое отображение называют функционалом. Если вы посмотрите на нашу функцию потерь, то увидите, что это именно функционал. Для каждой конкретной линейной функции, которую задают веса $w_i$, мы получаем число, которое оценивает, насколько точно эта функция приближает наши значения $y$. Чем меньше это число, тем точнее наше решение, значит для того, чтобы найти лучшую модель, этот функционал нам надо минимизировать по $w$:

$$color{#348FEA}{|y — Xw|_2^2 longrightarrow min_w}$$

Эту задачу можно решать разными способами. В этой главе мы сначала решим эту задачу аналитически, а потом приближенно. Сравнение двух этих решений позволит нам проиллюстрировать преимущества того подхода, которому посвящена эта книга. На наш взгляд, это самый простой способ «на пальцах» показать суть машинного обучения.

МНК: точный аналитический метод

Точку минимума можно найти разными способами. Если вам интересно аналитическое решение, вы можете найти его в главе про матричные дифференцирования (раздел «Примеры вычисления производных сложных функций»). Здесь же мы воспользуемся геометрическим подходом.

Пусть $x^{(1)},ldots,x^{(D)}$ – столбцы матрицы $X$, то есть столбцы признаков. Тогда

$$Xw = w_1x^{(1)}+ldots+w_Dx^{(D)},$$

и задачу регрессии можно сформулировать следующим образом: найти линейную комбинацию столбцов $x^{(1)},ldots,x^{(D)}$, которая наилучшим способом приближает столбец $y$ по евклидовой норме – то есть найти проекцию вектора $y$ на подпространство, образованное векторами $x^{(1)},ldots,x^{(D)}$.

Разложим $y = y_{parallel} + y_{perp}$, где $y_{parallel} = Xw$ – та самая проекция, а $y_{perp}$ – ортогональная составляющая, то есть $y_{perp} = y — Xwperp x^{(1)},ldots,x^{(D)}$. Как это можно выразить в матричном виде? Оказывается, очень просто:

$$X^T(y — Xw) = 0$$

В самом деле, каждый элемент столбца $X^T(y — Xw)$ – это скалярное произведение строки $X^T$ (=столбца $X$ = одного из $x^{(i)}$) на $y — Xw$. Из уравнения $X^T(y — Xw) = 0$ уже очень легко выразить $w$:

$$w = (X^TX)^{-1}X^Ty$$

Вопрос на подумать Для вычисления $w_{ast}$ нам приходится обращать (квадратную) матрицу $X^TX$, что возможно, только если она невырожденна. Что это значит с точки зрения анализа данных? Почему мы верим, что это выполняется во всех разумных ситуациях?

Ответ (не открывайте сразу; сначала подумайте сами!)Как известно из линейной алгебры, для вещественной матрицы $X$ ранги матриц $X$ и $X^TX$ совпадают. Матрица $X^TX$ невырожденна тогда и только тогда, когда её ранг равен числу её столбцов, что равно числу столбцов матрицы $X$. Иными словами, формула регрессии поломается, только если столбцы матрицы $X$ линейно зависимы. Столбцы матрицы $X$ – это признаки. А если наши признаки линейно зависимы, то, наверное, что-то идёт не так и мы должны выкинуть часть из них, чтобы остались только линейно независимые.

Другое дело, что зачастую признаки могут быть приближённо линейно зависимы, особенно если их много. Тогда матрица $X^TX$ будет близка к вырожденной, и это, как мы дальше увидим, будет вести к разным, в том числе вычислительным проблемам.

Вычислительная сложность аналитического решения — $O(N^2D + D^3)$, где $N$ — длина выборки, $D$ — число признаков у одного объекта. Слагаемое $N^2D$ отвечает за сложность перемножения матриц $X^T$ и $X$, а слагаемое $D^3$ — за сложность обращения их произведения. Перемножать матрицы $(X^TX)^{-1}$ и $X^T$ не стоит. Гораздо лучше сначала умножить $y$ на $X^T$, а затем полученный вектор на $(X^TX)^{-1}$: так будет быстрее и, кроме того, не нужно будет хранить матрицу $(X^TX)^{-1}X^T$.

Вычисление можно ускорить, используя продвинутые алгоритмы перемножения матриц или итерационные методы поиска обратной матрицы.

Проблемы «точного» решения

Заметим, что для получения ответа нам нужно обратить матрицу $X^TX$. Это создает множество проблем:

  1. Основная проблема в обращении матрицы — это то, что вычислительно обращать большие матрицы дело сложное, а мы бы хотели работать с датасетами, в которых у нас могут быть миллионы точек,
  2. Матрица $X^TX$, хотя почти всегда обратима в разумных задачах машинного обучения, зачастую плохо обусловлена. Особенно если признаков много, между ними может появляться приближённая линейная зависимость, которую мы можем упустить на этапе формулировки задачи. В подобных случаях погрешность нахождения $w$ будет зависеть от квадрата числа обусловленности матрицы $X$, что очень плохо. Это делает полученное таким образом решение численно неустойчивым: малые возмущения $y$ могут приводить к катастрофическим изменениям $w$.

Пара слов про число обусловленности.Пожертвовав математической строгостью, мы можем считать, что число обусловленности матрицы $X$ – это корень из отношения наибольшего и наименьшего из собственных чисел матрицы $X^TX$. Грубо говоря, оно показывает, насколько разного масштаба бывают собственные значения $X^TX$. Если рассмотреть $L^2$-норму ошибки предсказания, как функцию от $w$, то её линии уровня будут эллипсоидами, форма которых определяется квадратичной формой с матрицей $X^TX$ (проверьте это!). Таким образом, число обусловленности говорит о том, насколько вытянутыми являются эти эллипсоиды.ПодробнееДанные проблемы не являются поводом выбросить решение на помойку. Существует как минимум два способа улучшить его численные свойства, однако если вы не знаете про сингулярное разложение, то лучше вернитесь сюда, когда узнаете.

  1. Построим $QR$-разложение матрицы $X$. Напомним, что это разложение, в котором матрица $Q$ ортогональна по столбцам (то есть её столбцы ортогональны и имеют длину 1; в частности, $Q^TQ=E$), а $R$ квадратная и верхнетреугольная. Подставив его в формулу, получим

    $$w = ((QR)^TQR)^{-1}(QR)^T y = (R^Tunderbrace{Q^TQ}_{=E}R)^{-1}R^TQ^Ty = R^{-1}R^{-T}R^TQ^Ty = R^{-1}Q^Ty$$

    Отметим, что написать $(R^TR)^{-1} = R^{-1}R^{-T}$ мы имеем право благодаря тому, что $R$ квадратная. Полученная формула намного проще, обращение верхнетреугольной матрицы (=решение системы с верхнетреугольной левой частью) производится быстро и хорошо, погрешность вычисления $w$ будет зависеть просто от числа обусловленности матрицы $X$, а поскольку нахождение $QR$-разложения является достаточно стабильной операцией, мы получаем решение с более хорошими, чем у исходной формулы, численными свойствами.

  2. Также можно использовать псевдообратную матрицу, построенную с помощью сингулярного разложения, о котором подробно написано в разделе про матричные разложения. А именно, пусть

    $$A = Uunderbrace{mathrm{diag}(sigma_1,ldots,sigma_r)}_{=Sigma}V^T$$

    – это усечённое сингулярное разложение, где $r$ – это ранг $A$. В таком случае диагональная матрица посередине является квадратной, $U$ и $V$ ортогональны по столбцам: $U^TU = E$, $V^TV = E$. Тогда

    $$w = (VSigma underbrace{U^TU}_{=E}Sigma V^T)^{-1}VSigma U^Ty$$

    Заметим, что $VSigma^{-2}V^Tcdot VSigma^2V^T = E = VSigma^2V^Tcdot VSigma^{-2}V^T$, так что $(VSigma^2 V^T)^{-1} = VSigma^{-2}V^T$, откуда

    $$w = VSigma^{-2}underbrace{V^TV}_{=E}V^Tcdot VSigma U^Ty = VSigma^{-1}Uy$$

    Хорошие численные свойства сингулярного разложения позволяют утверждать, что и это решение ведёт себя довольно неплохо.

    Тем не менее, вычисление всё равно остаётся довольно долгим и будет по-прежнему страдать (хоть и не так сильно) в случае плохой обусловленности матрицы $X$.

Полностью вылечить проблемы мы не сможем, но никто и не обязывает нас останавливаться на «точном» решении (которое всё равно никогда не будет вполне точным). Поэтому ниже мы познакомим вас с совершенно другим методом.

МНК: приближенный численный метод

Минимизируемый функционал является гладким и выпуклым, а это значит, что можно эффективно искать точку его минимума с помощью итеративных градиентных методов. Более подробно вы можете прочитать о них в разделе про методы оптимизации, а здесь мы лишь коротко расскажем об одном самом базовом подходе.

Как известно, градиент функции в точке направлен в сторону её наискорейшего роста, а антиградиент (противоположный градиенту вектор) в сторону наискорейшего убывания. То есть имея какое-то приближение оптимального значения параметра $w$, мы можем его улучшить, посчитав градиент функции потерь в точке и немного сдвинув вектор весов в направлении антиградиента:

$$w_j mapsto w_j — alpha frac{d}{d{w_j}} L(f_w, X, y) $$

где $alpha$ – это параметр алгоритма («темп обучения»), который контролирует величину шага в направлении антиградиента. Описанный алгоритм называется градиентным спуском.

Посмотрим, как будет выглядеть градиентный спуск для функции потерь $L(f_w, X, y) = frac1Nvertvert Xw — yvertvert^2$. Градиент квадрата евклидовой нормы мы уже считали; соответственно,

$$
nabla_wL = frac2{N} X^T (Xw — y)
$$

Следовательно, стартовав из какого-то начального приближения, мы можем итеративно уменьшать значение функции, пока не сойдёмся (по крайней мере в теории) к минимуму (вообще говоря, локальному, но в данном случае глобальному).

Алгоритм градиентного спуска

w = random_normal()             # можно пробовать и другие виды инициализации
repeat S times:                 # другой вариант: while abs(err) > tolerance
   f = X.dot(w)                 # посчитать предсказание
   err = f - y                  # посчитать ошибку
   grad = 2 * X.T.dot(err) / N  # посчитать градиент
   w -= alpha * grad            # обновить веса

С теоретическими результатами о скорости и гарантиях сходимости градиентного спуска вы можете познакомиться в главе про методы оптимизации. Мы позволим себе лишь несколько общих замечаний:

  • Поскольку задача выпуклая, выбор начальной точки влияет на скорость сходимости, но не настолько сильно, чтобы на практике нельзя было стартовать всегда из нуля или из любой другой приятной вам точки;
  • Число обусловленности матрицы $X$ существенно влияет на скорость сходимости градиентного спуска: чем более вытянуты эллипсоиды уровня функции потерь, тем хуже;
  • Темп обучения $alpha$ тоже сильно влияет на поведение градиентного спуска; вообще говоря, он является гиперпараметром алгоритма, и его, возможно, придётся подбирать отдельно. Другими гиперпараметрами являются максимальное число итераций $S$ и/или порог tolerance.

Иллюстрация.Рассмотрим три задачи регрессии, для которых матрица $X$ имеет соответственно маленькое, среднее и большое числа обусловленности. Будем строить для них модели вида $y=w_1x_1 + w_2x_2$. Раскрасим плоскость $(w_1, w_2)$ в соответствии со значениями $|X_{text{train}}w — y_{text{train}}|^2$. Тёмная область содержит минимум этой функции – оптимальное значение $w_{ast}$. Также запустим из из двух точек градиентный спуск с разными значениями темпа обучения $alpha$ и посмотрим, что получится:

1_6.png Заголовки графиков («Round», «Elliptic», «Stripe-like») относятся к форме линий уровня потерь (чем более они вытянуты, тем хуже обусловлена задача и тем хуже может вести себя градиентный спуск).

Итог: при неудачном выборе $alpha$ алгоритм не сходится или идёт вразнос, а для плохо обусловленной задачи он сходится абы куда.

Вычислительная сложность градиентного спуска – $O(NDS)$, где, как и выше, $N$ – длина выборки, $D$ – число признаков у одного объекта. Сравните с оценкой $O(N^2D + D^3)$ для «наивного» вычисления аналитического решения.

Сложность по памяти – $O(ND)$ на хранение выборки. В памяти мы держим и выборку, и градиент, но в большинстве реалистичных сценариев доминирует выборка.

Стохастический градиентный спуск

На каждом шаге градиентного спуска нам требуется выполнить потенциально дорогую операцию вычисления градиента по всей выборке (сложность $O(ND)$). Возникает идея заменить градиент его оценкой на подвыборке (в английской литературе такую подвыборку обычно именуют batch или mini-batch; в русской разговорной терминологии тоже часто встречается слово батч или мини-батч).

А именно, если функция потерь имеет вид суммы по отдельным парам объект-таргет

$$L(w, X, y) = frac1Nsum_{i=1}^NL(w, x_i, y_i),$$

а градиент, соответственно, записывается в виде

$$nabla_wL(w, X, y) = frac1Nsum_{i=1}^Nnabla_wL(w, x_i, y_i),$$

то предлагается брать оценку

$$nabla_wL(w, X, y) approx frac1Bsum_{t=1}^Bnabla_wL(w, x_{i_t}, y_{i_t})$$

для некоторого подмножества этих пар $(x_{i_t}, y_{i_t})_{t=1}^B$. Обратите внимание на множители $frac1N$ и $frac1B$ перед суммами. Почему они нужны? Полный градиент $nabla_wL(w, X, y)$ можно воспринимать как среднее градиентов по всем объектам, то есть как оценку матожидания $mathbb{E}nabla_wL(w, x, y)$; тогда, конечно, оценка матожидания по меньшей подвыборке тоже будет иметь вид среднего градиентов по объектам этой подвыборки.

Как делить выборку на батчи? Ясно, что можно было бы случайным образом сэмплировать их из полного датасета, но даже если использовать быстрый алгоритм вроде резервуарного сэмплирования, сложность этой операции не самая оптимальная. Поэтому используют линейный проход по выборке (которую перед этим лучше всё-таки случайным образом перемешать). Давайте введём ещё один параметр нашего алгоритма: размер батча, который мы обозначим $B$. Теперь на $B$ очередных примерах вычислим градиент и обновим веса модели. При этом вместо количества шагов алгоритма обычно задают количество эпох $E$. Это ещё один гиперпараметр. Одна эпоха – это один полный проход нашего сэмплера по выборке. Заметим, что если выборка очень большая, а модель компактная, то даже первый проход бывает можно не заканчивать.

Алгоритм:

 w = normal(0, 1)
 repeat E times:
   for i = B, i <= n, i += B
      X_batch = X[i-B : i]       
      y_batch = y[i-B : i]
      f = X_batch.dot(w)                 # посчитать предсказание
      err = f - y_batch                  # посчитать ошибку
      grad = 2 * X_batch.T.dot(err) / B  # посчитать градиент
      w -= alpha * grad

Сложность по времени – $O(NDE)$. На первый взгляд, она такая же, как и у обычного градиентного спуска, но заметим, что мы сделали в $N / B$ раз больше шагов, то есть веса модели претерпели намного больше обновлений.

Сложность по памяти можно довести до $O(BD)$: ведь теперь всю выборку не надо держать в памяти, а достаточно загружать лишь текущий батч (а остальная выборка может лежать на диске, что удобно, так как в реальности задачи, в которых выборка целиком не влезает в оперативную память, встречаются сплошь и рядом). Заметим, впрочем, что при этом лучше бы $B$ взять побольше: ведь чтение с диска – намного более затратная по времени операция, чем чтение из оперативной памяти.

В целом, разницу между алгоритмами можно представлять как-то так: 1_7.png

Шаги стохастического градиентного спуска заметно более шумные, но считать их получается значительно быстрее. В итоге они тоже сходятся к оптимальному значению из-за того, что матожидание оценки градиента на батче равно самому градиенту. По крайней мере, сходимость можно получить при хорошо подобранных коэффициентах темпа обучения в случае выпуклого функционала качества. Подробнее мы об этом поговорим в главе про оптимизацию. Для сложных моделей и лоссов стохастический градиентный спуск может сходиться плохо или застревать в локальных минимумах, поэтому придумано множество его улучшений. О некоторых из них также рассказано в главе про оптимизацию.

Существует определённая терминологическая путаница, иногда стохастическим градиентным спуском называют версию алогоритма, в которой размер батча равен единице (то есть максимально шумная и быстрая версия алгоритма), а версии с бОльшим размером батча называют batch gradient descent. В книгах, которые, возможно, старше вас, такая процедура иногда ещё называется incremental gradient descent. Это не очень принципиально, но вы будьте готовы, если что.

Вопрос на подумать. Вообще говоря, если объём данных не слишком велик и позволяет это сделать, объекты лучше случайным образом перемешивать перед тем, как подавать их в алгоритм стохастического градиентного спуска. Как вам кажется, почему?

Также можно использовать различные стратегии отбора объектов. Например, чаще брать объекты, на которых ошибка больше. Какие ещё стратегии вы могли бы придумать?

Ответ (не открывайте сразу; сначала подумайте сами!)Легко представить себе ситуацию, в которой объекты как-нибудь неудачно упорядочены, скажем, по возрастанию таргета. Тогда модель будет попеременно то запоминать, что все таргеты маленькие, то – что все таргеты большие. Это может и не повлиять на качество итоговой модели, но может привести и к довольно печальным последствиям. И вообще, чем более разнообразные батчи модель увидит в процессе обучения, тем лучше.

Стратегий можно придумать много. Например, не брать объекты, на которых ошибка слишком большая (возможно, это выбросы – зачем на них учиться), или вообще не брать те, на которых ошибка достаточно мала (они «ничему не учат»). Рекомендуем, впрочем, прибегать к этим эвристикам, только если вы понимаете, зачем они вам нужны и почему есть надежда, что они помогут.

Неградиентные методы

После прочтения этой главы у вас может сложиться ощущение, что приближённые способы решения ML задач и градиентные методы – это одно и тоже, но вы будете правы в этом только на 98%. В принципе, существуют и другие способы численно решать эти задачи, но в общем случае они работают гораздо хуже, чем градиентный спуск, и не обладают таким хорошим теоретическим обоснованием. Мы не будем рассказывать про них подробно, но можете на досуге почитать, скажем, про Stepwise regression, Orthogonal matching pursuit или LARS. У LARS, кстати, есть довольно интересное свойство: он может эффективно работать на выборках, в которых число признаков больше числа примеров. С алгоритмом LARS вы можете познакомиться в главе про оптимизацию.

Регуляризация

Всегда ли решение задачи регрессии единственно? Вообще говоря, нет. Так, если в выборке два признака будут линейно зависимы (и следовательно, ранг матрицы будет меньше $D$), то гарантировано найдётся такой вектор весов $nu$ что $langlenu, x_irangle = 0 forall x_i$. В этом случае, если какой-то $w$ является решением оптимизационной задачи, то и $w + alpha nu $ тоже является решением для любого $alpha$. То есть решение не только не обязано быть уникальным, так ещё может быть сколь угодно большим по модулю. Это создаёт вычислительные трудности. Малые погрешности признаков сильно возрастают при предсказании ответа, а в градиентном спуске накапливается погрешность из-за операций со слишком большими числами.

Конечно, в жизни редко бывает так, что признаки строго линейно зависимы, а вот быть приближённо линейно зависимыми они вполне могут быть. Такая ситуация называется мультиколлинеарностью. В этом случае у нас, всё равно, возникают проблемы, близкие к описанным выше. Дело в том, что $Xnusim 0$ для вектора $nu$, состоящего из коэффициентов приближённой линейной зависимости, и, соответственно, $X^TXnuapprox 0$, то есть матрица $X^TX$ снова будет близка к вырожденной. Как и любая симметричная матрица, она диагонализуется в некотором ортонормированном базисе, и некоторые из собственных значений $lambda_i$ близки к нулю. Если вектор $X^Ty$ в выражении $(X^TX)^{-1}X^Ty$ будет близким к соответствующему собственному вектору, то он будет умножаться на $1 /{lambda_i}$, что опять же приведёт к появлению у $w$ очень больших по модулю компонент (при этом $w$ ещё и будет вычислен с большой погрешностью из-за деления на маленькое число). И, конечно же, все ошибки и весь шум, которые имелись в матрице $X$, при вычислении $ysim Xw$ будут умножаться на эти большие и неточные числа и возрастать во много-много раз, что приведёт к проблемам, от которых нас не спасёт никакое сингулярное разложение.

Важно ещё отметить, что в случае, когда несколько признаков линейно зависимы, веса $w_i$ при них теряют физический смысл. Может даже оказаться, что вес признака, с ростом которого таргет, казалось бы, должен увеличиваться, станет отрицательным. Это делает модель не только неточной, но и принципиально не интерпретируемой. Вообще, неадекватность знаков или величины весов – хорошее указание на мультиколлинеарность.

Для того, чтобы справиться с этой проблемой, задачу обычно регуляризуют, то есть добавляют к ней дополнительное ограничение на вектор весов. Это ограничение можно, как и исходный лосс, задавать по-разному, но, как правило, ничего сложнее, чем $L^1$- и $L^2$-нормы, не требуется.

Вместо исходной задачи теперь предлагается решить такую:

$$color{#348FEA}{min_w L(f, X, y) = min_w(|X w — y|_2^2 + lambda |w|^k_k )}$$

$lambda$ – это очередной параметр, а $|w|^k_k $ – это один из двух вариантов:

$$color{#348FEA}{|w|^2_2 = w^2_1 + ldots + w^2_D}$$

или

$$color{#348FEA}{|w|_1^1 = vert w_1 vert + ldots + vert w_D vert}$$

Добавка $lambda|w|^k_k$ называется регуляризационным членом или регуляризатором, а число $lambda$ – коэффициентом регуляризации.

Коэффициент $lambda$ является гиперпараметром модели и достаточно сильно влияет на качество итогового решения. Его подбирают по логарифмической шкале (скажем, от 1e-2 до 1e+2), используя для сравнения моделей с разными значениями $lambda$ дополнительную валидационную выборку. При этом качество модели с подобранным коэффициентом регуляризации уже проверяют на тестовой выборке, чтобы исключить переобучение. Более подробно о том, как нужно подбирать гиперпараметры, вы можете почитать в соответствующей главе.

Отдельно надо договориться о том, что вес $w_0$, соответствующий отступу от начала координат (то есть признаку из всех единичек), мы регуляризовать не будем, потому что это не имеет смысла: если даже все значения $y$ равномерно велики, это не должно портить качество обучения. Обычно это не отображают в формулах, но если придираться к деталям, то стоило бы написать сумму по всем весам, кроме $w_0$:

$$|w|^2_2 = sum_{color{red}{j=1}}^{D}w_j^2,$$

$$|w|_1 = sum_{color{red}{j=1}}^{D} vert w_j vert$$

В случае $L^2$-регуляризации решение задачи изменяется не очень сильно. Например, продифференцировав новый лосс по $w$, легко получить, что «точное» решение имеет вид:

$$w = (X^TX + lambda I)^{-1}X^Ty$$

Отметим, что за этой формулой стоит и понятная численная интуиция: раз матрица $X^TX$ близка к вырожденной, то обращать её сродни самоубийству. Мы лучше слегка исказим её добавкой $lambda I$, которая увеличит все собственные значения на $lambda$, отодвинув их от нуля. Да, аналитическое решение перестаёт быть «точным», но за счёт снижения численных проблем мы получим более качественное решение, чем при использовании «точной» формулы.

В свою очередь, градиент функции потерь

$$L(f_w, X, y) = |Xw — y|^2 + lambda|w|^2$$

по весам теперь выглядит так:

$$
nabla_wL(f_w, X, y) = 2X^T(Xw — y) + 2lambda w
$$

Подставив этот градиент в алгоритм стохастического градиентного спуска, мы получаем обновлённую версию приближенного алгоритма, отличающуюся от старой только наличием дополнительного слагаемого.

Вопрос на подумать. Рассмотрим стохастический градиентный спуск для $L^2$-регуляризованной линейной регрессии с батчами размера $1$. Выберите правильный вариант шага SGD:

(а) $w_imapsto w_i — 2alpha(langle w, x_jrangle — y_j)x_{ji} — frac{2alphalambda}N w_i,quad i=1,ldots,D$;

(б) $w_imapsto w_i — 2alpha(langle w, x_jrangle — y_j)x_{ji} — 2alphalambda w_i,quad i=1,ldots,D$;

(в) $w_imapsto w_i — 2alpha(langle w, x_jrangle — y_j)x_{ji} — 2lambda N w_i,quad i=1,ldots D$.

Ответ (не открывайте сразу; сначала подумайте сами!)Не регуляризованная функция потерь имеет вид $mathcal{L}(X, y, w) = frac1Nsum_{i=1}^Nmathcal{L}(x_i, y_i, w)$, и её можно воспринимать, как оценку по выборке $(x_i, y_i)_{i=1}^N$ идеальной функции потерь

$$mathcal{L}(w) = mathbb{E}_{x, y}mathcal{L}(x, y, w)$$

Регуляризационный член не зависит от выборки и добавляется отдельно:

$$mathcal{L}_{text{reg}}(w) = mathbb{E}_{x, y}mathcal{L}(x, y, w) + lambda|w|^2$$

Соответственно, идеальный градиент регуляризованной функции потерь имеет вид

$$nabla_wmathcal{L}_{text{reg}}(w) = mathbb{E}_{x, y}nabla_wmathcal{L}(x, y, w) + 2lambda w,$$

Градиент по батчу – это тоже оценка градиента идеальной функции потерь, только не на выборке $(X, y)$, а на батче $(x_{t_i}, y_{t_i})_{i=1}^B$ размера $B$. Он будет выглядеть так:

$$nabla_wmathcal{L}_{text{reg}}(w) = frac1Bsum_{i=1}^Bnabla_wmathcal{L}(x_{t_i}, y_{t_i}, w) + 2lambda w.$$

Как видите, коэффициентов, связанных с числом объектов в батче или в исходной выборке, во втором слагаемом нет. Так что верным является второй вариант. Кстати, обратите внимание, что в третьем ещё и нет коэффициента $alpha$ перед производной регуляризационного слагаемого, это тоже ошибка.

Вопрос на подумать. Распишите процедуру стохастического градиентного спуска для $L^1$-регуляризованной линейной регрессии. Как вам кажется, почему никого не волнует, что функция потерь, строго говоря, не дифференцируема?

Ответ (не открывайте сразу; сначала подумайте сами!)Распишем для случая батча размера 1:

$$w_imapsto w_i — alpha(langle w, x_jrangle — y_j)x_{ji} — frac{lambda}Ncdot text{sign}(w_i),quad i=1,ldots,D$$

Функция потерь не дифференцируема лишь в одной точке. Так как в машинном обучении чаще всего мы имеем дело с данными вероятностного характера, это не влечёт каких-то особых проблем. Дело в том, что попадание прямо в ноль очень маловероятно из-за численных погрешностей в данных, так что мы можем просто доопределить производную в одной точке, а если даже пару раз попадём в неё за время обучения, это не приведёт к каким-то значительным изменениям результатов.

Отметим, что $L^1$- и $L^2$-регуляризацию можно определять для любой функции потерь $L(w, X, y)$ (и не только в задаче регрессии, а и, например, в задаче классификации тоже). Новая функция потерь будет соответственно равна

$$widetilde{L}(w, X, y) = L(w, X, y) + lambda|w|_1$$

или

$$widetilde{L}(w, X, y) = L(w, X, y) + lambda|w|_2^2$$

Разреживание весов в $L^1$-регуляризации

$L^2$-регуляризация работает прекрасно и используется в большинстве случаев, но есть одна полезная особенность $L^1$-регуляризации: её применение приводит к тому, что у признаков, которые не оказывают большого влияния на ответ, вес в результате оптимизации получается равным $0$. Это позволяет удобным образом удалять признаки, слабо влияющие на таргет. Кроме того, это даёт возможность автоматически избавляться от признаков, которые участвуют в соотношениях приближённой линейной зависимости, соответственно, спасает от проблем, связанных с мультиколлинеарностью, о которых мы писали выше.

Не очень строгим, но довольно интуитивным образом это можно объяснить так:

  1. В точке оптимума линии уровня регуляризационного члена касаются линий уровня основного лосса, потому что, во-первых, и те, и другие выпуклые, а во-вторых, если они пересекаются трансверсально, то существует более оптимальная точка:

1_8.png

  1. Линии уровня $L^1$-нормы – это $N$-мерные октаэдры. Точки их касания с линиями уровня лосса, скорее всего, лежат на грани размерности, меньшей $N-1$, то есть как раз в области, где часть координат равна нулю:

1_9.png

Заметим, что данное построение говорит о том, как выглядит оптимальное решение задачи, но ничего не говорит о способе, которым это решение можно найти. На самом деле, найти такой оптимум непросто: у $L^1$ меры довольно плохая производная. Однако, способы есть. Можете на досуге прочитать, например, вот эту статью о том, как работало предсказание CTR в google в 2012 году. Там этой теме посвящается довольно много места. Кроме того, рекомендуем посмотреть про проксимальные методы в разделе этой книги про оптимизацию в ML.

Заметим также, что вообще-то оптимизация любой нормы $L_x, 0 < x leq 1$, приведёт к появлению разреженных векторов весов, просто если c $L^1$ ещё хоть как-то можно работать, то с остальными всё будет ещё сложнее.

Другие лоссы

Стохастический градиентный спуск можно очевидным образом обобщить для решения задачи линейной регрессии с любой другой функцией потерь, не только квадратичной: ведь всё, что нам нужно от неё, – это чтобы у функции потерь был градиент. На практике это делают редко, но тем не менее рассмотрим ещё пару вариантов.

MAE

Mean absolute error, абсолютная ошибка, появляется при замене $L^2$ нормы в MSE на $L^1$:

$$color{#348FEA}{MAE(y, widehat{y}) = frac1Nsum_{i=1}^N vert y_i — widehat{y}_ivert}$$

Можно заметить, что в MAE по сравнению с MSE существенно меньший вклад в ошибку будут вносить примеры, сильно удалённые от ответов модели. Дело тут в том, что в MAE мы считаем модуль расстояния, а не квадрат, соответственно, вклад больших ошибок в MSE получается существенно больше. Такая функция потерь уместна в случаях, когда вы пытаетесь обучить регрессию на данных с большим количеством выбросов в таргете.

Иначе на эту разницу можно посмотреть так: MSE приближает матожидание условного распределения $y mid x$, а MAE – медиану.

MAPE

Mean absolute percentage error, относительная ошибка.

$$MAPE(y, widehat{y}) = frac1Nsum_{i=1}^N left|frac{widehat{y}_i-y_i}{y_i}right|$$

Часто используется в задачах прогнозирования (например, погоды, загруженности дорог, кассовых сборов фильмов, цен), когда ответы могут быть различными по порядку величины, и при этом мы бы хотели верно угадать порядок, то есть мы не хотим штрафовать модель за предсказание 2000 вместо 1000 в разы сильней, чем за предсказание 2 вместо 1.

Вопрос на подумать. Кроме описанных выше в задаче линейной регрессии можно использовать и другие функции потерь, например, Huber loss:

$$mathcal{L}(f, X, y) = sum_{i=1}^Nh_{delta}(y_i — langle w_i, xrangle),mbox{ где }h_{delta}(z) = begin{cases}
frac12z^2, |z|leqslantdelta,\
delta(|z| — frac12delta), |z| > delta
end{cases}$$

Число $delta$ является гиперпараметром. Сложная формула при $vert zvert > delta$ нужна, чтобы функция $h_{delta}(z)$ была непрерывной. Попробуйте объяснить, зачем может быть нужна такая функция потерь.

Ответ (не открывайте сразу; сначала подумайте сами!)Часто требования формулируют в духе «функция потерь должна слабее штрафовать то-то и сильней штрафовать вот это». Например, $L^2$-регуляризованный лосс штрафует за большие по модулю веса. В данном случае можно заметить, что при небольших значениях ошибки берётся просто MSE, а при больших мы начинаем штрафовать нашу модель менее сурово. Например, это может быть полезно для того, чтобы выбросы не так сильно влияли на результат обучения.

Линейная классификация

Теперь давайте поговорим про задачу классификации. Для начала будем говорить про бинарную классификацию на два класса. Обобщить эту задачу до задачи классификации на $K$ классов не составит большого труда. Пусть теперь наши таргеты $y$ кодируют принадлежность к положительному или отрицательному классу, то есть принадлежность множеству ${-1,1}$ (в этой главе договоримся именно так обозначать классы, хотя в жизни вам будут нередко встречаться и метки ${0,1}$), а $x$ – по-прежнему векторы из $mathbb{R}^D$. Мы хотим обучить линейную модель так, чтобы плоскость, которую она задаёт, как можно лучше отделяла объекты одного класса от другого.

1_10.png

В идеальной ситуации найдётся плоскость, которая разделит классы: положительный окажется с одной стороны от неё, а отрицательный с другой. Выборка, для которой это возможно, называется линейно разделимой. Увы, в реальной жизни такое встречается крайне редко.

Как обучить линейную модель классификации, нам ещё предстоит понять, но уже ясно, что итоговое предсказание можно будет вычислить по формуле

$$y = text{sign} langle w, x_irangle$$

Почему бы не решать, как задачу регрессии?Мы можем попробовать предсказывать числа $-1$ и $1$, минимизируя для этого, например, MSE с последующим взятием знака, но ничего хорошего не получится. Во-первых, регрессия почти не штрафует за ошибки на объектах, которые лежат близко к *разделяющей плоскости*, но не с той стороны. Во вторых, ошибкой будет считаться предсказание, например, $5$ вместо $1$, хотя нам-то на самом деле не важно, какой у числа модуль, лишь бы знак был правильным. Если визуализировать такое решение, то проблемы тоже вполне заметны:

1_11.png

Нам нужна прямая, которая разделяет эти точки, а не проходит через них!

Сконструируем теперь функционал ошибки так, чтобы он вышеперечисленными проблемами не обладал. Мы хотим минимизировать число ошибок классификатора, то есть

$$sum_i mathbb{I}[y_i neq sign langle w, x_irangle]longrightarrow min_w$$

Домножим обе части на $$y_i$$ и немного упростим

$$sum_i mathbb{I}[y_i langle w, x_irangle < 0]longrightarrow min_w$$

Величина $M = y_i langle w, x_irangle$ называется отступом (margin) классификатора. Такая фунция потерь называется misclassification loss. Легко видеть, что

  • отступ положителен, когда $sign(y_i) = sign(langle w, x_irangle)$, то есть класс угадан верно; при этом чем больше отступ, тем больше расстояние от $x_i$ до разделяющей гиперплоскости, то есть «уверенность классификатора»;

  • отступ отрицателен, когда $sign(y_i) ne sign(langle w, x_irangle)$, то есть класс угадан неверно; при этом чем больше по модулю отступ, тем более сокрушительно ошибается классификатор.

От каждого из отступов мы вычисляем функцию

$$F(M) = mathbb{I}[M < 0] = begin{cases}1, M < 0,\ 0, Mgeqslant 0end{cases}$$

Она кусочно-постоянная, и из-за этого всю сумму невозможно оптимизировать градиентными методами: ведь её производная равна нулю во всех точках, где она существует. Но мы можем мажорировать её какой-нибудь более гладкой функцией, и тогда задачу можно будет решить. Функции можно использовать разные, у них свои достоинства и недостатки, давайте рассмотрим несколько примеров:

1_12.png

Вопрос на подумать. Допустим, мы как-то обучили классификатор, и подавляющее большинство отступов оказались отрицательными. Правда ли нас постигла катастрофа?

Ответ (не открывайте сразу; сначала подумайте сами!)Наверное, мы что-то сделали не так, но ситуацию можно локально выправить, если предсказывать классы, противоположные тем, которые выдаёт наша модель.

Вопрос на подумать. Предположим, что у нас есть два классификатора с примерно одинаковыми и достаточно приемлемыми значениями интересующей нас метрики. При этом одна почти всегда выдаёт предсказания с большими по модулю отступами, а вторая – с относительно маленькими. Верно ли, что первая модель лучше, чем вторая?

Ответ (не открывайте сразу; сначала подумайте сами!)На первый взгляд кажется, что первая модель действительно лучше: ведь она предсказывает «увереннее», но на самом деле всё не так однозначно: во многих случаях модель, которая умеет «честно признать, что не очень уверена в ответе», может быть предпочтительней модели, которая врёт с той же непотопляемой уверенностью, что и говорит правду. В некоторых случаях лучше может оказаться модель, которая, по сути, просто отказывается от классификации на каких-то объектах.

Ошибка перцептрона

Реализуем простейшую идею: давайте считать отступы только на неправильно классифицированных объектах и учитывать их не бинарно, а линейно, пропорционально их размеру. Получается такая функция:

$$F(M) = max(0, -M)$$

Давайте запишем такой лосс с $L^2$-регуляризацией:

$$L(w, x, y) = lambdavertvert wvertvert^2_2 + sum_i max(0, -y_i langle w, x_irangle)$$

Найдём градиент:

$$
nabla_w L(w, x, y) = 2 lambda w + sum_i
begin{cases}
0, & y_i langle w, x_i rangle > 0 \
— y_i x_i, & y_i langle w, x_i rangle leq 0
end{cases}
$$

Имея аналитическую формулу для градиента, мы теперь можем так же, как и раньше, применить стохастический градиентный спуск, и задача будет решена.

Данная функция потерь впервые была предложена для перцептрона Розенблатта, первой вычислительной модели нейросети, которая в итоге привела к появлению глубокого обучения.

Она решает задачу линейной классификации, но у неё есть одна особенность: её решение не единственно и сильно зависит от начальных параметров. Например, все изображённые ниже классификаторы имеют одинаковый нулевой лосс:

1_13.png

Hinge loss, SVM

Для таких случаев, как на картинке выше, возникает логичное желание не только найти разделяющую прямую, но и постараться провести её на одинаковом удалении от обоих классов, то есть максимизировать минимальный отступ:

1_14.png

Это можно сделать, слегка поменяв функцию ошибки, а именно положив её равной:

$$F(M) = max(0, 1-M)$$

$$L(w, x, y) = lambda||w||^2_2 + sum_i max(0, 1-y_i langle w, x_irangle)$$

$$
nabla_w L(w, x, y) = 2 lambda w + sum_i
begin{cases}
0, & 1 — y_i langle w, x_i rangle leq 0 \
— y_i x_i, & 1 — y_i langle w, x_i rangle > 0
end{cases}
$$

Почему же добавленная единичка приводит к желаемому результату?

Интуитивно это можно объяснить так: объекты, которые проклассифицированы правильно, но не очень «уверенно» (то есть $0 leq y_i langle w, x_irangle < 1$), продолжают вносить свой вклад в градиент и пытаются «отодвинуть» от себя разделяющую плоскость как можно дальше.

К данному выводу можно прийти и чуть более строго; для этого надо совершенно по-другому взглянуть на выражение, которое мы минимизируем. Поможет вот эта картинка:

1_15.png

Если мы максимизируем минимальный отступ, то надо максимизировать $frac{2}{|w|_2}$, то есть ширину полосы при условии того, что большинство объектов лежат с правильной стороны, что эквивалентно решению нашей исходной задачи:

$$lambda|w|^2_2 + sum_i max(0, 1-y_i langle w, x_irangle) longrightarrowminlimits_{w}$$

Отметим, что первое слагаемое у нас обратно пропорционально ширине полосы, но мы и максимизацию заменили на минимизацию, так что тут всё в порядке. Второе слагаемое – это штраф за то, что некоторые объекты неправильно расположены относительно разделительной полосы. В конце концов, никто нам не обещал, что классы наши линейно разделимы и можно провести оптимальную плоскость вообще без ошибок.

Итоговое положение плоскости задаётся всего несколькими обучающими примерами. Это ближайшие к плоскости правильно классифицированные объекты, которые называют опорными векторами или support vectors. Весь метод, соответственно, зовётся методом опорных векторов, или support vector machine, или сокращённо SVM. Начиная с шестидесятых годов это был сильнейший из известных методов машинного обучения. В девяностые его сменили методы, основанные на деревьях решений, которые, в свою очередь, недавно передали «пальму первенства» нейросетям.

Почему же SVM был столь популярен? Из-за небольшого количества параметров и доказуемой оптимальности. Сейчас для нас нормально выбирать специальный алгоритм под задачу и подбирать оптимальные гиперпараметры для этого алгоритма перебором, а когда-то трава была зеленее, а компьютеры медленнее, и такой роскоши у людей не было. Поэтому им нужны были модели, которые гарантированно неплохо работали бы в любой ситуации. Такой моделью и был SVM.

Другие замечательные свойства SVM: существование уникального решения и доказуемо минимальная склонность к переобучению среди всех популярных классов линейных классификаторов. Кроме того, несложная модификация алгоритма, ядровый SVM, позволяет проводить нелинейные разделяющие поверхности.

Строгий вывод постановки задачи SVM можно прочитать тут или в лекции К.В. Воронцова.

Логистическая регрессия

В этом параграфе мы будем обозначать классы нулём и единицей.

Ещё один интересный метод появляется из желания посмотреть на классификацию как на задачу предсказания вероятностей. Хороший пример – предсказание кликов в интернете (например, в рекламе и поиске). Наличие клика в обучающем логе не означает, что, если повторить полностью условия эксперимента, пользователь обязательно кликнет по объекту опять. Скорее у объектов есть какая-то «кликабельность», то есть истинная вероятность клика по данному объекту. Клик на каждом обучающем примере является реализацией этой случайной величины, и мы считаем, что в пределе в каждой точке отношение положительных и отрицательных примеров должно сходиться к этой вероятности.

Проблема состоит в том, что вероятность, по определению, величина от 0 до 1, а простого способа обучить линейную модель так, чтобы это ограничение соблюдалось, нет. Из этой ситуации можно выйти так: научить линейную модель правильно предсказывать какой-то объект, связанный с вероятностью, но с диапазоном значений $(-infty,infty)$, и преобразовать ответы модели в вероятность. Таким объектом является logit или log odds – логарифм отношения вероятности положительного события к отрицательному $logleft(frac{p}{1-p}right)$.

Если ответом нашей модели является $logleft(frac{p}{1-p}right)$, то искомую вероятность посчитать не трудно:

$$langle w, x_irangle = logleft(frac{p}{1-p}right)$$

$$e^{langle w, x_irangle} = frac{p}{1-p}$$

$$p=frac{1}{1 + e^{-langle w, x_irangle}}$$

Функция в правой части называется сигмоидой и обозначается

$$color{#348FEA}{sigma(z) = frac1{1 + e^{-z}}}$$

Таким образом, $p = sigma(langle w, x_irangle)$

Как теперь научиться оптимизировать $w$ так, чтобы модель как можно лучше предсказывала логиты? Нужно применить метод максимума правдоподобия для распределения Бернулли. Это самое простое распределение, которое возникает, к примеру, при бросках монетки, которая орлом выпадает с вероятностью $p$. У нас только событием будет не орёл, а то, что пользователь кликнул на объект с такой вероятностью. Если хотите больше подробностей, почитайте про распределение Бернулли в теоретическом минимуме.

Правдоподобие позволяет понять, насколько вероятно получить данные значения таргета $y$ при данных $X$ и весах $w$. Оно имеет вид

$$ p(ymid X, w) =prod_i p(y_imid x_i, w) $$

и для распределения Бернулли его можно выписать следующим образом:

$$ p(ymid X, w) =prod_i p_i^{y_i} (1-p_i)^{1-y_i} $$

где $p_i$ – это вероятность, посчитанная из ответов модели. Оптимизировать произведение неудобно, хочется иметь дело с суммой, так что мы перейдём к логарифмическому правдоподобию и подставим формулу для вероятности, которую мы получили выше:

$$ ell(w, X, y) = sum_i big( y_i log(p_i) + (1-y_i)log(1-p_i) big) =$$

$$ =sum_i big( y_i log(sigma(langle w, x_i rangle)) + (1-y_i)log(1 — sigma(langle w, x_i rangle)) big) $$

Если заметить, что

$$
sigma(-z) = frac{1}{1 + e^z} = frac{e^{-z}}{e^{-z} + 1} = 1 — sigma(z),
$$

то выражение можно переписать проще:

$$
ell(w, X, y)=sum_i big( y_i log(sigma(langle w, x_i rangle)) + (1 — y_i) log(sigma(-langle w, x_i rangle)) big)
$$

Нас интересует $w$, для которого правдоподобие максимально. Чтобы получить функцию потерь, которую мы будем минимизировать, умножим его на минус один:

$$color{#348FEA}{L(w, X, y) = -sum_i big( y_i log(sigma(langle w, x_i rangle)) + (1 — y_i) log(sigma(-langle w, x_i rangle)) big)}$$

В отличие от линейной регрессии, для логистической нет явной формулы решения. Деваться некуда, будем использовать градиентный спуск. К счастью, градиент устроен очень просто:

$$
nabla_w L(y, X, w) = -sum_i x_i big( y_i — sigma(langle w, x_i rangle)) big)
$$

Вывод формулы градиентаНам окажется полезным ещё одно свойство сигмоиды::

$$
frac{d log sigma(z)}{d z} = left( log left( frac{1}{1 + e^{-z}} right) right)’ = frac{e^{-z}}{1 + e^{-z}} = sigma(-z)
frac{d log sigma(-z)}{d z} = -sigma(z)
$$

Отсюда:

$$
nabla_w log sigma(langle w, x_i rangle) = sigma(-langle w, x_i rangle) x_i
nabla_w log sigma(-langle w, x_i rangle) = -sigma(langle w, x_i rangle) x_i
$$

и градиент оказывается равным

$$
nabla_w L(y, X, w) = -sum_i big( y_i x_i sigma(-langle w, x_i rangle) — (1 — y_i) x_i sigma(langle w, x_i rangle)) big) =
= -sum_i big( y_i x_i (1 — sigma(langle w, x_i rangle)) — (1 — y_i) x_i sigma(langle w, x_i rangle)) big) =
= -sum_i big( y_i x_i — y_i x_i sigma(langle w, x_i rangle) — x_i sigma(langle w, x_i rangle) + y_i x_i sigma(langle w, x_i rangle)) big) =
= -sum_i big( y_i x_i — x_i sigma(langle w, x_i rangle)) big)
$$

Предсказание модели будет вычисляться, как мы договаривались, следующим образом:

$$p=sigma(langle w, x_irangle)$$

Это вероятность положительного класса, а как от неё перейти к предсказанию самого класса? В других методах нам достаточно было посчитать знак предсказания, но теперь все наши предсказания положительные и находятся в диапазоне от 0 до 1. Что же делать? Интуитивным и не совсем (и даже совсем не) правильным является ответ «взять порог 0.5». Более корректным будет подобрать этот порог отдельно, для уже построенной регрессии минимизируя нужную вам метрику на отложенной тестовой выборке. Например, сделать так, чтобы доля положительных и отрицательных классов примерно совпадала с реальной.

Отдельно заметим, что метод называется логистической регрессией, а не логистической классификацией именно потому, что предсказываем мы не классы, а вещественные числа – логиты.

Вопрос на подумать. Проверьте, что, если метки классов – это $pm1$, а не $0$ и $1$, то функцию потерь для логистической регрессии можно записать в более компактном виде:

$$mathcal{L}(w, X, y) = sum_{i=1}^Nlog(1 + e^{-y_ilangle w, x_irangle})$$

Вопрос на подумать. Правда ли разделяющая поверхность модели логистической регрессии является гиперплоскостью?

Ответ (не открывайте сразу; сначала подумайте сами!)Разделяющая поверхность отделяет множество точек, которым мы присваиваем класс $0$ (или $-1$), и множество точек, которым мы присваиваем класс $1$. Представляется логичным провести отсечку по какому-либо значению предсказанной вероятности. Однако, выбор этого значения — дело не очевидное. Как мы увидим в главе про калибровку классификаторов, это может быть не настоящая вероятность. Допустим, мы решили провести границу по значению $frac12$. Тогда разделяющая поверхность как раз задаётся равенством $p = frac12$, что равносильно $langle w, xrangle = 0$. А это гиперплоскость.

Вопрос на подумать. Допустим, что матрица объекты-признаки $X$ имеет полный ранг по столбцам (то есть все её столбцы линейно независимы). Верно ли, что решение задачи восстановления логистической регрессии единственно?

Ответ (не открывайте сразу; сначала подумайте сами!)В этот раз хорошего геометрического доказательства, как было для линейной регрессии, пожалуй, нет; нам придётся честно посчитать вторую производную и доказать, что она является положительно определённой. Сделаем это для случая, когда метки классов – это $pm1$. Формулы так получатся немного попроще. Напомним, что в этом случае

$$L(w, X, y) = -sum_{i=1}^Nlog(1 + e^{-y_ilangle w, x_irangle})$$

Следовательно,

$$frac{partial}{partial w_{j}}L(w, X, y) = sum_{i=1}^Nfrac{y_ix_{ij}e^{-y_ilangle w, x_irangle}}{1 + e^{-y_ilangle w, x_irangle}} = sum_{i=1}^Ny_ix_{ij}left(1 — frac1{1 + e^{-y_ilangle w, x_irangle}}right)$$

$$frac{partial^2L}{partial w_jpartial w_k}(w, X, y) = sum_{i=1}^Ny^2_ix_{ij}x_{ik}frac{e^{-y_ilangle w, x_irangle}}{(1 + e^{-y_ilangle w, x_irangle})^2} =$$

$$ = sum_{i=1}^Ny^2_ix_{ij}x_{ik}sigma(y_ilangle w, x_irangle)(1 — sigma(y_ilangle w, x_irangle))$$

Теперь заметим, что $y_i^2 = 1$ и что, если обозначить через $D$ диагональную матрицу с элементами $sigma(y_ilangle w, x_irangle)(1 — sigma(y_ilangle w, x_irangle))$ на диагонали, матрицу вторых производных можно представить в виде:

$$nabla^2L = left(frac{partial^2mathcal{L}}{partial w_jpartial w_k}right) = X^TDX$$

Так как $0 < sigma(y_ilangle w, x_irangle) < 1$, у матрицы $D$ на диагонали стоят положительные числа, из которых можно извлечь квадратные корни, представив $D$ в виде $D = D^{1/2}D^{1/2}$. В свою очередь, матрица $X$ имеет полный ранг по столбцам. Стало быть, для любого вектора приращения $une 0$ имеем

$$u^TX^TDXu = u^TX^T(D^{1/2})^TD^{1/2}Xu = vert D^{1/2}Xu vert^2 > 0$$

Таким образом, функция $L$ выпукла вниз как функция от $w$, и, соответственно, точка её экстремума непременно будет точкой минимума.

А теперь – почему это не совсем правда. Дело в том, что, говоря «точка её экстремума непременно будет точкой минимума», мы уже подразумеваем существование этой самой точки экстремума. Только вот существует этот экстремум не всегда. Можно показать, что для линейно разделимой выборки функция потерь логистической регрессии не ограничена снизу, и, соответственно, никакого экстремума нет. Доказательство мы оставляем читателю.

Вопрос на подумать. На картинке ниже представлены результаты работы на одном и том же датасете трёх моделей логистической регрессии с разными коэффициентами $L^2$-регуляризации:

1_16.png

Наверху показаны предсказанные вероятности положительного класса, внизу – вид разделяющей поверхности.

Как вам кажется, какие картинки соответствуют самому большому коэффициенту регуляризации, а какие – самому маленькому? Почему?

Ответ (не открывайте сразу; сначала подумайте сами!)Коэффициент регуляризации максимален у левой модели. На это нас могут натолкнуть два соображения. Во-первых, разделяющая прямая проведена достаточно странно, то есть можно заподозрить, что регуляризационный член в лосс-функции перевесил функцию потерь исходной задачи. Во-вторых, модель предсказывает довольно близкие к $frac12$ вероятности – это значит, что значения $langle w, xrangle$ близки к нулю, то есть сам вектор $w$ близок к нулевому. Это также свидетельствует о том, что регуляризационный член играет слишком важную роль при оптимизации.

Наименьший коэффициент регуляризации у правой модели. Её предсказания достаточно «уверенные» (цвета на верхнем графике сочные, то есть вероятности быстро приближаются к $0$ или $1$). Это может свидетельствовать о том, что числа $langle w, xrangle$ достаточно велики по модулю, то есть $vertvert w vertvert$ достаточно велик.

Многоклассовая классификация

В этом разделе мы будем следовать изложению из лекций Евгения Соколова.

Пусть каждый объект нашей выборки относится к одному из $K$ классов: $mathbb{Y} = {1, ldots, K}$. Чтобы предсказывать эти классы с помощью линейных моделей, нам придётся свести задачу многоклассовой классификации к набору бинарных, которые мы уже хорошо умеем решать. Мы разберём два самых популярных способа это сделать – one-vs-all и all-vs-all, а проиллюстрировать их нам поможет вот такой игрушечный датасет

1_17.png

Один против всех (one-versus-all)

Обучим $K$ линейных классификаторов $b_1(x), ldots, b_K(x)$, выдающих оценки принадлежности классам $1, ldots, K$ соответственно. В случае с линейными моделями эти классификаторы будут иметь вид

$$b_k(x) = text{sgn}left(langle w_k, x rangle + w_{0k}right)$$

Классификатор с номером $k$ будем обучать по выборке $left(x_i, 2mathbb{I}[y_i = k] — 1right)_{i = 1}^{N}$; иными словами, мы учим классификатор отличать $k$-й класс от всех остальных.

Логично, чтобы итоговый классификатор выдавал класс, соответствующий самому уверенному из бинарных алгоритмов. Уверенность можно в каком-то смысле измерить с помощью значений линейных функций:

$$a(x) = text{argmax}_k left(langle w_k, x rangle + w_{0k}right) $$

Давайте посмотрим, что даст этот подход применительно к нашему датасету. Обучим три линейных модели, отличающих один класс от остальных:

1_18.png

Теперь сравним значения линейных функций

1_19.png

и для каждой точки выберем тот класс, которому соответствует большее значение, то есть самый «уверенный» классификатор:

1_20.png

Хочется сказать, что самый маленький класс «обидели».

Проблема данного подхода заключается в том, что каждый из классификаторов $b_1(x), dots, b_K(x)$ обучается на своей выборке, и значения линейных функций $langle w_k, x rangle + w_{0k}$ или, проще говоря, «выходы» классификаторов могут иметь разные масштабы. Из-за этого сравнивать их будет неправильно. Нормировать вектора весов, чтобы они выдавали ответы в одной и той же шкале, не всегда может быть разумным решением: так, в случае с SVM веса перестанут являться решением задачи, поскольку нормировка изменит норму весов.

Все против всех (all-versus-all)

Обучим $C_K^2$ классификаторов $a_{ij}(x)$, $i, j = 1, dots, K$, $i neq j$. Например, в случае с линейными моделями эти модели будут иметь вид

$$b_{ij}(x) = text{sgn}left( langle w_{ij}, x rangle + w_{0,ij} right)$$

Классификатор $a_{ij}(x)$ будем настраивать по подвыборке $X_{ij} subset X$, содержащей только объекты классов $i$ и $j$. Соответственно, классификатор $a_{ij}(x)$ будет выдавать для любого объекта либо класс $i$, либо класс $j$. Проиллюстрируем это для нашей выборки:

1_21.png

Чтобы классифицировать новый объект, подадим его на вход каждого из построенных бинарных классификаторов. Каждый из них проголосует за своей класс; в качестве ответа выберем тот класс, за который наберется больше всего голосов:

$$a(x) = text{argmax}_ksum_{i = 1}^{K} sum_{j neq i}mathbb{I}[a_{ij}(x) = k]$$

Для нашего датасета получается следующая картинка:

1_22.png

Обратите внимание на серый треугольник на стыке областей. Это точки, для которых голоса разделились (в данном случае каждый классификатор выдал какой-то свой класс, то есть у каждого класса было по одному голосу). Для этих точек нет явного способа выдать обоснованное предсказание.

Многоклассовая логистическая регрессия

Некоторые методы бинарной классификации можно напрямую обобщить на случай многих классов. Выясним, как это можно проделать с логистической регрессией.

В логистической регрессии для двух классов мы строили линейную модель

$$b(x) = langle w, x rangle + w_0,$$

а затем переводили её прогноз в вероятность с помощью сигмоидной функции $sigma(z) = frac{1}{1 + exp(-z)}$. Допустим, что мы теперь решаем многоклассовую задачу и построили $K$ линейных моделей

$$b_k(x) = langle w_k, x rangle + w_{0k},$$

каждая из которых даёт оценку принадлежности объекта одному из классов. Как преобразовать вектор оценок $(b_1(x), ldots, b_K(x))$ в вероятности? Для этого можно воспользоваться оператором $text{softmax}(z_1, ldots, z_K)$, который производит «нормировку» вектора:

$$text{softmax}(z_1, ldots, z_K) = left(frac{exp(z_1)}{sum_{k = 1}^{K} exp(z_k)},
dots, frac{exp(z_K)}{sum_{k = 1}^{K} exp(z_k)}right).$$

В этом случае вероятность $k$-го класса будет выражаться как

$$P(y = k vert x, w) = frac{
exp{(langle w_k, x rangle + w_{0k})}}{ sum_{j = 1}^{K} exp{(langle w_j, x rangle + w_{0j})}}.$$

Обучать эти веса предлагается с помощью метода максимального правдоподобия: так же, как и в случае с двухклассовой логистической регрессией:

$$sum_{i = 1}^{N} log P(y = y_i vert x_i, w) to max_{w_1, dots, w_K}$$

Масштабируемость линейных моделей

Мы уже обсуждали, что SGD позволяет обучению хорошо масштабироваться по числу объектов, так как мы можем не загружать их целиком в оперативную память. А что делать, если признаков очень много, или мы не знаем заранее, сколько их будет? Такое может быть актуально, например, в следующих ситуациях:

  • Классификация текстов: мы можем представить текст в формате «мешка слов», то есть неупорядоченного набора слов, встретившихся в данном тексте, и обучить на нём, например, определение тональности отзыва в интернете. Наличие каждого слова из языка в тексте у нас будет кодироваться отдельной фичой. Тогда размерность каждого элемента обучающей выборки будет порядка нескольких сотен тысяч.
  • В задаче предсказания кликов по рекламе можно получить выборку любой размерности, например, так: в качестве фичи закодируем индикатор того, что пользователь X побывал на веб-странице Y. Суммарная размерность тогда будет порядка $10^9 cdot 10^7 = 10^{16}$. Кроме того, всё время появляются новые пользователи и веб-страницы, так что на этапе применения нас ждут сюрпризы.

Есть несколько хаков, которые позволяют бороться с такими проблемами:

  • Несмотря на то, что полная размерность объекта в выборке огромна, количество ненулевых элементов в нём невелико. Значит, можно использовать разреженное кодирование, то есть вместо плотного вектора хранить словарь, в котором будут перечислены индексы и значения ненулевых элементов вектора.
  • Даже хранить все веса не обязательно! Можно хранить их в хэш-таблице и вычислять индекс по формуле hash(feature) % tablesize. Хэш может вычисляться прямо от слова или id пользователя. Таким образом, несколько фичей будут иметь общий вес, который тем не менее обучится оптимальным образом. Такой подход называется hashing trick. Ясно, что сжатие вектора весов приводит к потерям в качестве, но, как правило, ценой совсем небольших потерь можно сжать этот вектор на много порядков.

Примером открытой библиотеки, в которой реализованы эти возможности, является vowpal wabbit.

Parameter server

Если при решении задачи ставки столь высоки, что мы не можем разменивать качество на сжатие вектора весов, а признаков всё-таки очень много, то задачу можно решать распределённо, храня все признаки в шардированной хеш-таблице

1_23.png

Кружки здесь означают отдельные сервера. Жёлтые загружают данные, а серые хранят части модели. Для обучения жёлтый кружок запрашивает у серого нужные ему для предсказания веса, считает градиент и отправляет его обратно, где тот потом применяется. Схема обладает бесконечной масштабируемостью, но задач, где это оправдано, не очень много.

Подытожим

На линейную модель можно смотреть как на однослойную нейросеть, поэтому многие методы, которые были изначально разработаны для них, сейчас переиспользуются в задачах глубокого обучения, а базовые подходы к регрессии, классификации и оптимизации вообще выглядят абсолютно так же. Так что несмотря на то, что в целом линейные модели на сегодня применяются редко, то, из чего они состоят и как строятся, знать очень и очень полезно.

Надеемся также, что главным итогом прочтения этой главы для вас будет осознание того, что решение любой ML-задачи состоит из выбора функции потерь, параметризованного класса моделей и способа оптимизации. В следующих главах мы познакомимся с другими моделями и оптимизаторами, но эти базовые принципы не изменятся.

$newcommandarray[1]{begin{bmatrix}#1end{bmatrix}}$ [MITx 6.86x Notes Index]

Unit 01 — Linear Classifiers and Generalizations

Course Introduction

There are lots and lots of applications out there, but what’s so interesting about it is that, in terms of algorithms, there is a relatively small toolkit of algorithms you need to learn to understand how these different applications can work so nicely and be integrated in our daily life.

The course covers these 3 topics

Supervised Learning

  • Make predictions based on a set of data for which correct examples are given
  • E.g. Attach the label «dog» to an image, based on many couple (image/dog label) already provided
  • The correct answers of the examples provided to the algorithm are already given
  • What to produce is given explicitly as a target
  • First 3 units in increasing complexity from simple linear classification methods to more complex neural network algorithms

Unsupervised Learning

  • A generalisation of supervised learning
  • The target is no longer given
  • «Learning» to produce output (still at the end, «make predictions»), but now just observing existing outputs, like images, or molecules
  • Algorithms to learn how to generate things
  • We’ll talk about probabilistic models and how to generate samples, mix and match (???)

Reinforced Learning

  • Suggest how to act in the world given a certain goal, how to achieve an objective optimally
  • It involves making predictions, aspects of SL and UL, but also it has a goal
  • Learning from the failures, how to do things better
  • E.g. a robot arm trying to grasp an object
  • Objective is to control a system

Interesting stuff (solving real problems) happens at the mix of these 3 categories.

Lecture 1. Introduction to Machine Learning

Slides

1.1. Unit 1 Overview

Unit 1 will cover Linear classification

Exercise: predicting whether an Amazon product review, looking at only the text, will be positive or negative.

1.2. Objectives

Introduction to Machine Learning

At the end of this lecture, you will be able to:

  • understand the goal of machine learning from a movie recommender example
  • understand elements of supervised learning, and the difference between the training set and the test set
  • understand the difference of classification and regression — two representative kinds of supervised learning

1.3. What is Machine Learning?

Many examples: Interpretation of web search queries, movie reccomendations, digital assistants, automatic translations, image analysis.. playing the go game

Machine learning as a discipline aims to design, understand, and apply computer programs that learn from experience (i.e. data) for the purpose of modelling, prediction, and control.

There are many ways to learn or many reasons to learn:

  • You can try to model, understand how things work;
  • You can try to predict about, say, future outcomes;
  • Or you can try to control towards a desired output configuration.

Prediction

We will start with prediction as a core machine learning task. There are many types of predictions that we can make.:

  • We can predict outcomes of events that occur in the future such as the market, weather tomorrow, the next word a text message user will type, or anticipate pedestrian behavior in self driving vehicles, and so on.
  • We can also try to predict properties that we do not yet know. For example, properties of materials such as whether a chemical is soluble in water, what the object is in an image, what an English sentence translates to in Hindi, whether a product review carries positive sentiment, and so on.

1.4. Introduction to Supervised Learning

Common to all these “prediction problems» mentioned previously is that they would be very hard to solve in a traditional engineering way, where we specify rules or solutions directly to the problem. It is far easier to provide examples of correct behavior. For example, how would you encode rules for translation, or image classification? It is much easier to provide large numbers of translated sentences, or examples of what the objects are on a large set of images.
I don’t have to specify the solution method to be able to illustrate the task implicitly through examples.
The ability to learn the solution from examples is what has made machine learning so popular and pervasive.

We will start with supervised learning in this course. In supervised learning, we are given an example (e.g. an image) along with a target (e.g. what object is in the image), and the goal of the machine learning algorithm is to find out how to produce the target from the example.

More specifically, in supervised learning, we hypothesize a collection of functions (or mappings) parametrized by a parameter (actually a large set of parameters), from the examples (e.g. the images) to the targets (e.g. the objects in the images). The machine learning algorithm then automates the process of finding the parameter of the function that fits with the example-target pairs the best.

We will automate this process of finding these parameters, and also specifying what the mappings are.

So this is what the machine learning algorithms do for you. You can then apply the same approach in different contexts.

1.5. A Concrete Example of a Supervised Learning Task

Let’s consider a movie recommender problem.
I have a set of movies I’ve already seen (the training set), and I was to use the experience from those movies to make recommendations of whether I would like to see tens of thousands of other movies (the test set).

We will compile a feature vector (a binary list of its characteristics.. genre, director, year..) for each movie in the training set as well for those I want to test (we will denote these feature vectors as $x$).

I also give my recommendation (again binary) if I want to see again or not the films in the training set.

Now I have the training set (feature vectors with associated labels), but I really wish to solve the task over the test set.
It is this discrepancy that makes the learning task interesting. I wish to generalize what I extract from the training set and apply that information to the test set.

More specifically, I wish to learn the mapping from x to labels (plus minus one) on the basis of the training set, and hope and guarantee that that mapping, if applied now in the same way to the test examples, it would work well.

I want to predict the films in the test set based on their characteristics and my previous recommendation on the training set.

1.6. Introduction to Classifiers: Let’s bring in some geometry!

On the basis of the training set, pairs of feature vectors associated with labels, I need to learn to map each each x, each future vector, to a corresponding label, which is a plus or minus 1.

What we need is a classifier (here denoted with $h$) that maps from points to corresponding labels.

So what the classifier does is divide the space into essentially two halves — one that’s labeled 1, and the other one that’s labeled minus 1.
—> a «linear classifier» is a classifier that perform this division of the full space in the two half linearly

We need to now, somehow, evaluate how good the classifier is in relation to the training examples that we have.
To this end, we define something called training error (here denoted with $epsilon$) It has a subscript n that refers to the number of training examples that I have.
And I apply it to a particular classifier. I evaluate a particular classifier, in relation to the training examples that I have.

$epsilon_n(h) = sum_{i=1}^n frac{[!![ h(x^i) neq y^i ]!!] }{n}$

(The double brackets denotes a function that takes a comparison expression inside and returns 1 if the expression is true, 0 otherwise. It is basically an indicator function.)

In the second example of classifier given in the lesson, the training error is 0.
So, according to just the training examples, this seems like a good classifier.

The fact that the training error is zero however doesn’t mean that the classifier is perfect!

Let’s now consider a non-linear classifier.

We can build an «extreme» classifier that accept as +1 only a very narrow area around the +1 training set points.

As a result, this classifier would still have training error equal to zero, but it would classify all the points in the test set, no matter how much close to the +1 training set points they are, as -1 !

what is going on here is an issue called generalization —how well the classifier that we train on the training set generalizes or applies correctly, similarly to the test examples, as well?
This is at the heart of machine-learning problems, the ability to generalize from the training set to the test set.

The problem here is that, in allowing these kind of classifiers that wrap themselves just around the examples (in the sense of allowing any kind of non-linear classifier), we are making the hypothesis class, the set of possible classifiers that we are considering, too large.
We improve generalization, we generalize well, when we only have a very limited set of classifiers. And, out of those, we can find one that works well on the training set.

The more complex set of classifiers we consider, the less well we are likely to generalize (this is the same concept as overfitting in a statistical context).

We would wish to, in general, solve these problems by finding a small set of possibilities that work well on the training set, so as to generalize well on the test set.

Training data can be graphically depicted on a (hyper)plane. Classifiers are mappings that take feature vectors as input and produce labels as output. A common kind of classifier is the linear classifier, which linearly divides space (the hyperplane where training data lies) into two. Given a point x in the space, the classifier $h$ outputs $h(x)=1$ or $h(x)=−1$, depending on where the point $x$ exists in among the two linearly divided spaces.

Each classifier represents a possible “hypothesis» about the data; thus, the set of possible classifiers can be seen as the space of possible hypothesis

1.7. Different Kinds of Supervised Learning: classification vs regression

A supervised learning task is one where you have specified the correct behaviour.
Examples are then feature vector and what you want it to be associated with.
So you give «supervision» of what the correct behaviour is (from which the term).

Types of supervised learning:

  • Multi-way classification : $h:Χ to {text{finite set}}$
  • Regression: $h:Χ to R$
  • Structured prediction: $h:Χ to {text{structured object, like a language sentence}}$

Types of machine learning:

  • Supervised learning
  • Unsupervised learning: You can observe, but the task itself is not well-defined. The problem there is to model, to find the irregularities in how those examples vary.
  • Semi-supervised learning
  • Active learning (the algorithm asks for useful additional examples)
  • Transfer learning
  • Reinforcement learning

The training set is illustration of the task, the test set is what we wish to really do well on. But those are examples that we don’t have available at the time we need to select the mapping.

Classification maps feature vectors to categories. The number of categories need not be two — they can be as many as needed. Regression maps feature vectors to real numbers. There are other kinds of supervised learning as well.

Fully labelled training and test examples corresponds to supervised learning. Limited annotation is semi-supervised learning, and no annotation is unsupervised learning. Using knowledge from one task on another task means you’re “transferring» information. Learning how to navigate a robot means learning to act and optimize your actions, or reinforcement learning. Deciding which examples are needed to learn is the definition of active learning.

Lecture 2. Linear Classifier and Perceptron Algorithm

Slides

2.1. Objectives

At the end of this lecture, you will be able to

  • understand the concepts of Feature vectors and labels, Training set and Test set, Classifier, Training error, Test error, and the Set of classifiers
  • derive the mathematical presentation of linear classifiers
  • understand the intuitive and formal definition of linear separation
  • use the perceptron algorithm with and without offset

2.2. Review of Basic Concepts

A supervised learning task is when you are given the input and the corresponding output that you want, and you’re supposed to learn irregularity between the two in order to make predictions for future examples, or inputs, or feature vectors x.

Test error is defined exactly similarly over the test examples. So defined similarly to the training error, but over a disjoint set of examples, those future examples that you actually wish to do well.

We typically drop the n on it, assuming that the test set is relatively large,

Much of machine learning, really, the theory part is in relating how a classifier that might do well on the training set would also do well on the test set.
That’s the problem called Generalization, as we’ve already seen.
We can effect generalization by limiting the choices that we have at the time of considering minimizing the training error.

So our classifier here belongs to a set of classifiers (here denoted with $H$), that’s not the set of all mappings, but it’s a limited set of options that we constrain ourselves to.

The trick here is to somehow guide the selection of the classifier based on the training example, such that it would do well on the examples that we have not yet seen.

In order for this to be possible at all, you have to have some relationship between the training samples and the test examples.
Typically, it is assumed that both sets are samples from some large collection of examples as a random subset.
So you get a random subset as a training set.

What is this lecture going to be about ?

This lecture we will consider only linear classifiers, such that we keep the problem well generalised (we will return to the question of generalization more formally later on in this course).

We’re going to formally define the set of linear classifiers, the set H restricted set of classifiers.
We need to introduce parameters that index classifiers in this set so that we can search over the possible classifiers in the set.

We’ll see what’s the limitation of using linear classifiers.

We’ll next need to define the learning algorithm that takes in the training set and the set of classifiers and tries to find a classifier,
in that set, that somehow best fits the training set.

We will consider initially the perceptron algorithm, which is a very simple online mistake driven algorithm that is still useful as it can be generalized to high dimensional problems.
So perceptron algorithm finds a classifier $hat h$, where hat denotes an estimate from the data.
It’s an algorithm that takes, as an input, the training set and the set of classifiers and then returns that estimated classifier,

2.3. Linear Classifiers Mathematically Revisited

The dividing line here is also called decision boundary:

  • If x was a one-dimensional quantity, the decision boundary would be a point.
  • In 2D, that decision boundary is a line.
  • In 3D, it would be a plane.
  • And in higher dimensions, it’s called hyperplane that divides the space into two halves.

So now we need to parameterize the linear classifiers, so that we can effectively search for the right one given the training set.

Through the origin classifiers

Definition of a decision boundary through the origin:

All points $x$ such that $x: g_1 * x_1 + g_2 * x_2 =0$ or, calling $theta$ the vector of coefficients and $x$ the vector of the points, $x: theta cdot x =0$.

Note that this means that the vector $theta$ is ortoghonal to the positional vectors of the points in the boundary.

The classifier is now parametrised by theta: $h(x;theta)$
So each choice of theta defines one classifier.
You change theta, you get a different classifier.
It’s oriented differently.
But it also goes through origin.

Our classifier become: $h(x;theta) = sign(theta cdot x)$

Note that this association between the classifier and the parameter vector theta is not unique.
There are multiple parameter vectors theta that defined exactly the same classifier.
The norm of the parameter vector of theta is not relevant in terms of the decision boundary.

General linear classifiers

Decision boundary: $x: theta cdot x + theta_0 = 0$.

Our classifier becomes: $h(x;theta, theta_0) = sign(theta cdot x + theta_0)$

2.4. Linear Separation

A training set is said to be linearly separable if it exists a linear classifier that correctly classifies all the training examples (i.e. if parameter $hat theta$ and $hat theta_0$ exists such that $y^i * (hat theta cdot x^i + hat theta_0) &gt; 0 ~~ forall i = 1,….,n$ ).

Given $theta$ and $theta_0$, a linear classifier $h: X to {−1,0,+1}$ is a function that outputs $+1$ if $θ⋅x+θ_0$ is positive, $0$ if it is zero, and $−1$ if it is negative. In other words, $h(x)=sign(θ⋅x+θ_0)$.

2.5. The Perceptron Algorithm

When the output of a classifier is exactly 0, if the example lies exactly on the linear boundary, we count that as an error, since we don’t know which way we should really classify that point.

Training error for a linear classifier:

$epsilon_n(h) = sum_{i=1}^n frac{[!![ h(x^i) neq y^i ]!!] }{n}$

becomes:

$epsilon_n(theta,theta_0) = sum_{i=1}^n frac{[!![ y^i * (theta cdot x^i + theta_0) leq 0 ]!!] }{n}$

We can now turn to the problem of actually finding a linear classifier that agrees with the training examples to the extent possible.

Through the origin classifier

  • We start with a $theta = 0$ (vector) parameter
  • We check if, with this parameter, the classifier make an error
  • If so, we progressively update the classifier

The update function is $theta^{i} = theta^{i — 1} + y^i * x^i$.

As we start with $theta^0 = array{0}$, the first attempt is always leading to an error and to a first «update» that will be $theta^{1} = array{0} + y^1 * x^1$.

For example, given the pair $(x^1 = array{24}, y^1=-1)$, $theta_1$ becomes $theta^1 = array{0} + -1 * array{24} = array{-2-4}$

Its error is then $epsilon_n(theta^1) = [!!![ y^i * (theta¹ cdot x^i)) leq 0 ]!!!] = [!!![ ((y^i)^2 * || x^i||^2) leq 0 ]!!!] = 0$

Now, what are we going to do here over the whole training set, is we start with the 0 parameter vector and then go over all the training examples.
And if the i-th example is a mistake, then we perform that update that we just discussed.

So we’d nudge the parameters in the right direction, based on an individual update.
Now, since the different training examples might update the parameters in different directions, it is possible that the later updates actually make the earlier undo some of the earlier updates, and some of the earlier examples are no longer correctly classified.
In other words, there may be cases where the perceptron algorithm needs to go over the training set multiple times before a separable solution is found.

So we have to go through the training set here multiple times, here capital T times go through the training set, either in order or select at random, look at whether it’s a mistake, and perform a simple update.

  • function perceptron $displaystyle left(big { (x^{(i)}, y^{(i)}), i=1,…,nbig } , T right)$:
    • initialize $theta =0$ (vector);
    • for $t=1,…,T$ do
      • for $i=1,…,n$ do
        • if $y^{(i)}(theta cdot x^{(i)}) leq 0$ then
          • update $theta = theta + y^{(i)}x^{(i)}$
    • return $theta$

So the perceptron algorithm takes two parameters: the training set of data (pairs feature vectors => label) and the T parameter that tells you how many times you try to go over the training set.

Now, this classifier for a sufficiently large T, if there exists a linear classifier through origin that correctly classifies the training samples, this simple algorithm actually will find a solution to that problem.
There are many solutions typically, but this will find one. And note that the one found is not, generally, some «optimal» one, where the points are «best» separated, just one where the points are separated.

Generalised linear classifier

We can generalize the perceptron algorithm to run with the general class of linear classifiers with the offset parameter.
The only difference here is that now we initialize the parameter back to 0, as well as the scalar to 0, that we consider also $theta_0$ in the error check, that we update $theta_0$ as well and that we return it together with $theta$:

  • function perceptron $displaystyle left(big { (x^{(i)}, y^{(i)}), i=1,…,nbig } , T right)$:
    • initialize $theta =0$ (vector), $theta_0 = 0$ (scalar);
    • for $t=1,…,T$ do
      • for $i=1,…,n$ do
        • if $y^{(i)}(theta cdot x^{(i)}+theta_0) leq 0$ then
          • update $theta = theta + y^{(i)}x^{(i)}$
          • update $theta_0 = theta_0 + y^{(i)}$
    • return $theta,theta_0$

The update of $theta_0$ can be seen as the update of a linear model trough the origin, where the offset is a further dimension of the data:

The model $theta cdot x + theta_0$ can be then see equivalently as $array{theta\theta_0} cdot array{x1}$.

The update function $theta = theta + x^i*y^i$ becomes then $array{theta\theta_0} = array{theta\theta_0} + y^i * array{x1}$ from which, going back to our original model, we obtain the given update functions.

So now we have a general learning algorithm.
The simplest one, but it can be generalized to be quite powerful and therefore, hence it is a useful algorithm to understand.

For example, we saw here a binary classification, but it can be easily be extended to a multiclass classification employing a «one vs all» strategy, as explained in this SO answer or on wikipedia.

Code implementation: functions perceptron_single_step_update(), perceptron(), average_perceptron(), pegasos_single_step_update() and pegasos() in project1.

Lecture 3 Hinge loss, Margin boundaries and Regularization

Slides

3.1. Objective

Hinge loss, Margin boundaries, and Regularization

At the end of this lecture, you will be able to

  • understand the need for maximizing the margin
  • pose linear classification as an optimization problem
  • understand hinge loss, margin boundaries and regularization

3.2. Introduction

Today, we will talk about how to turn machine learning problems into optimization problems.
That is, we are going to turn the problem of finding a linear classifier on the basis of the training set into an optimization problem that can be solved in many ways.
Today’s lesson we will talk about what linear large margin classification is and introduce notions such as margin loss and regularization.

Why optimisation ?

The perceptron algorithm choose a correct classifier, but there are many possible correct classifiers.
Between them, we would favor the solution that somehow is drawn between the two sets of training examples, leaving lots of space on both sides before hitting the training examples.
This is known as a large margin classifier.

A large margin linear classifier still correctly classifies all of the test examples, even if these are noisy samples of unknown true values.
A large margin classifier in this sense is more robust against noises in the examples. In general, large margin means good generalization performance on test data.

How to find such large margin classifier? —> optimisation problem

We consider the parallel plane to the classifier passing by the closest positive and negative point as respectively positive and negative margin boundaries, and we want them to be equidistant from the classifier.

The goal here is now to use these margin boundaries essentially to define a fat decision boundary that we will still try to fit with
the training examples.
So we will push these margin boundaries apart that will force us to reorient there and move that system boundary into a place that carves out
this large empty space between the two sets of examples.

We will minimise an objective function made of two terms, the regularisation term, that push to set the boundaries as much apart as possible, but also a loss function term, that gives us the penalty from points that now, as the boundaries extend, got trapped inside the margin or even more to the other part (becoming misclassified)

3.3. Margin Boundary

The first thing that we must do is to define what exactly the margin boundaries are and how we can control them, how far they are from the decision boundary.
Remember that they are equidistant from the decision boundary.

Given the linear equation $theta cdot x + theta_0 = k$, the decision boundary is the set of points where $k=0$, the positive margin boundary is the set of points where $k$ is some positive constant and the negative margin boundary is where $k$ is some negative constant.

The equation of the decision boundary can be wrote in normalised version by dividing it by the norm of the $theta$ vector:

$frac{theta}{||theta||} cdot x + frac{theta_0}{||theta||} = frac{k}{||theta||}$

3.4. Hinge Loss and Objective Function

The objective is to maximise the distance of the decision boundary from the marginal boundaries, $k/||theta||$ for the choosen $k$ (plus/minus 1 in the lesson). This is equivalent to minimise $||theta||$, in turn equivalent to minimize $frac{||theta||^2}{2}$

We can define the Hinge loss function as a function of the amount of agreement (here denoted with $z$) between the classifier score and the data given by an equation we already saw: $y^i*(theta cdot x^i + theta_0)$.

Previously, in the perceptron algorithm, we used the indicator function of such agreement in the definition of the error $epsilon$.

Now we use its value, as the loss function is defined as:

$loss(z) = 0$ if $z geq 1$ (the point is outside the boundary, on the right direction) and $loss(z) = 1-z$ if $z &lt; 1$ (either the point is well classified, but inside the boundary — $0 leq z &lt; 1$ — or it is even misclassified — $z leq 0$).

Note that while for a point on the decision boundary, being exactly on the decision boundary implies a misclassification, being on the (right) margin boundary implies a zero loss.

A bit of terminology

  • Support vectors are the data points that lie closest to the decision surface (or hyperplane). They are the data points most difficult to classify but they have direct bearing on the optimum location of the decision surface.
  • Support-vector machines (SVMs, also support-vector networks) are supervised learning models with associated learning algorithms that analyze data used for classification and regression analysis. Given a set of training examples, each marked as belonging to one or the other of two categories, an SVM training algorithm builds a model that assigns new examples to one category or the other, making it a non-probabilistic binary linear classifier (SVMs can perform also non-linear classification using what is called the kernel trick, implicitly mapping their inputs into high-dimensional feature spaces).
  • In mathematical optimization and decision theory, a Loss function or cost function is a function that maps an event or values of one or more variables onto a real number intuitively representing some «cost» associated with the event. An optimization problem seeks to minimize a loss function. An objective function is either a loss function or its negative (in specific domains, variously called a reward function, a profit function, a utility function, a fitness function, etc.), in which case it is to be maximized.
  • The Hinge loss is a specific loss function used for training classifiers. The hinge loss is used for «maximum-margin» classification, most notably for support vector machines (SVMs). For an intended output $y = ±1$ and a classifier score $s$, the hinge loss of the prediction $s$ is defined as $ell(s) = max(0, 1-y cdot s)$.
    Note that $s$ should be the «raw» output of the classifier’s decision function, not the predicted class label. For instance, in linear SVMs, $s = mathbf{theta} cdot mathbf{x} + theta_0$, where $mathbf {x}$ is the input variable(s).
    When $y$ and $s$ have the same sign (meaning $s$ predicts the right class) and $|s| ge 1$, the hinge loss $ell(s) = 0$. When they have opposite signs, $ell(s)$ increases linearly with $s$, and similarly if $|s|&lt;1$, even if it has the same sign (correct prediction, but not by enough margin).

We are now ready to define the objective function (to minimise) as:

$J(theta , theta_0) = frac{1}{n} sum_{i=1}^{n} text{Loss}_h (y^{(i)} * (theta cdot x^{(i)} + theta_0 )) + frac{lambda }{2} mid mid theta mid mid ^2$

Now, our objective function how we wish to guide the solution is a balance between the two.
And we set the balance by defining a new parameter called regularization parameter (in the previous equation denoted by $lambda$) that simply weighs how these two terms should affect our solution.
Regularization parameter here is always greater than 0.

Greater $lambda$ : we will favor large margin solutions but potentially at a cost of incurring some further loss as the margin boundaries push past the examples.

Optimal value of $theta$ and $theta_0$ is obtained by minimizing this objective function.
So we have turned the learning problem into an optimization problem.

Code implementation: functions hinge_loss_single(), hinge_loss_full() in project1.

Homework 1

1. Perceptron Mistakes

1. (e) Perceptron Mistake Bounds

Novikoff Theorem (1962): https://arxiv.org/pdf/1305.0208.pdf

Assumptions:

  • There exists an optimal $theta^* $ such that $frac{y^{(i)}(theta ^* x^{(i)})}{| theta ^* | } geq gamma ∀ i= 1,…,n ~ text{and some} gamma >0$ (the data is separable by a linear classifier through the origin)
  • All training data set examples are bounded by being $| x^{(i)}| leq R, i=1,cdots ,n$

Predicate:

Then the number of $k$ updates of the perceptron algorithm is bounded by $k&lt;frac{R²}{gamma^2}$

Lecture 4. Linear Classification and Generalization

Slides

4.1. Objectives

At the end of this lecture, you will be able to:

  • understanding optimization view of learning
  • apply optimization algorithms such as gradient descent, stochastic gradient descent, and quadratic program

4.2. Review and the Lambda parameter

Last time (lecture 3), we talked about how to formulate maximum margin linear classification as an optimization problem.
Today, we’re going to try to understand the solutions to that optimization problem and how to find those solutions.

The objective function to minimise is still

$J(theta , theta_0) = frac{1}{n} sum_{i=1}^{n} text{Loss}_h (y^{(i)} * (theta cdot x^{(i)} + theta_0 )) + frac{lambda }{2} mid mid theta mid mid ^2$

where the first term is the average loss and the second one is the regularisation.

The average loss is what we are trying to minimize.

Minimizing the regularization term will try instead to push the margin boundaries further and further apart.

And the balance between these two are controlled by the regularization parameter lambda.

Minimising the regularisation term $frac{lambda }{2} mid mid theta mid mid ^2$ we maximise the distance of the margin boundary $frac{1}{mid mid theta mid mid}$.

And as we do that, we start hitting the actual training examples.
The boundary needs to orient itself, and we may start incurring losses.

The role of the lambda parameter

As we change the regularization parameter, lambda, we change the balance between these two terms.
The larger the value lambda is, the more we try to push the margin boundaries apart; the smaller it is, the more emphasis we put on minimizing the average laws on the training example, reducing the distance of the margin boundaries up to the extreme $lambda=0$ where the margin boundaries themselves collapse towards the actual decision boundary.

The further and further the margin boundaries are posed, the more the solution will be guided by the bulk of the points, rather than just the points that are right close to the decision boundary.
So the solution changes as we change the regularization parameter.

In other terms:

  • $lambda = 0$: if we consider a minimisation of only the loss function, without the margin boundaries, (admitting a separable problem) we would have infinite solutions within the right classifiers (similarly to the perceptron algorithm);
  • $lambda = ϵ^+$: With a very small (but positive) $lambda$, the margin boundaries would be immediately pushed to the first point(s) at the minimal distance to the classifier (aka the «support vectors», from which the name of this learning method), and only this point(s) would drive the «optimal» classifier within all the possible ones (we overfit relatively to these boundary points);
  • $lambda = text{large}^+$:
    As we increase $lambda$, we are starting to give weight also to the points that are further apart, and the optimal classifier may be changing as a consequence, eventually even misclassifying some of the closest points, if there are enough far points pushing for such classifier.

4.3. Regularization and Generalization

We minimise a new function $J/lambda = frac{1}{lambda} * frac{1}{n} sum_{i=1}^{n} text{Loss}_h (cdot) + frac{1 }{2} mid mid theta mid mid ^2$ (as $lambda$ is positive minimising the new function is equal to minimising the old one).

We can think the objective function as function of the $1/lambda$ ratio (that we denote as «c»):

  • $1/lambda$ small -> wide margins, high losses
  • $1/lambda$ big -> narrow margins, small/zero losses

Such function, once minimised, will result in optimal classifiers $h(theta^* , theta_0^* , c )$ from which I can compute the average loss. Such average loss would be a convex, monotonically decreasing function of $c$, although it would not reach zero losses even for very large values of $c$ if the problem is not linearly separable.

If we could measure also the test loss (from the test set) obtained from such optimal classifiers, we would find a typical u-shape where test loss first decreases with $c$, but then would growth up again. Also, the test loss (or «error») would be always higher than the training loss, as we are fitting from the training set, not the test set.

We call $c^* ~$ the «optimal» $c$ value that minimise the test error. If we could find it, we would have found the value of $lambda$ that best generalise the method.

Now, we cannot do that, but we will talk about how to approximately do that.

With $c$ below $c^* ~$ I am underfitting, with $c$ above $c^* ~$ I am overfitting (around the point(s) closest to the decision margin).
How to find $c^* ~$? By dividing my training set in a «new» training set, and a (smaller) validation set, our new «pretending» test set.

Using this «new» training set we can find the optimal classifier as function of $c$, and at that point use $h(theta^* , theta_0^* , c )$ to evaluate the validation loss (or «validation error») to numerically find an approximate value of $c^* ~$.

4.4. Gradient Descent

Objective: So far we have seen how to qualitatively understand the type of solutions that we get when we vary the regularization parameter and optimize with respect to theta and theta naught.
Now, we are going to talk about, actually, algorithms for finding those solutions.

Gradient descent algorithm to find the minimum of a function $J(theta)$ with respect to a parameter $theta in mathbb{R}$ (for simplicity).

  • I start with a given $theta_{text{start}}$
  • I evaluate the derivative $partial{J}/partial{theta}$ at $theta_{text{start}}$, i.e. the slope of the function in $theta_{text{start}}$. If this is positive, increasing $theta$ will increase the $J$ function and the opposite if it is negative. In both cases, if I move $theta$ in the opposite direction of the slope, I move toward a lower value of the function.
  • My new, updated value of $theta$ is then $theta = theta — eta frac{partial{J}}{partial{theta}}$ where $eta$ is known as the step size or learning rate, and the whole equation as gradient descent update rule.
  • We stop when the variation in $theta$ goes below a certain threshold.

If $eta$ is too small: we may converge very slowly or end up trapped in small local minima;

If $eta$ is too small: we may diverge instead of converge to the minimum (going to the opposite direction respect to the minimum).

If the function is strictly convex, then there would be a constant learning rate small enough that I am guaranteed quickly to get to the minimum of that function.

Multi-dimensional case

The multi-dimensional case is similar, we update each parameter with respect to the corresponding partial derivative (i.e. the corresponding entry in the gradient):

$theta_j = theta_j — eta frac{partial{J}}{partial{theta_j}}$ or, in vector form,
$mathbf{theta} = mathbf{theta} — eta nabla{J(mathbf{theta})}$

(where $nabla{J(mathbf{theta_j})}$ is the gradient of $J$, i.e. the column vector concatenating the partial derivatives with respect to the various parameters)

4.5. Stochastic Gradient Descent

Let firs note that we can write $frac{1}{n} sum_{i=1}^n (a_i) +b$ as $frac{1}{n} sum_{i=1}^n (a_i +b)$.

Our original objective function can hence be written as

$J(theta , theta_0) = frac{1}{n} sum_{i=1}^{n} left[ text{Loss}_h (y^{(i)} * (theta cdot x^{(i)} + theta_0 )) + frac{lambda }{2} mid mid theta mid mid ^2 right]$

Let’s also, for now, simplify the calculation omitting the offset parameter:

$J(theta) = frac{1}{n} sum_{i=1}^{n} left[ text{Loss}_h (y^{(i)} * (theta cdot x^{(i)} )) + frac{lambda }{2} mid mid theta mid mid ^2 right]$

We can now see the above objective function as an expectation of the function $J(theta)$: $E[J(theta)] = frac{1}{n} sum_{i=1}^{n} J[theta]$ where t

We can then use a stochastic approach (SGD, standing for Stochastic Gradient Descen), where we sample at random from the training set a single data pair $i$, we compute the gradient of the objective function with respect to that single parameter $frac{partial J_i(theta)}{partial theta}$, we compute an update of theta following the same rule as before ($mathbf{theta} = mathbf{theta} — eta_t nabla{J_i(mathbf{theta})}$), we sample an other data pair j, we re-compute the gradient with respect to this new pair, we update again ($mathbf{theta} = mathbf{theta} — eta_t nabla{J_j(mathbf{theta})}$), and so on.

This has the advantage to be more efficient than taking all the data, compute the objective function and the gradients with respect to all the data points (could be milions!), and perform the gradient descent with respect to such function.

By sampling we introduce however some stochasticity and noises, and hence we need to put care on the learning parameter that need to be reduced to avoid to diverge.

The new learning rate $eta$ needs to:

  • Be lower than the one we would employ for the deterministic gradient descent algorithm in order to reduce the variance from the stochasticity that we’re introducing:
    • reduce at each update $t$ with the limit as the steps go to infinite to go to zero $lim_{t to infty} eta_t = 0$
    • be such that are «square summable», i.e. the sum of the square values must be finite, $sum_{t=1}^∞ eta_t^2 &lt; infty$
  • But at the same time retain enough weight that we can reach the minimum wherever it is:
    • if we sum at the infinite the learning rates we must be able to reach infinity, i.e. $sum_{t=1}^infty eta_t = infty$

One possible learning rate that satisfies all the above constraints is $eta_t = frac{1}{1+t}$.

Which is the gradient of the objective function with respect to data pair $i$ ?

$nabla{J_i(mathbf{theta})} = begin{cases}
0 & text{when loss=0}
-y^{i}mathbf{x}^{(i)} & text{when loss >0}
end{cases} + lambda mathbf{theta}$

The update rule for the $i$ data pair is hence:

$mathbf{theta} = mathbf{theta} — eta_t * left( begin{cases}
0 & text{when loss=0}
-y^{i}mathbf{x}^{(i)} & text{when loss >0}
end{cases} + lambda mathbf{theta} right)$

There are three differences
between the update in the stochastic gradient descent method and the update in our earlier perception algorithm ($mathbf{theta} = mathbf{theta} + y^{(i)} mathbf{x}^{(i)}$):

  • First, is that we are actually using a decreasing learning rate due to the stochasticity.
  • The second difference is that we are actually performing the update, even if we are correctly classifying the example, because the regularization term will always yield an update, regardless of what the loss is. And the role of that regularization term is to nudge the parameters a little bit backwards, so decrease the norm of the parameter vector at every stamp, which corresponds to trying to maximize the margin.
  • To counterbalance that, we will get a non-zero derivative from the last terms, if the loss is non-zero. And that update looks like the perceptor update, but it is actually made even if we correctly classify the example. If the example is within the margin boundaries, you would get a non-zero loss.

An other point of view on SGD compared to a deterministic approach:

The original concern for using SGD is due to computational constraint: it is inefficient to compute the gradients over all the samples and update the model, think about you have more than a million training samples, and you can only make progress after computing all gradients. Thus, instead of compute the exact value of the gradient over the entire training data set, we randomly sample a fraction of them to estimate the true gradient. You see, there is a trade-off controlled by the batch size (number of samples used in each SGD updates), large batch size is more accurate but slower, and it need to be tuned in practice.

Nowadays, researchers start to understand SGD from a different perspective. The noise caused by SGD could make the trained more robust, (high level idea, noisy updates will make you converge to a flatter minima), which results in a better generalization performance. Thus, SGD could also be viewed as a way of regularization, in that sense, we may say it is better compared to gradient descent.

4.6. The Realizable Case — Quadratic program

Let’s consider a simple case where (a) the problem is separable and (b) we do not allow any error, i.e. we want the loss part of the objective function to be zero (that’s the meaning of «realisable case»: we set as constraint that the loss function must return zero).

The problem becomes:

$min_{(mathbf{theta}, theta_0)} frac{1}{2}||mathbf{theta}||^2$

Subject to:

$y^{(i)} * (mathbf{theta} cdot mathbf{x}^{(i)} + theta_0 ) geq 1 ~~ forall i = 1,…,n$

We want hence extend the margins as much as possible while keeping zero losses, that is until the first data pair(s) is reach (we can’t go over them otherwise we would start encoring a loss). Note that this is exactly equivalent to the minimisation of our original $J(theta)$ function when $lambda$ is very small but not zero. There the zero loss output (in case of a separable problem) is the result of the minimisation of the loss function, here is it imposed as a constraint.

This is a problem quadratic in the objective and with linear constraints, and it can be solved with so-called quadratic solvers.

Relaxing the loss constraint and incorporate the loss in the objective would still leave the problem as a quadratic one.

This case is also called maximum margin separator or hard margin SVM to distinguish it from the soft margin SVM we saw earlier where, even in cases of separable problems, we allow to trade some misclassifications for a better regularisation.

Homework 2

Project 1: Automatic Review Analyzer

Recitation 1: Tuning the Regularization Hyperparameter by Cross Validation and a Demonstration

Outline

Supervised learning: Importance to have a model
Objective: classification or regression

Cross validation: using the validation set to find the optimal parameters of our learning algorithm.

Supervised Learning

obj: derive a function $f_{est}$ that approximate the real function $f$ that link an input $x$ to an output $y$.

We started by sampling from X and corresponding y —> training dataset
We call the relation between this sampled pairs $f_{data}$

Our first obj is then to find a $f_{est}$, parametrised by some parameters $(theta,theta_0)$, that approximate this $f_{data}$.

In order to find $(theta,theta_0)$, we use an optimisation approach that minimise the function $J()$ made of a «loss» term $L(theta,theta_0;x,y)$ that describes the difference between our $f_{est}$ and $f_{data}$.

But $f_{data} neq f$. Because of that we add to our loss function a regularisation term $R(theta)$ that constraints $f_{est}$ not to be too similar to $f_{data}$ that then is no longer able to generalise to $f$.

A hyperparameter $alpha$ then balance these two terms in our function to minimise. And we remain with the task to choose this parameter, as it is not determined by the minimisation of the function as it is for $(theta,theta_0)$.
We’ll see that to find $alpha$ we will use indeed the cross validation using training data only and how choosing alpha will affect the performance of the model.

We’ll go trough cross the method of cross validation which this is actually how we find $alpha$ in practice using training data only, not the test data.

Support Vector Machine

What are the Loss and the regularisation functions for Support Vector Machines (SVM)

SVM obj: maximise the margins of the decision boundary

Distance from point $i$ to the decision boundary:

$gamma = frac{y^i * (theta cdot x^i + theta_0)}{||theta||}$ (note that this is a distance with positive sign if the point side match the label side, negative otherwise)

The margin $d$ is the minimal distance of any point with the decision boundary:

$d = min_{i} gamma(x^i, y^i, theta, theta_0)$

Large margin —> more ability of our model to generalise

Loss term

For SVM the loss term is the hinge loss $L_h$:

$L_h = fleft(frac{gamma}{gamma_{ref}} right) = begin{cases}
1-frac{gamma}{gamma_{ref}} & text{when} gamma < gamma_{ref}
0 & text{otherwise}
end{cases}$

As a function of $gamma$, the hinge loss function for each point is above 1 for negative gammas, is 1 for $gamma =1$, continue to linearly decrease up to reaching 0 when $gamma = gamma_{ref}$ and then remains zero, where $gamma_{ref}$ is indeed the margin $d$ as previously defined.

Regularisation term

The goal of the regularisation term is to make the model more generalisable.

For that, we want to maximise the margin, hence $gamma_{ref}$. As we have a minimisation problem, that is equivalent to minimise $1/gamma_{ref}$ or (as did in practice) $1/gamma_{ref}^2$.

Objective function

$J = frac{1}{n} sum_{i=1}^n L_h(frac{gamma_i}{gamma_{ref}})+alpha * frac{1}{gamma_{ref}^2}$

We now are left to define what $gamma_{ref}$ is in terms of $(theta,theta_0)$.

Maximum margin

Note that we can scale $theta$ by any constant (i.e. change it’s magnitude) without changing the decision boundary (obviously also $theta_0$ will be rescaled).

In particular, we can scale $theta$ such that $y^m (theta cdot x^m + theta_zero) = 1$, where $m$ denotes the point at the minimum distance with the decision boundary.

In such case $theta_{ref}$ simply becomes $frac{1}{||theta||}.

The objective function becomes the one we saw in the lecture:

$J = frac{1}{n} sum_{i=1}^n L_h($y^i (theta cdot x^i + theta_0))+alpha * ||theta||^2$

Note that the regularisation term is a function of $theta$ alone.

Testing and Training Error as Regularization Increases

We will now see how different values of alpha affect the performance of the model.

Our objective function is

$J = L_(theta,theta_0,x_{data},y_{data})+alpha R(theta)$

At $alpha = 0$, the obj model becomes just the loss model, and our functions should approximate very well $f_{data}$, the relation between training data and training outputs.

Accuracy is defined as $1/J$, as we are trying to minimise $J$.

As we increase $alpha$, $J$ increases and the accuracy reduces.

What about the J function as computed from the testing dataset? As $alpha$ increases it first reduce, as the model is gaining generability, but then it start back to increases as the model becomes too much general. The opposite for its accuracy.

There is indeed a value $alpha^* ~$ for which indeed the $J$ function under the testing set is minimised (accuracy is maximised).

And what’t the $alpha$ that we want to use. How do we find it with only training set data ? (we can’t use testing data, as we don’t yet have that data). The method is «cross validation» (next video).

Cross Validation

We want to find $alpha^* ~$.
We just split our training data in a «new» training data, and a «validation set» to act as the «test set» and fine tune our $alpha$ hyperparameter.

We start to discretize our hyperparameter in a number of $K$ values to test (there are many ways to do that.. ex-ante using a homogeneous grid or sampling approach, or updating the values to test as we have the results of the first $alpha$ we tested..)

We then divide our training data in $n$ partitions (where n depends on the data available), and, for each $alpha_k$, we choose one of that n partitions to be the «validation set»: we minimise the $J$ function using $alpha_k$ and the remaining $(n-1)$ partitions, and we compute the accuracy $S_n(alpha_k)$ for the validation set.

We then compute the average accuracy for $alpha_k$: $S(alpha_k) = frac{1}{n} sum_{i=1}^n S_n(alpha_k)$.

Finally we «choose» the $alpha^* ~$ with the lowest $S(alpha_k)$.

Tumor Diagnosis Demo

  • Python code
  • Julia code

In this demo we found the best value of alpha in a SVM model that links breast cancer characteristics (such as cancer texture or size) with its benign/malign nature.

The example use sikit-learn, a library that allows to train your own machine learning algorithm (linear SVM in our case).

We use the function linear_model.SGDClassifier(loss='hinge', penalty='l2', alpha=alpha[i]) that set up a SVM model using gradient descendent algorithm on hinge loss, using the L2 norm as regularisation term («penalty») and the specific $alpha$ we want to test.

We then use ms.cross_val_score(model, X, y, cv=5) to actually train the model on the training set divided in 5 different partitions. The function return already an array of the scores of the remaining validation partition.
To compute the score for that particular alpha we now need just to average the score array obtained by that function.

[MITx 6.86x Notes Index]

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Обучение искусственной нейронной сети методом обратного распространения ошибки
  • Обучающий фильм обрезка формировка ошибки советы при выращивании винограда