Глава 5. Базовая практика
До сих пор я лишь вскользь упоминал некоторые вопросы, которые аналитику данных необходимо учитывать при работе над проблемой машинного обучения: инженерия признаков, переобучение и настройка гиперпараметров. В этой главе мы поговорим об этих и других проблемах, которые необходимо решить, прежде чем вы сможете набрать model = LogisticRegression().fit(x,y)
в scikit-learn.
5.1 Инженерия признаков
Когда менеджер по продукту говорит вам: «Нам нужно предсказать, останется ли конкретный клиент с нами. Вот журналы взаимодействия клиентов с нашим продуктом за пять лет», вы не можете просто взять данные, загрузить их в библиотеку и получить предсказание. Сначала нужно построить набор данных (dataset).
Помните из первой главы, что набор данных — это коллекция размеченных примеров \({(x_i, y_i)}_{i=1}^N\). Каждый элемент \(x_i\) среди \(N\) называется вектором признаков. Вектор признаков — это вектор, в котором каждое измерение \(j = 1, \dots, D\) содержит значение, которое каким-то образом описывает пример. Это значение называется признаком и обозначается как \(x^{(j)}\).
Проблема преобразования необработанных данных в набор данных называется инженерией признаков (feature engineering). Для большинства практических задач инженерия признаков — это трудоемкий процесс, который требует от аналитика данных большой креативности и, желательно, знаний в предметной области.
Например, для преобразования журналов взаимодействия пользователя с компьютерной системой можно создать признаки, содержащие информацию о пользователе и различные статистики, извлеченные из журналов. Для каждого пользователя один признак может содержать цену подписки; другие признаки могут содержать частоту подключений в день, неделю и год. Другой признак может содержать среднюю продолжительность сеанса в секундах или среднее время ответа на один запрос и так далее. Все, что можно измерить, может быть использовано в качестве признака. Роль аналитика данных заключается в создании информативных признаков: тех, которые позволят алгоритму обучения построить модель, хорошо предсказывающую метки данных, использованных для обучения. Высокоинформативные признаки также называются признаками с высокой предсказательной силой (predictive power). Например, средняя продолжительность сеанса пользователя имеет высокую предсказательную силу для проблемы предсказания того, будет ли пользователь продолжать использовать приложение в будущем.
Мы говорим, что модель имеет низкое смещение (low bias), когда она хорошо предсказывает обучающие данные. То есть модель делает мало ошибок, когда мы используем ее для предсказания меток примеров, использованных для построения модели.
5.1.1 One-Hot кодирование
Некоторые алгоритмы обучения работают только с числовыми векторами признаков. Когда некоторый признак в вашем наборе данных является категориальным, например «цвета» или «дни недели», вы можете преобразовать такой категориальный признак в несколько бинарных.
Если ваш пример имеет категориальный признак «цвета» и этот признак имеет три возможных значения: «красный», «желтый», «зеленый», вы можете преобразовать этот признак в вектор из трех числовых значений:
красный = [1, 0, 0] желтый = [0, 1, 0] зеленый = [0, 0, 1] (1)
Таким образом, вы увеличиваете размерность ваших векторов признаков. Вам не следует преобразовывать красный в 1, желтый в 2 и зеленый в 3, чтобы избежать увеличения размерности, потому что это подразумевало бы, что существует порядок среди значений в этой категории, и этот конкретный порядок важен для принятия решений. Если порядок значений признака не важен, использование упорядоченных чисел в качестве значений, скорее всего, запутает алгоритм обучения1, потому что алгоритм будет пытаться найти закономерность там, где ее нет, что потенциально может привести к переобучению.
5.1.2 Биннинг
Противоположная ситуация, встречающаяся на практике реже, — это когда у вас есть числовой признак, но вы хотите преобразовать его в категориальный. Биннинг (Binning) (также называемый группировкой (bucketing)) — это процесс преобразования непрерывного признака в несколько бинарных признаков, называемых бинами или бакетами, обычно на основе диапазона значений. Например, вместо представления возраста как одного вещественного признака, аналитик может разбить диапазоны возраста на дискретные бины: все возрасты от 0 до 5 лет могут быть помещены в один бин, от 6 до 10 лет — во второй бин, от 11 до 15 лет — в третий бин и так далее.
Пусть признак \(j = 4\) представляет возраст. Применив биннинг, мы заменяем этот признак соответствующими бинами. Пусть три новых бина, «age_bin1», «age_bin2» и «age_bin3», будут добавлены с индексами \(j = 123\), \(j = 124\) и \(j = 125\) соответственно (по умолчанию значения этих трех новых признаков равны 0). Теперь, если \(x_i^{(4)} = 7\) для некоторого примера \(x_i\), то мы устанавливаем признак \(x_i^{(124)}\) в 1; если \(x_i^{(4)} = 13\), то мы устанавливаем признак \(x_i^{(125)}\) в 1 и так далее.
В некоторых случаях тщательно разработанный биннинг может помочь алгоритму обучения обучиться на меньшем количестве примеров. Это происходит потому, что мы даем «подсказку» алгоритму обучения, что если значение признака попадает в определенный диапазон, точное значение признака не имеет значения.
5.1.3 Нормализация
Нормализация (Normalization) — это процесс преобразования фактического диапазона значений, которые может принимать числовой признак, в стандартный диапазон значений, обычно в интервал \([-1, 1]\) или \([0, 1]\).
Например, предположим, что естественный диапазон конкретного признака составляет от 350 до 1450. Вычитая 350 из каждого значения признака и деля результат на 1100, можно нормализовать эти значения в диапазон \([0, 1]\).
В более общем виде формула нормализации выглядит так:
\[ \bar{x}^{(j)} = \frac{x^{(j)} - \min^{(j)}}{\max^{(j)} - \min^{(j)}}, \]где \(\min^{(j)}\) и \(\max^{(j)}\) — это, соответственно, минимальное и максимальное значение признака \(j\) в наборе данных.
Зачем мы нормализуем? Нормализация данных не является строгим требованием. Однако на практике это может привести к увеличению скорости обучения. Вспомните пример градиентного спуска из предыдущей главы. Представьте, что у вас есть двумерный вектор признаков. Когда вы обновляете параметры \(w^{(1)}\) и \(w^{(2)}\), вы используете частные производные среднеквадратичной ошибки по \(w^{(1)}\) и \(w^{(2)}\). Если \(x^{(1)}\) находится в диапазоне \([0, 1000]\), а \(x^{(2)}\) — в диапазоне \([0, 0.0001]\), то производная по большему признаку будет доминировать в обновлении.
Кроме того, полезно убедиться, что наши входы находятся примерно в одном и том же относительно небольшом диапазоне, чтобы избежать проблем, которые возникают у компьютеров при работе с очень малыми или очень большими числами (известных как числовое переполнение (numerical overflow)).
5.1.4 Стандартизация
Стандартизация (Standardization) (или нормализация z-оценки) — это процедура, в ходе которой значения признаков масштабируются таким образом, чтобы они имели свойства стандартного нормального распределения с \(\mu = 0\) и \(\sigma = 1\), где \(\mu\) — среднее (среднее значение признака, усредненное по всем примерам в наборе данных), а \(\sigma\) — стандартное отклонение от среднего.
Стандартные оценки (или z-оценки) признаков вычисляются следующим образом:
\[ \hat{x}^{(j)} = \frac{x^{(j)} - \mu^{(j)}}{\sigma^{(j)}}. \]Вы можете спросить, когда следует использовать нормализацию, а когда стандартизацию. Однозначного ответа на этот вопрос нет. Обычно, если ваш набор данных не слишком велик и у вас есть время, вы можете попробовать оба варианта и посмотреть, какой из них работает лучше для вашей задачи.
Если у вас нет времени на проведение множества экспериментов, в качестве эмпирического правила:
- алгоритмы обучения без учителя на практике чаще выигрывают от стандартизации, чем от нормализации;
- стандартизация также предпочтительна для признака, если значения, которые он принимает, распределены близко к нормальному распределению (так называемая колоколообразная кривая);
- опять же, стандартизация предпочтительна для признака, если он иногда может иметь чрезвычайно высокие или низкие значения (выбросы); это связано с тем, что нормализация «сожмет» нормальные значения в очень малый диапазон;
- во всех остальных случаях предпочтительна нормализация.
Масштабирование признаков обычно полезно для большинства алгоритмов обучения. Однако современные реализации алгоритмов обучения, которые можно найти в популярных библиотеках, устойчивы к признакам, лежащим в разных диапазонах.
5.1.5 Работа с пропущенными признаками
В некоторых случаях данные поступают к аналитику в виде набора данных с уже определенными признаками. В некоторых примерах значения некоторых признаков могут отсутствовать. Это часто случается, когда набор данных создавался вручную, и человек, работавший над ним, забыл заполнить некоторые значения или не измерил их.
Типичные подходы к работе с пропущенными значениями для признака включают:
- удаление примеров с пропущенными признаками из набора данных (это можно сделать, если ваш набор данных достаточно велик, чтобы вы могли пожертвовать некоторыми обучающими примерами);
- использование алгоритма обучения, который может работать с пропущенными значениями признаков (зависит от библиотеки и конкретной реализации алгоритма);
- использование техники заполнения данных (data imputation).
5.1.6 Техники заполнения данных
Одна из техник заполнения данных заключается в замене пропущенного значения признака средним значением этого признака в наборе данных:
\[ \hat{x}^{(j)} \leftarrow \frac{1}{M} \sum_{i=1}^N x_i^{(j)}, \]где \(M < N\) — количество примеров, в которых значение признака \(j\) присутствует, а суммирование исключает примеры, в которых значение признака \(j\) отсутствует.
Другая техника заключается в замене пропущенного значения значением, выходящим за пределы нормального диапазона значений. Например, если нормальный диапазон \([0, 1]\), то вы можете установить пропущенное значение равным 2 или -1. Идея заключается в том, что алгоритм обучения научится, что лучше всего делать, когда признак имеет значение, значительно отличающееся от обычных значений. В качестве альтернативы вы можете заменить пропущенное значение значением в середине диапазона. Например, если диапазон для признака \([-1, 1]\),
вы можете установить пропущенное значение равным 0. Здесь идея заключается в том, что значение в середине диапазона не окажет существенного влияния на предсказание.
Более продвинутая техника заключается в использовании пропущенного значения в качестве целевой переменной для задачи регрессии. Вы можете использовать все оставшиеся признаки \([x_i^{(1)}, x_i^{(2)}, \dots, x_i^{(j-1)}, x_i^{(j+1)}, \dots, x_i^{(D)}]\), чтобы сформировать вектор признаков \(\hat{x}_i\), установить \(\hat{y}_i \leftarrow x_i^{(j)}\), где \(j\) — это признак с пропущенным значением. Затем вы строите модель регрессии для предсказания \(\hat{y}\) по \(\hat{x}\). Конечно, для построения обучающих примеров \((\hat{x}, \hat{y})\) вы используете только те примеры из исходного набора данных, в которых значение признака \(j\) присутствует.
Наконец, если у вас значительно большой набор данных и всего несколько признаков с пропущенными значениями, вы можете увеличить размерность ваших векторов признаков, добавив бинарный индикаторный признак для каждого признака с пропущенными значениями. Допустим, признак \(j = 12\) в вашем \(D\)-мерном наборе данных имеет пропущенные значения. Для каждого вектора признаков \(x\) вы затем добавляете признак \(j = D + 1\), который равен 1, если значение признака 12 присутствует в \(x\), и 0 в противном случае. Пропущенное значение признака затем можно заменить на 0 или любое число по вашему выбору.
Во время предсказания, если ваш пример неполный, вы должны использовать ту же технику заполнения данных для заполнения пропущенных признаков, что и техника, которую вы использовали для заполнения обучающих данных.
Прежде чем приступить к работе над проблемой обучения, вы не можете сказать, какая техника заполнения данных сработает лучше всего. Попробуйте несколько техник, постройте несколько моделей и выберите ту, которая работает лучше всего.
5.2 Выбор алгоритма обучения
Выбор алгоритма машинного обучения может быть сложной задачей. Если у вас много времени, вы можете попробовать все. Однако обычно время на решение проблемы ограничено. Вы можете задать себе несколько вопросов, прежде чем приступить к работе над проблемой. В зависимости от ваших ответов, вы можете сузить список некоторых алгоритмов и попробовать их на своих данных.
- Объяснимость
Должна ли ваша модель быть объяснимой для нетехнической аудитории? Большинство очень точных алгоритмов обучения являются так называемыми «черными ящиками». Они изучают модели, которые делают очень мало ошибок, но почему модель сделала конкретное предсказание, может быть очень трудно понять и еще труднее объяснить. Примерами таких моделей являются нейронные сети или ансамблевые модели.
С другой стороны, kNN, линейная регрессия или алгоритмы обучения деревьев решений создают модели, которые не всегда являются самыми точными, однако способ, которым они делают свои предсказания, очень прост.
- В памяти vs. вне памяти
Может ли ваш набор данных быть полностью загружен в ОЗУ вашего сервера или персонального компьютера? Если да, то вы можете выбирать из широкого спектра алгоритмов. В противном случае вы предпочтете инкрементные алгоритмы обучения, которые могут улучшать модель, постепенно добавляя больше данных.
- Количество признаков и примеров
Сколько обучающих примеров у вас в наборе данных? Сколько признаков имеет каждый пример? Некоторые алгоритмы, включая нейронные сети и градиентный бустинг (мы рассмотрим оба позже), могут обрабатывать огромное количество примеров и миллионы признаков. Другие, такие как SVM, могут быть очень скромными в своей производительности.
- Категориальные vs. числовые признаки
Состоят ли ваши данные только из категориальных, только из числовых признаков или из их смеси? В зависимости от вашего ответа, некоторые алгоритмы не могут напрямую обрабатывать ваш набор данных, и вам потребуется преобразовать ваши категориальные признаки в числовые.
- Нелинейность данных
Являются ли ваши данные линейно разделимыми или могут быть смоделированы с использованием линейной модели? Если да, то SVM с линейным ядром, логистическая или линейная регрессия могут быть хорошим выбором. В противном случае могут лучше работать глубокие нейронные сети или ансамблевые алгоритмы, обсуждаемые в Главах 6 и 7.
- Скорость обучения
Сколько времени разрешено алгоритму обучения для построения модели? Нейронные сети известны тем, что обучаются медленно. Простые алгоритмы, такие как логистическая и линейная регрессия или деревья решений, намного быстрее. Специализированные библиотеки содержат очень эффективные реализации некоторых алгоритмов; вы можете предпочесть провести онлайн-исследование, чтобы найти такие библиотеки. Некоторые алгоритмы, такие как случайные леса, выигрывают от наличия нескольких ядер ЦП, поэтому время построения их модели может быть значительно сокращено на машине с десятками ядер.
- Скорость предсказания
Насколько быстрой должна быть модель при генерации предсказаний? Будет ли ваша модель использоваться в производственной среде, где требуется очень высокая пропускная способность? Алгоритмы, такие как SVM, линейная и логистическая регрессия, и (некоторые типы) нейронных сетей, чрезвычайно быстры во время предсказания. Другие, такие как kNN, ансамблевые алгоритмы и очень глубокие или рекуррентные нейронные сети, медленнее2.
Если вы не хотите угадывать лучший алгоритм для ваших данных, популярный способ выбрать один — это протестировать его на валидационном наборе (validation set). Мы поговорим об этом ниже. В качестве альтернативы, если вы используете scikit-learn, вы можете попробовать их диаграмму выбора алгоритма, показанную на Рисунке 1 (в pdf).
5.3 Три набора
До сих пор я использовал выражения «набор данных» и «обучающий набор» взаимозаменяемо. Однако на практике аналитики данных работают с тремя различными наборами размеченных примеров:
- обучающий набор (training set),
- валидационный набор (validation set), и
- тестовый набор (test set).
Как только вы получили свой аннотированный набор данных, первое, что вы делаете, это перемешиваете примеры и разделяете набор данных на три подмножества: обучающее, валидационное и тестовое. Обучающий набор обычно самый большой; вы используете его для построения модели. Валидационный и тестовый наборы примерно одинакового размера, намного меньше размера обучающего набора. Алгоритм обучения не может использовать примеры из этих двух подмножеств для построения модели. Вот почему эти два набора часто называют отложенными наборами (holdout sets).
Нет оптимальной пропорции для разделения набора данных на эти три подмножества. В прошлом эмпирическое правило заключалось в использовании 70% набора данных для обучения, 15% для валидации и 15% для тестирования. Однако в эпоху больших данных наборы данных часто содержат миллионы примеров. В таких случаях может быть разумно оставить 95% для обучения и 2.5%/2.5% для валидации/тестирования.
Вы можете задаться вопросом, зачем иметь три набора, а не один. Ответ прост: когда мы строим модель, мы не хотим, чтобы модель хорошо предсказывала только метки примеров, которые алгоритм обучения уже видел. Тривиальный алгоритм, который просто запоминает все обучающие примеры, а затем использует память для «предсказания» их меток, не сделает ошибок при предсказании меток обучающих примеров, но такой алгоритм был бы бесполезен на практике. Что нам действительно нужно, так это модель, которая хорошо предсказывает примеры, которые алгоритм обучения не видел: нам нужна хорошая производительность на отложенном наборе.
Зачем нам два отложенных набора, а не один? Мы используем валидационный набор для 1) выбора алгоритма обучения и 2) нахождения наилучших значений гиперпараметров. Мы используем тестовый набор для оценки модели перед ее передачей клиенту или внедрением в производство.
5.4 Недообучение и переобучение
Выше я упомянул понятие смещения (bias). Я сказал, что модель имеет низкое смещение, если она хорошо предсказывает метки обучающих данных. Если модель делает много ошибок на обучающих данных, мы говорим, что модель имеет высокое смещение (high bias) или что модель недообучается (underfits). Таким образом, недообучение (underfitting) — это неспособность модели хорошо предсказывать метки данных, на которых она была обучена. Может быть несколько причин недообучения, наиболее важными из которых являются:
- ваша модель слишком проста для данных (например, линейная модель часто может недообучаться);
- признаки, которые вы спроектировали, недостаточно информативны.
Первую причину легко проиллюстрировать на примере одномерной регрессии: набор данных может напоминать кривую линию, но наша модель — прямая линия. Вторую причину можно проиллюстрировать так: допустим, вы хотите предсказать, есть ли у пациента рак, и признаки, которые у вас есть, — это рост, артериальное давление и частота сердечных сокращений. Эти три признака явно не являются хорошими предикторами рака, поэтому наша модель не сможет изучить значимую взаимосвязь между этими признаками и меткой.
Решение проблемы недообучения заключается в том, чтобы попробовать более сложную модель или спроектировать признаки с более высокой предсказательной силой.
Переобучение (Overfitting) — это другая проблема, которую может демонстрировать модель. Модель, которая переобучается, очень хорошо предсказывает обучающие данные, но плохо предсказывает данные как минимум из одного из двух отложенных наборов. Я уже приводил иллюстрацию переобучения в Главе 3. К переобучению могут привести несколько причин, наиболее важными из которых являются:
- ваша модель слишком сложна для данных (например, очень высокое дерево решений или очень глубокая или широкая нейронная сеть часто переобучаются);
- у вас слишком много признаков, но мало обучающих примеров.
В литературе вы можете найти другое название проблемы переобучения: проблема высокой дисперсии (high variance). Этот термин происходит из статистики. Дисперсия — это ошибка модели из-за ее чувствительности к малым флуктуациям в обучающем наборе. Это означает, что если бы ваши обучающие данные были отобраны по-другому, обучение привело бы к значительно отличающейся модели. Вот почему модель, которая переобучается, плохо работает на тестовых данных: тестовые и обучающие данные отбираются из набора данных независимо друг от друга.
Даже самая простая модель, такая как линейная, может переобучаться. Это обычно происходит, когда данные имеют высокую размерность, но количество обучающих примеров относительно мало. Фактически, когда векторы признаков имеют очень высокую размерность, линейный алгоритм обучения может построить модель, которая присваивает ненулевые значения большинству параметров \(w^{(j)}\) в векторе параметров \(w\), пытаясь найти очень сложные взаимосвязи между всеми доступными признаками для идеального предсказания меток обучающих примеров.
Такая сложная модель, скорее всего, будет плохо предсказывать метки отложенных примеров. Это связано с тем, что, пытаясь идеально предсказать метки всех обучающих примеров, модель также изучит идиосинкразии обучающего набора: шум в значениях признаков обучающих примеров, несовершенство выборки из-за малого размера набора данных и другие артефакты, не относящиеся к решаемой проблеме, но присутствующие в обучающем наборе.
Рисунок 2 (в pdf) иллюстрирует одномерный набор данных, для которого модель регрессии недообучается, хорошо подходит и переобучается.
Возможны несколько решений проблемы переобучения:
- Попробуйте более простую модель (линейную вместо полиномиальной регрессии, или SVM с линейным ядром вместо RBF, нейронную сеть с меньшим количеством слоев/блоков).
- Уменьшите размерность примеров в наборе данных (например, используя одну из техник снижения размерности, обсуждаемых в Главе 9).
- Добавьте больше обучающих данных, если это возможно.
- Регуляризуйте модель.
Регуляризация (Regularization) — это наиболее широко используемый подход для предотвращения переобучения.
5.5 Регуляризация
Регуляризация — это общий термин, который охватывает методы, заставляющие алгоритм обучения строить менее сложную модель. На практике это часто приводит к немного более высокому смещению, но значительно снижает дисперсию. Эта проблема известна в литературе как компромисс смещения-дисперсии (bias-variance tradeoff).
Два наиболее широко используемых типа регуляризации называются L1 и L2 регуляризацией. Идея довольно проста. Чтобы создать регуляризованную модель, мы изменяем целевую функцию, добавляя штрафной член, значение которого выше, когда модель более сложная.
Для простоты я иллюстрирую регуляризацию на примере линейной регрессии. Тот же принцип может быть применен к широкому спектру моделей.
Вспомним цель линейной регрессии:
\[ \min_{w,b} \frac{1}{N} \sum_{i=1}^N (f_{w,b}(x_i) - y_i)^2. \quad (2) \]Цель с L1-регуляризацией выглядит так:
\[ \min_{w,b} \left[ C|w| + \frac{1}{N} \sum_{i=1}^N (f_{w,b}(x_i) - y_i)^2 \right], \quad (3) \]где \(|w| \stackrel{\text{def}}{=} \sum_{j=1}^D |w^{(j)}|\), а \(C\) — гиперпараметр, который контролирует важность регуляризации. Если мы установим \(C\) в ноль, модель станет стандартной нерегуляризованной моделью линейной регрессии. С другой стороны, если мы установим \(C\) в высокое значение, алгоритм обучения попытается установить большинство \(w^{(j)}\) в очень малое значение или ноль, чтобы минимизировать цель, и модель станет очень простой, что может привести к недообучению. Ваша роль как аналитика данных заключается в том, чтобы найти такое значение гиперпараметра \(C\), которое не слишком увеличивает смещение, но снижает
дисперсию до уровня, разумного для решаемой задачи. В следующем разделе я покажу, как это сделать.
Цель с L2-регуляризацией выглядит так:
\[ \min_{w,b} \left[ C\|w\|^2 + \frac{1}{N} \sum_{i=1}^N (f_{w,b}(x_i) - y_i)^2 \right], \quad \text{где } \|w\|^2 \stackrel{\text{def}}{=} \sum_{j=1}^D (w^{(j)})^2. \quad (4) \]На практике L1-регуляризация создает разреженную модель (sparse model), модель, у которой большинство параметров (в случае линейных моделей, большинство \(w^{(j)}\)) равны нулю, при условии, что гиперпараметр \(C\) достаточно велик. Таким образом, L1 выполняет отбор признаков (feature selection), решая, какие признаки важны для предсказания, а какие нет. Это может быть полезно в случае, если вы хотите повысить объяснимость модели. Однако, если ваша единственная цель — максимизировать производительность модели на отложенных данных, то L2 обычно дает лучшие результаты. L2 также имеет преимущество в том, что она дифференцируема, поэтому для оптимизации целевой функции можно использовать градиентный спуск.
Методы L1 и L2 регуляризации также были объединены в так называемую регуляризацию эластичной сети (elastic net regularization), при этом L1 и L2 регуляризации являются частными случаями. В литературе вы можете найти название гребневая регуляризация (ridge regularization) для L2 и лассо (lasso) для L1.
В дополнение к широкому использованию с линейными моделями, L1 и L2 регуляризация также часто используются с нейронными сетями и многими другими типами моделей, которые напрямую минимизируют целевую функцию.
Нейронные сети также выигрывают от двух других техник регуляризации: dropout и пакетной нормализации (batch-normalization). Существуют также нематематические методы, которые имеют эффект регуляризации: аугментация данных (data augmentation) и ранняя остановка (early stopping). Мы поговорим об этих техниках в Главе 8.
5.6 Оценка производительности модели
Как только у вас есть модель, которую ваш алгоритм обучения построил, используя обучающий набор, как вы можете сказать, насколько хороша модель? Вы используете тестовый набор для оценки модели.
Тестовый набор содержит примеры, которые алгоритм обучения никогда не видел раньше, поэтому если наша модель хорошо справляется с предсказанием меток примеров из тестового набора, мы говорим, что наша модель хорошо обобщает (generalizes) или, проще говоря, что она хорошая (good).
Чтобы быть более строгими, специалисты по машинному обучению используют различные формальные метрики и инструменты для оценки производительности модели. Для регрессии оценка модели довольно проста. Хорошо подогнанная модель регрессии приводит к предсказанным значениям, близким к наблюдаемым значениям данных. Средняя модель (mean model), которая всегда предсказывает среднее значение меток в обучающих данных, обычно использовалась бы, если бы не было информативных признаков. Подгонка оцениваемой модели регрессии должна, следовательно, быть лучше, чем подгонка средней модели. Если это так, то следующим шагом является сравнение производительности модели на обучающих и тестовых данных.
Для этого мы вычисляем среднеквадратичную ошибку3 (MSE) для обучающих и, отдельно, для тестовых данных. Если MSE модели на тестовых данных существенно выше, чем MSE, полученная на обучающих данных, это признак переобучения. Регуляризация или лучшая настройка гиперпараметров могут решить проблему. Значение «существенно выше» зависит от конкретной задачи и должно определяться аналитиком данных совместно с лицом, принимающим решения/владельцем продукта, который заказал модель.
Для классификации все немного сложнее. Наиболее широко используемые метрики и инструменты для оценки модели классификации:
- матрица ошибок (confusion matrix),
- точность (accuracy),
- точность с учетом стоимости (cost-sensitive accuracy),
- точность/полнота (precision/recall), и
- площадь под ROC-кривой (area under the ROC curve).
Для упрощения иллюстрации я использую задачу бинарной классификации. При необходимости я покажу, как расширить подход на многоклассовый случай.
5.6.1 Матрица ошибок
Матрица ошибок (confusion matrix) — это таблица, которая суммирует, насколько успешно модель классификации предсказывает примеры, принадлежащие к различным классам. Одна ось матрицы ошибок — это метка, которую предсказала модель, а другая ось — это фактическая метка. В задаче бинарной классификации есть два класса. Допустим, модель предсказывает два класса: «спам» и «не спам»:
спам (предсказано) | не спам (предсказано) | |
---|---|---|
спам (факт) | 23 (TP) | 1 (FN) |
не спам (факт) | 12 (FP) | 556 (TN) |
Приведенная выше матрица ошибок показывает, что из 24 примеров, которые на самом деле были спамом, модель правильно классифицировала 23 как спам. В этом случае мы говорим, что у нас 23 истинно положительных (true positives) или TP = 23. Модель неправильно классифицировала 1 пример как не спам. В этом случае у нас 1 ложноотрицательный (false negative), или FN = 1. Аналогично, из 568 примеров, которые на самом деле не были спамом, 556 были правильно классифицированы (556 истинно отрицательных (true negatives) или TN = 556), а 12 были неправильно классифицированы (12 ложноположительных (false positives), FP = 12).
Матрица ошибок для многоклассовой классификации имеет столько же строк и столбцов, сколько существует различных классов. Она может помочь вам определить закономерности ошибок. Например, матрица ошибок может выявить, что модель, обученная распознавать различные виды животных, склонна ошибочно предсказывать «кошка» вместо «пантера» или «мышь» вместо «крыса». В этом случае вы
можете решить добавить больше размеченных примеров этих видов, чтобы помочь алгоритму обучения «увидеть» разницу между ними. В качестве альтернативы вы можете добавить дополнительные признаки, которые алгоритм обучения может использовать для построения модели, которая лучше различала бы эти виды.
Матрица ошибок используется для вычисления двух других метрик производительности: точности (precision) и полноты (recall).
5.6.2 Точность/Полнота
Двумя наиболее часто используемыми метриками для оценки модели являются точность и полнота. Точность — это отношение правильных положительных предсказаний к общему числу положительных предсказаний:
\[ \text{precision} \stackrel{\text{def}}{=} \frac{\text{TP}}{\text{TP} + \text{FP}}. \]Полнота — это отношение правильных положительных предсказаний к общему числу положительных примеров в наборе данных:
\[ \text{recall} \stackrel{\text{def}}{=} \frac{\text{TP}}{\text{TP} + \text{FN}}. \]Чтобы понять значение и важность точности и полноты для оценки модели, часто полезно думать о задаче предсказания как о задаче поиска документов в базе данных по запросу. Точность — это доля релевантных документов в списке всех возвращенных документов. Полнота — это отношение релевантных документов, возвращенных поисковой системой, к общему числу релевантных документов, которые могли бы быть возвращены.
В случае проблемы обнаружения спама мы хотим иметь высокую точность (мы хотим избежать ошибок, обнаруживая, что законное сообщение является спамом), и мы готовы мириться с более низкой полнотой (мы терпим некоторые спам-сообщения в нашем почтовом ящике).
Почти всегда на практике нам приходится выбирать между высокой точностью или высокой полнотой. Обычно невозможно иметь и то, и другое. Мы можем достичь одного из двух различными способами:
- присваивая более высокий вес примерам определенного класса (алгоритм SVM принимает веса классов в качестве входных данных);
- настраивая гиперпараметры для максимизации точности или полноты на валидационном наборе;
- изменяя порог принятия решения для алгоритмов, которые возвращают вероятности классов; например, если мы используем логистическую регрессию или дерево решений, чтобы увеличить точность (ценой более низкой полноты), мы можем решить, что предсказание будет положительным, только если вероятность, возвращенная моделью, выше 0.9.
Даже если точность и полнота определены для случая бинарной классификации, вы всегда можете использовать их для оценки модели многоклассовой классификации. Для этого сначала выберите класс, для которого вы
хотите оценить эти метрики. Затем вы рассматриваете все примеры выбранного класса как положительные, а все примеры остальных классов как отрицательные.
5.6.3 Точность (Accuracy)
Точность (Accuracy) задается числом правильно классифицированных примеров, деленным на общее число классифицированных примеров. В терминах матрицы ошибок она задается:
\[ \text{accuracy} \stackrel{\text{def}}{=} \frac{\text{TP} + \text{TN}}{\text{TP} + \text{TN} + \text{FP} + \text{FN}}. \quad (5) \]Точность является полезной метрикой, когда ошибки при предсказании всех классов одинаково важны. В случае спам/не спам это может быть не так. Например, вы будете меньше терпимы к ложноположительным результатам, чем к ложноотрицательным. Ложноположительный результат при обнаружении спама — это ситуация, когда ваш друг отправляет вам электронное письмо, но модель помечает его как спам и не показывает вам. С другой стороны, ложноотрицательный результат — меньшая проблема: если ваша модель не обнаруживает небольшой процент спам-сообщений, это не страшно.
5.6.4 Точность с учетом стоимости
Для работы с ситуацией, когда разные классы имеют разную важность, полезной метрикой является точность с учетом стоимости (cost-sensitive accuracy). Чтобы вычислить точность с учетом стоимости, вы сначала присваиваете стоимость (положительное число) обоим типам ошибок: FP и FN. Затем вы вычисляете количества TP, TN, FP, FN как обычно и умножаете количества для FP и FN на соответствующую стоимость перед вычислением точности с использованием ур. 5.
5.6.5 Площадь под ROC-кривой (AUC)
ROC-кривая (расшифровывается как «receiver operating characteristic»; термин пришел из радиолокации) является широко используемым методом оценки производительности моделей классификации. ROC-кривые используют комбинацию доли истинно положительных результатов (true positive rate) (определяемой точно так же, как полнота) и доли ложноположительных результатов (false positive rate) (доли отрицательных примеров, предсказанных неверно) для построения сводной картины производительности классификации.
Доля истинно положительных результатов (TPR) и доля ложноположительных результатов (FPR) определяются соответственно как,
\[ \text{TPR} \stackrel{\text{def}}{=} \frac{\text{TP}}{\text{TP} + \text{FN}} \quad \text{и} \quad \text{FPR} \stackrel{\text{def}}{=} \frac{\text{FP}}{\text{FP} + \text{TN}}. \]ROC-кривые могут использоваться только для оценки классификаторов, которые возвращают некоторую оценку уверенности (или вероятность) предсказания. Например, логистическая регрессия, нейронные сети и деревья решений (и ансамблевые модели на основе деревьев решений) могут быть оценены с использованием ROC-кривых.
Чтобы построить ROC-кривую, вы сначала дискретизируете диапазон оценки уверенности. Если этот диапазон для модели равен \([0, 1]\), то вы можете дискретизировать его так: \([0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]\). Затем вы используете каждое дискретное значение в качестве порога предсказания и предсказываете метки примеров в вашем наборе данных, используя модель и этот порог. Например, если вы хотите вычислить TPR и FPR для порога, равного 0.7, вы применяете модель к каждому примеру, получаете оценку, и, если оценка выше или равна 0.7, вы предсказываете положительный класс; в противном случае вы предсказываете отрицательный класс.
Посмотрите на иллюстрацию на Рисунке 3 (в pdf). Легко видеть, что если порог равен 0, все наши предсказания будут положительными, поэтому и TPR, и FPR будут равны 1 (верхний правый угол). С другой стороны, если порог равен 1, то ни одно положительное предсказание не будет сделано, и TPR, и FPR будут равны 0, что соответствует нижнему левому углу.
Чем выше площадь под ROC-кривой (AUC), тем лучше классификатор. Классификатор с AUC выше 0.5 лучше, чем случайный классификатор. Если AUC ниже 0.5, то что-то не так с вашей моделью. Идеальный классификатор имел бы AUC, равный 1. Обычно, если ваша модель ведет себя хорошо, вы получаете хороший классификатор, выбирая значение порога, которое дает TPR близко к 1, сохраняя FPR близко к 0.
ROC-кривые популярны, потому что они относительно просты для понимания, они охватывают более одного аспекта классификации (учитывая как ложноположительные, так и ложноотрицательные результаты) и позволяют визуально и с малыми усилиями сравнивать производительность различных моделей.
5.7 Настройка гиперпараметров
Когда я представлял алгоритмы обучения, я упоминал, что вы как аналитик данных должны выбрать хорошие значения для гиперпараметров алгоритма, таких как \(\epsilon\) и \(d\) для ID3, \(C\) для SVM или \(\alpha\)
для градиентного спуска. Но что это значит? Какое значение является наилучшим и как его найти? В этом разделе я отвечаю на эти важные вопросы.
Как вы уже знаете, гиперпараметры не оптимизируются самим алгоритмом обучения. Аналитик данных должен «настроить» гиперпараметры, экспериментально найдя наилучшую комбинацию значений, по одному на каждый гиперпараметр.
Один типичный способ сделать это, когда у вас достаточно данных для приличного валидационного набора (в котором каждый класс представлен хотя бы парой десятков примеров) и количество гиперпараметров и их диапазон не слишком велики, — это использовать поиск по сетке (grid search).
Поиск по сетке — это самая простая техника настройки гиперпараметров. Допустим, вы обучаете SVM, и у вас есть два гиперпараметра для настройки: параметр штрафа \(C\) (положительное вещественное число) и ядро (либо «линейное», либо «rbf»).
Если вы впервые работаете с этим конкретным набором данных, вы не знаете, каков возможный диапазон значений для \(C\). Самый распространенный трюк — использовать логарифмическую шкалу. Например, для \(C\) вы можете попробовать следующие значения: \([0.001, 0.01, 0.1, 1, 10, 100, 1000]\). В этом случае у вас есть 14 комбинаций гиперпараметров для пробы: \([(0.001, \text{“linear”}), (0.01, \text{“linear”}), (0.1, \text{“linear”}), (1, \text{“linear”}), (10, \text{“linear”}), (100, \text{“linear”}), (1000, \text{“linear”}), (0.001, \text{“rbf”}), (0.01, \text{“rbf”}), (0.1, \text{“rbf”}), (1, \text{“rbf”}), (10, \text{“rbf”}), (100, \text{“rbf”}), (1000, \text{“rbf”})]\).
Вы используете обучающий набор и обучаете 14 моделей, по одной для каждой комбинации гиперпараметров. Затем вы оцениваете производительность каждой модели на валидационных данных, используя одну из метрик, которые мы обсуждали в предыдущем разделе (или какую-либо другую метрику, которая важна для вас). Наконец, вы сохраняете модель, которая работает лучше всего согласно метрике.
Как только найдена лучшая пара гиперпараметров, вы можете попытаться исследовать значения, близкие к лучшим, в некоторой области вокруг них. Иногда это может привести к еще лучшей модели.
Наконец, вы оцениваете выбранную модель с использованием тестового набора.
Как вы могли заметить, перебор всех комбинаций гиперпараметров, особенно если их больше пары, может быть трудоемким, особенно для больших наборов данных. Существуют более эффективные техники, такие как случайный поиск (random search) и байесовская оптимизация гиперпараметров (Bayesian hyperparameter optimization).
Случайный поиск отличается от поиска по сетке тем, что вы больше не предоставляете дискретный набор значений для исследования для каждого гиперпараметра; вместо этого вы предоставляете статистическое распределение для каждого гиперпараметра, из которого значения выбираются случайным образом, и устанавливаете общее количество комбинаций, которые вы хотите попробовать.
Байесовские техники отличаются от случайного или сеточного поиска тем, что они используют результаты прошлых оценок для выбора следующих значений для оценки. Идея заключается в том, чтобы ограничить количество дорогостоящих оптимизаций целевой функции, выбирая следующие значения гиперпараметров на основе тех, которые хорошо себя показали в прошлом.
Существуют также техники на основе градиентов (gradient-based techniques), эволюционные техники оптимизации (evolutionary optimization techniques) и другие алгоритмические техники настройки гиперпараметров. Большинство современных библиотек машинного обучения реализуют одну или несколько таких техник. Существуют также библиотеки настройки гиперпараметров, которые могут помочь вам настроить гиперпараметры практически любого алгоритма обучения, включая те, которые вы запрограммировали сами.
5.7.1 Перекрестная проверка (Cross-Validation)
Когда у вас нет приличного валидационного набора для настройки гиперпараметров, общая техника, которая может помочь, называется перекрестной проверкой (cross-validation). Когда у вас мало обучающих примеров, может быть нецелесообразно иметь как валидационный, так и тестовый набор. Вы предпочтете использовать больше данных для обучения модели. В таком случае вы разделяете свои данные только на обучающий и тестовый набор. Затем вы используете перекрестную проверку на обучающем наборе для имитации валидационного набора.
Перекрестная проверка работает следующим образом. Сначала вы фиксируете значения гиперпараметров, которые хотите оценить. Затем вы разделяете свой обучающий набор на несколько подмножеств одинакового размера. Каждое подмножество называется блоком (fold). Обычно на практике используется пятиблочная перекрестная проверка. При пятиблочной перекрестной проверке вы случайным образом разделяете свои обучающие данные на пять блоков: \(\{F_1, F_2, \dots, F_5\}\). Каждый \(F_k\), \(k = 1, \dots, 5\), содержит 20% ваших обучающих данных. Затем вы обучаете пять моделей следующим образом. Чтобы обучить первую модель, \(f_1\), вы используете все примеры из блоков \(F_2, F_3, F_4\) и \(F_5\) в качестве обучающего набора, а примеры из \(F_1\) — в качестве валидационного набора. Чтобы обучить вторую модель, \(f_2\), вы используете примеры из блоков \(F_1, F_3, F_4\) и \(F_5\) для обучения, а примеры из \(F_2\) — в качестве валидационного набора. Вы продолжаете строить модели итеративно таким образом и вычисляете значение интересующей метрики на каждом валидационном наборе, от \(F_1\) до \(F_5\). Затем вы усредняете пять значений метрики, чтобы получить окончательное значение.
Вы можете использовать поиск по сетке с перекрестной проверкой, чтобы найти наилучшие значения гиперпараметров для вашей модели. Как только вы нашли эти значения, вы используете весь обучающий набор для построения модели с этими наилучшими значениями гиперпараметров, которые вы нашли с помощью перекрестной проверки. Наконец, вы оцениваете модель с использованием тестового набора.
1Когда порядок значений некоторой категориальной переменной имеет значение, мы можем заменить эти значения числами, сохранив только одну переменную. Например, если наша переменная представляет качество статьи, а значения {плохое, приличное, хорошее, отличное}, то мы можем заменить эти категории числами, например, {1, 2, 3, 4}.
2Скорость предсказания kNN и ансамблевых методов, реализованных в современных библиотеках, все еще довольно высока. Не бойтесь использовать эти алгоритмы на практике.
3Или любой другой тип функции средней потери, который имеет смысл.