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

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

Решение задач анализа данных состоит из двух больших этапов:

  1. Подготовка данных.
  2. Построение на подготовленных данных моделей.

На практике, качество итоговых моделей намного сильнее зависит от качества подготовленных данных, чем от выбора самой модели и её оптимизации.

Например, XGBoost может дать улучшение качества модели порядка 5% по сравнению со случайным лесом, нейронная сеть до 3% по сравнению с XGBoost. Оптимизации, регуляризация и подбор гиперпараметров может ещё добавить 1-5%.

Но просто добавив информационные признаки, извлечённые из тех же данных, которые уже есть, можно сразу получить до 15% прироста качества модели.

Построение признакового пространства




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

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

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

1. найти все возможные характеристики описываемых моделью объектов;
2. не делать предположения о важности извлекаемых из данных параметров;
3. извлекаемые параметры должны быть осмыслены.

Расскажу о каждом пункте подробнее

Данные, на которых мы обучаем модель – это объекты реального мира. Изначально мы не располагаем векторами и тензорами. Всё что у нас есть – это какое-то сложное описание каждого объекта в выборке. Это могут быть, например, номер телефона, цвет упаковки, рост и даже запах.

Для нас важно всё. И из каждого из этих сложных признаков можно извлечь цифровую информацию.

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

Когда-то такой подход считался плохой практикой. Линейные модели не могли работать с коррелирующими параметрами, так как это приводило к плохой обусловленности матриц, неограниченному росту весов. Сегодня проблема мультиколлинеарности практически исчерпана за счёт использования продвинутых алгоритмов и методов регуляризации. Если у вас есть рост и вес человека – берите оба эти параметра. Да, они коррелируют, но мультиколлинеарность – в прошлом. Просто используйте современные алгоритмы и регуляризацию.

Итак, рассмотрите каждый аспект вашего объекта и найдите все числовые характеристики. В конце ещё раз посмотрите и подумайте. Не упустили ли вы чего-то.

Приведу пару примеров.

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

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

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

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

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

Не делайте предположения о важности извлекаемых из данных параметров.
Какой бы экспертизой в предметной области мы не обладали, мы не знаем всех статистических закономерностей. Я не перестаю удивляться как иногда, казалось бы, не важные на первый взгляд вещи улучшают качество модели и выходят в топ features importance. В конечном итоге у вас будет много признаков, которые вообще не работают. Но вы не знаете заранее, какие хитрые сочетания не важных, на первый взгляд, параметров сработают хорошо.

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

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

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

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

Наводим порядок в данных




Когда данные собраны, нужно навести в них порядок.

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

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

И наконец, посчитайте features importance. Делать это нужно по двум причинам.

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

Во-вторых, вам нужно найти самые важные признаки и проанализировать их.

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



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

TL;DR


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

Используйте функциональные выражения от ваших информационных признаков, если они оправданы.

Удаляйте статистически не значимые переменные и переменные сильно коррелирующие с другими.

Сделайте диаграмму важности признаков. Возможно удалите самые не важные.
Изучите самые важные.

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

Если у вас есть возможность проверить вашу модель не только на тестовых, но и на реальных данных. Проверьте её сначала исключив подозрительно важные параметры, а затем включив их. И сравните результаты.

Приведённые здесь рекомендации зависят от того, какой алгоритм используется для построения модели. Я обычно использую нейронные сети. Эти рекомендации точно не подойдут вам, если вы используете логистические и линейные регрессии.

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

Объём статьи не позволяет затронуть все аспекты, но я постарался изложить основные моменты.
Большинство публикаций по машинному обучению ориентированы на описание алгоритмов. Но сбор и подготовка данных – это 95% работы по построению модели. Надеюсь, моя заметка поможет вам пореже наступать на грабли.

А какие методы улучшения качества моделей используете вы?
Автор — Валерий Дмитриев rotor
Спасибо MikeKosulin за правки :)

