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

Анализ данных можно рассматривать как устройство (или черный ящик, или китайскую комнату), которое при некоторых входных данных дает выходные данные. Основное различие между основанным на правилах и основанным на статистике (также известном как машинное обучение) заключается в том, что первое принимает обучающие примеры и правила (алгоритмы) в качестве входных данных и дает прогнозы в качестве выходных данных, в то время как второе предполагает обучение примеры и метки в качестве входных данных и дает правила в качестве выходных данных. То есть в машинном обучении правила выводятся из взаимосвязи между входными данными и метками, в то время как в классическом подходе правила предопределены, как правило, людьми, которые потратили годы, пытаясь их понять. Разница не так тонка, как может показаться: например, в науке правила часто закодированы в программах, выполняющих моделирование исследуемой физической системы (например, климат Земли или взаимодействия между частицами). С другой стороны, если эти правила не известны заранее как ранее существовавшие теоретические основы, другой вариант, вероятно, будет единственным, который имеет смысл. Стоит отметить, что в некоторых известных случаях, таких как свертывание белков, подход машинного обучения под названием AlphaFold оказался не менее успешным, чем более традиционные средства, открывая новые захватывающие возможности.

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

Для начала давайте кратко рассмотрим, как обрабатываются категориальные входные данные. Самый простой способ — прикрепить числовую (целочисленную) метку к каждой категории, например, dog = 1, cat = 2 и fish = 3 . Хотя в принципе это может работать, на практике общеизвестно, что статистическая модель (далее просто модель) может обнаружить фиктивную закономерность из-за того, что, например, fish > dog (потому что 3 > 1 ), что вряд ли имеет смысл. Чтобы избежать такой проблемы, обычно рекомендуется использовать кодировку one-hot. В этом методе каждая категория представлена ​​вектором из N элементов (где N — количество категорий), все из которых равны 0, за исключением 1 помещается в индекс, соответствующий данной категории. В нашем примере dog = (1,0,0), cat = (0,1,0) и fish = (0,0,1). В этом случае вам необходимо расширить категориальный признак до N бинарных признаков (или N-1, если в рассматриваемой проблеме может возникнуть проблема с фиктивной переменной-ловушкой или мультиколлинеарностью) . Однако это не конец истории. Эти индексы должны использоваться в справочной таблице, элементы которой будут дополнительно обрабатываться моделью, чтобы соответствовать выходным данным, представленным во время обучения. Если вы не знакомы с этой концепцией, интерполяционная таблица представляет собой матрицу NxM, где количество строк соответствует количеству категорий N, а M охватывают пространство параметров, которое часто называют пространством внедрения векторов. Таблица поиска называется матрицей внедрения. Например, если матрица:

A = [
     [0.1, -0.2, 0.3], 
     [-0.2, 0.3, 0.1],
     [0.7, -0.4, -0.2]
]

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

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

Для начала можно просто масштабировать («минимальное-максимальное масштабирование» или «нормализация») входной объект до фиксированного диапазона, который обычно равен (0,1), а затем отправить его вниз по течению к остальной части модели:

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

Чтобы эта процедура имела смысл, данные должны быть распределены примерно как распределение Гаусса. В приведенном ниже примере гипотетическая функция a) может быть либо нормализована, либо стандартизирована успешно, но функция b), скорее всего, вызовет проблемы.

Есть и еще один аспект, который необходимо учитывать. Некоторые функции могут быть неотрицательными или ограниченными ниже заданного значения, но неограниченными в противном случае (например, зарплата). Другие могут быть неограниченными в обоих направлениях (например, расстояние влево или вправо) или даже иметь симметрию относительно 0 (как многие тригонометрические функции). Более того, обучающие данные могут не иметь достаточного количества экстремальных примеров, так что параметры масштабирования (среднее, мин./макс., стандартное) могут не отражать большую совокупность. Любой выброс, появляющийся во время вывода, не будет обрабатываться правильно, что может привести к непреднамеренному поведению или непонятным результатам (для X > Xmax у одного есть X’>1).

Одно правило, чтобы управлять ими всеми

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

  1. Объедините данные в N бинов, чтобы построить гистограмму функции. Если позволяет объем обучающих данных, найти оптимальные границы, рассчитав квантили распределения (в этом случае бины будут располагаться неравномерно);
  2. Замените входной объект индексом бина и обработайте его как категориальный вход (т.е. какому бину соответствует это значение?);
  3. Используйте справочную таблицу для извлечения плотных векторных вложений для каждого бина;
  4. Передайте векторное вложение вниз по течению.

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

Хорошая новость: в библиотеке scikit-learn есть класс KBinsDiscretizer, который реализует большую часть обсуждавшихся выше вещей.

Реализация с TensorFlow 2.x

Чтобы было понятнее, я подготовил простую реализацию слоя встраивания квантованных признаков на основе TensorFlow 2.x. Для полноценного тест-драйва не стесняйтесь раскошелиться на этот ноутбук Google Colab.

Для начала вам нужно квантовать входные функции. Я настоятельно рекомендую использовать класс KBinsDiscretizer из scikit-learn , но ту же процедуру можно воссоздать, используя функцию numpy.quantile.

Входные функции могут выглядеть следующим образом:

После квантования с 5 бинами для каждого признака мы получаем что-то вроде этого:

На данный момент нам нужно создать расширение слоя Embedding из TensorFlow/Keras. В исходной реализации матрица внедрения представляет собой 2D-объект, индексированный идентификатором токена. В нашем случае нам нужна дополнительная индексация измерения, на которую ссылается вложение, поэтому в целом это трехмерный тензор. К счастью для нас, функция gather_nd позволяет нам выбирать записи из трехмерного тензора, используя двумерный тензорный индекс. Звучит сложно, но это не так: все, что нужно сделать, это выбрать вектор, вложенный в 2D-справочную таблицу, индексированную (идентификатор функции, идентификатор токена):

Вы можете использовать этот слой так же, как и обычный слой внедрения, например:

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

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

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

Последнее слово о генеративных моделях: я сам участвовал в проекте по разработке GAN для моделирования взаимодействия между частицами на Большом адронном коллайдере [JHEP08(2019)110], где некоторые входные характеристики охватывают несколько порядков, некоторые являются положительными, но неограниченными, другие ограничены и демонстрируют осевую симметрию. В то время я не знал об этой технике. Оглядываясь назад, квантование признаков могло бы избавить нас от множества размышлений и проблем. Точно так же я подозреваю, что этот метод может оказаться полезным для автоэнкодеров.