Комментарии (12)


  1. sshmakov
    14.11.2017 16:04

    Внезапно habrahabr.ru/company/modulbank

    Компания
    МОДУЛЬБАНК
    ПРЕКРАТИЛА АКТИВНОСТЬ НА ХАБРЕ


    1. ModulbankOfficial Автор
      14.11.2017 16:11

      Пока не решились на покупку Блога — это было промо.
      Выпускали статью: habrahabr.ru/article/339452


  1. stavinsky
    15.11.2017 10:33

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

    Можно пожалуйста подробнее о том как работать имея небольшое количество размеченных данных и большое количество неразмеченных данных?
    И второй вопрос который пришел сегодня в голову. Как быть и можно ли что-то придумать если данные размечены некачественно. Положим требования к параметрам для попадания в какую-либо категорию менялись из года в год с ростом бизнеса и изменением внешних факторов.


    1. rotor
      15.11.2017 14:07

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

      Смысл в том что бы использовать понижение размерности.
      Можно использовать классический PCA, но лучше использовать автокодировщики. Автоэнкодеры умеют улавливать нелинейность в данных, а не просто удалять компоненты с минимальной дисперсией.
      Как это работает.
      Берём большой набор неразмеченных данных. Строим автоенкодер. Автоенкодер принимает на вход вектор всех ваших фич и даёт вектор небольшой размерности 10-30. Результат работы автокодировщика добавляется к фичам.
      Автокодировщик можно строить разными способами. Тут сложно дать какие то универсальные рекомендации.
      Я обычно использую автокодировщики с 4-мя скрытыми слоями. Что-то вроде такого:


      Input -> H1 -> relu -> H2  ->  tanh ->
      H3 -> tanh H4  -> relu -> Output

      Функции активации могут быть другими. Всегда есть relu, а его расположение может меняться.
      Вторую половину выкидываю и выход после H2 -> tanh беру как выход автокодировщика.
      Можно понижать размерность в несколько этапов.
      Допустим так 3000 -> 2100 -> 1000 -> 15
      Причина поэтапного понижения размерности в том, что из-за затухания градиентов, вы не можете сделать автокодировщик сразу слишком глубоким.
      Какие-то универсальных рекомендаций дать не могу. Нужно экспериментировать.


      При использовании автоэнкодера нужно учитывать следующие нюансы:
      1) Автокодировщик находит внутренние закономерности. Его выход невозможно объяснить. Это просто какой-то вектор. Как его интерпретировать не понятно.
      2) Автокодировщик теряет информацию. Поэтому строить прогноз только на его выводе нельзя. Чем сильнее понижается размерность, тем больше информации он теряет.
      3) Если понижать размерность поэтапно, то каждый следующий автокодировщик будет иметь намного меньшую ёмкость по сравнению с предыдущим.
      Рассчитывать этапы понижения нужно с учётом ёмкости каждого автокодировщика и объёма имеющихся неразмеченных данных.


      Сложно проверить хорошо сработал у вас автокодировщик или плохо. Можно косвенно оценивать по качеству аппроксимации исходного набора. Но качество полученных в результате фич оценить сложно.
      Но он точно работает, потому что результаты автоенкодера часто выходят у нас в топ FI.


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

      Вот это сложный для меня вопрос. Реальные данные часто грязные. Как быть не знаю. Пытаться исправить качество разметки, разве что. Самому интересно, есть ли какие то рецепты на этот счёт.


      1. rotor
        15.11.2017 14:13

        Вот один из моих примеров понижения размерности автокодировщиком:
        3039 -> 213 -> 56 -> 15
        Если в конец добавить ещё 15 -> 3 то можно визуализировать результат и посмотреть распределение.


        Что-то такое


      1. stavinsky
        16.11.2017 10:18

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


        1. alex4321
          17.11.2017 08:06

          То есть, у нас есть, предположим, 1000 примеров с ответами и еще 100к примеров без ответов. Я могу натравить автоэнкодер на все и получить доп фичи, это понятно.


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


          Но это моё мнение дилетанта, который даже не особо учится :-)


  1. Almet
    15.11.2017 16:04

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

    Вот это очень хороший совет. Можете еще что-нибудь посоветовать по этому поводу? Т.е. интересно было бы знать, какие фичи нужно использовать при анализе данных.


    1. rotor
      16.11.2017 10:40

      какие фичи нужно использовать при анализе данных

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


      1. Almet
        16.11.2017 15:14

        Спасибо большое, будем изучать


  1. WTYPMAH
    16.11.2017 06:22

    Для меня самым интересным и наглядным общедоступным примером feature engeneiring является задача Титаника. Можно просто почитать готовые работы на кегле и понять всю суть этого процесса — сколько всего полезного можно извлечь из простых, казалось бы, данных + заполнить пропуски одних параметров на основании других.


    1. Almet
      16.11.2017 15:15

      А можно чуть подробнее? либо ссылочку:)