Часть 1: Предварительная обработка данных

Эпоха глубокого обучения популяризировала подход сквозного машинного обучения, при котором необработанные данные поступают на один конец конвейера, а прогнозы — на другой конец. Это, безусловно, привело к ускорению вывода моделей в некоторых областях, особенно в конвейерах компьютерного зрения, о чем свидетельствует, например, более высокая частота кадров однократных детекторов по сравнению с моделями, которые полагаются на предложения областей, за которыми следует обнаружение объектов. Способность сложных моделей автоматически извлекать признаки позволила отказаться от вычислительных ресурсов, чтобы сэкономить человеческие ресурсы.
Этот подход означает, что специалисты по машинному обучению все чаще перерабатывают модели, а не оттачивают свои данные. Но наступает момент, когда легкие выгоды сорваны, и удвоение размера модели может дать лишь незначительное улучшение производительности. Это когда функции ручной работы могут принести большую отдачу.
«Прикладное машинное обучение — это, по сути, разработка функций»
— Эндрю Нг
Отчасти компромисс между автоматическими и созданными вручную функциями стал возможен благодаря богатству, многомерности и обилию визуальных данных. При работе с небольшим количеством данных или менее многофункциональными данными, что слишком характерно для специалистов по данным, которым поручено делать прогнозы на основе всего дюжины или около того функций, конструирование функций необходимо для скопируйте и выделите все доступные «сигналы», присутствующие в ограниченных данных; а также для преодоления ограничений популярных алгоритмов машинного обучения, например сложности разделения данных на основе взаимодействия мультипликативных или разделительных признаков.
Соревнуясь в соревнованиях Kaggle, лучшие команды побеждают не просто за счет выбора модели, компоновки и настройки гиперпараметров, а, в значительной степени, благодаря своей способности разрабатывать новые функции, иногда кажущиеся из воздуха, хотя чаще всего, то, что рождается из комбинации истинного понимания данных (привнесение знаний в предметную область), дополнения вспомогательными данными и упорной, творческой (скорее искусство, чем наука), но утомительной работы методом проб и ошибок по построению и тестированию новых функции, чтобы увидеть, что работает.
В этой серии, состоящей из нескольких частей, мы рассмотрим три части полного пайплайна Feature Engineering:
- Предварительная обработка данных
- Генерация функций
- Выбор функции
Эти три шага выполняются по порядку, но иногда возникает неясность относительно того, представляет ли определенный метод предварительную обработку данных, извлечение признаков или генерацию. Но мы не зацикливаемся на семантике… вместо этого мы сосредоточимся на обзоре целого ряда методов, которые любой хороший специалист по машинному обучению и специалист по данным может применить в проекте.
Целью этой серии статей является повышение осведомленности об этих иногда забываемых, особенно в эпоху глубокого обучения и моделей с миллиардами параметров, методах, о которых всегда следует помнить, и знании некоторых библиотечных функций, которые могут значительно облегчить их использование. Для описания внутренней работы каждой техники потребуется отдельная статья, многие из которых можно найти здесь, в разделе На пути к науке о данных.
1. Предварительная обработка данных
1.1 Очистка данных
«Мусор на входе, мусор на выходе».
Во время EDA одним из первых шагов должна быть проверка и удаление постоянных функций. Но наверняка модель может обнаружить это самостоятельно? Да и нет. Рассмотрим модель линейной регрессии, в которой ненулевой вес был инициализирован постоянным свойством. Затем этот термин служит вторичным термином «предвзятости» и кажется достаточно безобидным… но нет, если этот «постоянный» термин был постоянным только в наших обучающих данных и (без нашего ведома) позже принимал другой вид. значение в наших производственных/испытательных данных.
Еще одна вещь, на которую следует обращать внимание, — это дублированные функции. Это может быть неочевидно, когда речь идет о категориальных данных, поскольку это может проявляться в том, что разные метки имена назначаются одному и тому же атрибуту в разных столбцах, например. Одна функция использует «XYZ» для обозначения категориального класса, а другая функция обозначает «ABC», возможно, из-за того, что столбцы отбираются из разных баз данных или отделов. pd.factorize() может помочь определить, являются ли две функции синонимами.
Далее идут избыточные и сильно связанные функции. Мультиколлинеарность может привести к тому, что коэффициенты модели будут нестабильными и очень чувствительными к шуму. Помимо негативного влияния на хранение и вычислительные затраты, избыточные функции снижают эффективность других функций, когда принимается во внимание регуляризация веса, что делает модель более подверженной шуму. pd.DataFrame.corr() можно использовать для определения коррелированных функций.
Дублирование может происходить не только между столбцами, но и между строками. Такое дублирование образцов может привести к дисбалансу данных и/или переобучению во время обучения. pd.DataFrame.duplicated() вернет серию со значением True в каждой дублированной строке после ее первого появления.
1.2 Перетасовка данных
Важно различать перетасовку во время предварительной обработки и во время обучения.
Во время предварительной обработки важно перетасовать набор данных, прежде чем разбивать его на подмножества обучения/проверки/тестирования. Для небольших или сильно несбалансированных наборов данных (например, при обнаружении аномалий, мошенничества или болезней) используйте функцию stratify on sklearn.model_selection.train_test_split(), чтобы обеспечить согласованное распределение ваших целей меньшинства по всем вашим подмножествам. pd.DataFrame.sample(frac=1.0) можно использовать для простого перемешивания вашего фрейма данных.
В целях обучения большинство платформ машинного обучения будут перемешивать данные за вас, но важно понимать, выполняется ли это одноразовое перемешивание, т. е. только при загрузке набора данных, или оно делает это постоянно, пакет за пакетом. Последнее предпочтительнее для получения наименьших потерь при обучении, но может привести к более медленному обучению, поскольку мини-пакеты данных нельзя кэшировать и повторно использовать для следующей эпохи.
1.3 Вменение данных
Это большая тема! Отсутствующие функции должны быть продуманы.
Отсутствующие функции могут быть не очевидны сразу, поэтому простое использование pd.DataFrame.isna.sum(axis=0) может не показать их все. Отсутствующие поля могут быть обозначены специальной (непустой) строкой или числовым значением (например, «-», 0 или -999). Набор данных, который вы используете, возможно, уже кем-то предварительно обработан и импутирован. К счастью, обнаружение отсутствующих признаков может быть выполнено путем построения гистограммы каждого признака — необычные всплески выбросов указывают на использование специальных значений, в то время как всплеск в середине распределения является признаком того, что среднее/медианное вменение уже выполнено.
Следующий вопрос — Как заменить отсутствующие поля. Самый распространенный и простой метод — заменить моду (для категориальных признаков), среднее (для числовых признаков без большого количества выбросов) или медиану (где выбросы значительно искажают среднее значение) для отсутствующего значения.
Тем не менее, особенно если вы считаете, что функция важна, не заменяйте слепо среднее/медиану/моду всего набора данных. Например, в наборе данных Titanic не указан возраст нескольких пассажиров. Вместо того, чтобы приписывать всем таким пассажирам средний возраст всех пассажиров на корабле, мы можем получить более точную оценку, поняв, что средний (и медианный) возраст между классами пассажиров на борту корабля был совершенно разным.

На самом деле, поскольку в этом наборе данных нет пропущенных значений для пола пассажира, вы можете сделать еще один шаг при условном исчислении и подставить средний возраст на основе i. тарифный класс и ii. пол каждой выборки, в которой отсутствует значение возраста.
Для временного ряда никогда не следует вменять отсутствующие выборки с помощью замены среднего/медианы, так как это неизменно приведет к внезапным изменениям в ряду, которые являются нереалистичными. Вместо этого используйте повторение значений или интерполяцию. Методы шумоподавления обработки сигналов, такие как медианная фильтрация или низкочастотная фильтрация нулевой фазы, также могут использоваться для заполнения небольших пробелов в обучающих данных; но имейте в виду, что некаузальные методы нельзя использовать во время производства, за исключением случаев, когда допустим отсроченный вывод модели.
Альтернативой является полное отсутствие вменения и вместо этого добавление бинарного флага, чтобы позволить нижестоящему алгоритму обучения самостоятельно научиться справляться с такими условиями. Недостатком этого является то, что вам, возможно, придется добавить гораздо больше таких объектов с низким уровнем сигнала, если отсутствующие значения разбросаны по многим объектам. Обратите внимание, что XGBoost обрабатывает NaN из коробки, поэтому при его использовании нет необходимости добавлять столбцы с отсутствующими данными. В общем, деревья решений могут изначально обрабатывать кодировку меток специальных значений отсутствующих значений, устанавливая для них нижние/верхние экстремальные значения, которые затем могут быть легко разделены узлами принятия решений.
Другой популярный метод — запустить k-NN для вменения пропущенных значений. Использование нейронной сети для импутации — еще один популярный способ. Например, автокодировщик можно обучить воспроизводить обучающие данные с пропуском входных данных, а после обучения его выходные данные можно использовать для прогнозирования отсутствующих значений признаков. Однако использование методов машинного обучения для изучения вменения может быть сложным, поскольку трудно оценить, как гиперпараметры модели вменения (например, значение k) влияют на производительность конечной модели.
Независимо от метода импутации, по возможности, всегда выполняйте Генерацию признаков (обсуждается во второй части этой серии) доимпутации данных, т.к. это позволит более точно вычислять сгенерированные значения признаков, особенно когда для вменения используется кодирование со специальными значениями. Знание того, что соответствующее значение функции отсутствует, оставляет дверь открытой для специальной обработки при создании новых функций.
1.4 Кодирование функций
Порядковые признаки могут иметь целочисленные значения, но они отличаются от числовых признаков тем, что, хотя порядковые значения подчиняются транзитивному отношению сравнения, они не подчиняются арифметическим правилам вычитания или деления.
Порядковые признаки, такие как звездные рейтинги, часто имеют сильно нелинейные «истинные» отображения, соответствующие сильно биполярному распределению. т. е. количественная «разница» между 4-звездочным и 5-звездочным рейтингом часто невелика и значительно меньше половины разницы между 4-звездочным и 2-звездочным рейтингом, что может привести к путанице в линейных моделях.
Таким образом, линейные модели могут выиграть от более линейного переназначения присвоения порядковых значений, но, с другой стороны, древовидные модели способны справляться с такой нелинейностью по своей сути. Порядковое кодирование лучше оставить как единую количественную характеристику (т. Отношение шума других прогностических функций (например, когда применяется регуляризация параметров).
Обработка категориальных функций зависит от того, является ли ваша модель древовидной. В древовидных моделях может использоваться меточное кодирование (т. е. фиксированные строки или целые числа, обозначающие принадлежность к классу), и дополнительная предварительная обработка не требуется. Методы, отличные от дерева, требуют, чтобы категориальные признаки были горяче закодированы, что может быть выполнено с использованием либо pd.get_dummies(), либо sklearn.preprocessing.OneHotEncoder(). Избегайте удаления первого столбца (т. е. не указывайте drop=’first’), если только вы не имеете дело с бинарной категорией (т. е. используйте drop=’if_binary’), поскольку удаление создает больше проблем, чем решает.
Альтернативой одноразовому кодированию является использование частотного кодирования или дополнение к нему. Это включает в себя вычисление нормализованной частоты целевой переменной, соответствующей каждой категории. Например. Присвойте бинарному категориальному признаку значение 0,4, если 40 % выборок в этой категории дают целевое значение, равное единице. Это полезно, когда категориальный признак коррелирует с целевым значением.
Еще одним способом кодирования категориальных признаков является использование категориальных вложений. Это особенно подходит для категориальных функций с высокой кардинальностью, таких как почтовые индексы или продукты. Как и в случае встраивания слов, эти вложения изучаются с помощью плотной нейронной сети. Анализ результатов показывает, что эти непрерывные вложения также имеют смысл для кластеризации и визуализации, уменьшая при этом переоснащение.
Последний момент в работе с категориальными функциями — что делать, если в подмножестве проверки/тестирования встречается невидимая категория. В этом случае относитесь к нему так же, как к отсутствующей функции, или назначьте ему зарезервированную категорию «Неизвестно».
1.5 Числовые характеристики
Масштабирование или нормализация не требуются для древовидных методов, но в остальном необходимы для достижения низких потерь при обучении, быстрой сходимости и правильной работы регуляризации весов. Выберите один или другой.
Масштабирование sklearn.preprocessing.MinMaxScaler() выполняется быстро, и часто это все, что требуется для данных изображения. Однако на масштабирование Min-Max могут существенно повлиять выбросы (даже всего один!) или отсутствующие значения, которые закодированы как значения, выходящие за пределы нормального диапазона признаков.
Нормализация sklearn.preprocessing.StandardScaler() более устойчива к выбросам, если доля выбросов мала (т. е. если выбросы не искажают существенно среднее значение и стандартное отклонение).
Числовые признаки часто выигрывают от преобразования. Логарифмическое преобразование, np.log(1 + x), является очень сильным преобразованием, которое особенно полезно, когда функция соблюдает степенную зависимость или когда в распределении выбросов есть длинный хвост. Преобразование Квадратный корень, np.sqrt(x) менее сильное, и его можно попробовать в качестве полезного промежуточного преобразования. Преобразование Бокса-Коксаscipy.stats.boxcox() позволяет плавно перейти от прямолинейной к сильно нелинейной передаточной функции благодаря использованию гиперпараметра лямбда и часто используется для преобразования асимметричное распределение (например, положительный результат теста на COVID в зависимости от возраста) в более нормальное распределение, которое является основным предположением, сделанным многими традиционными алгоритмами машинного обучения, такими как NB, LogR и LinR. . [ПРИМЕЧАНИЕ: x ›= 0 предполагается для всех вышеупомянутых преобразований].
1.6 Функции геолокации
Методы на основе дерева иногда могут выиграть от вращательных преобразований в координатах геолокации. Например, South-of-Market (SoMa) — это район в Сан-Франциско, граничащий с Market Street. Однако Маркет-стрит проходит не с севера на юг или с востока на запад, а скорее с юго-востока на северо-восток. Таким образом, деревьям решений будет трудно точно сегментировать эту окрестность (когда глубина дерева ограничена, что часто необходимо), поскольку деревья могут рисовать только линии раздела, которые параллельны оси (т. е. либо долготе, либо оси широты). Однако трудность с выполнением вращательных преобразований заключается в выборе точки поворота для поворота координат, поскольку глобально оптимальной может не быть.
Одним из решений является преобразование декартовых координат в полярные координаты. Город Париж, например, разделен на округа, расположенные примерно по кругу вокруг центра города. В качестве альтернативы можно выполнить кластеризацию и создать новый категориальный признак, указывающий, к какому кластеру принадлежит точка, после чего можно использовать полярные координаты для кодирования местоположения каждой точки из ее центроида/ядра кластера.
1.7 Особенности времени
Время в наборе данных может отображаться как время UTC/GMT, а не как местное время, даже если все события относятся исключительно к одному (и другому) часовому поясу. Даже если временные метки указаны по местному времени, может оказаться полезным выполнить сдвиг во времени для функций времени.
Например, тарифы на совместные поездки, как правило, выше в конце дня (особенно в пятницу/субботу/воскресенье) из-за сочетания более высокого спроса и более низкого предложения. Однако, как известно любому любителю ночных гуляк, вечеринки не заканчиваются в полночь. Из-за переноса времени модели трудно определить, что 00:30 «позднее» или даже «близко» к 23:30. Однако, если выполняется сдвиг во времени и сложный переход 23:59 → 00:00 происходит во время дня, когда наименьшая активность, линейные модели регрессируют лучше, чем древовидные. -модели на основе потребуют меньшего количества уровней ветвления.
1.8 Текст

Текст, возможно, является функцией, которая требует наибольшей предварительной обработки. Начнем с трансформаций, которых много.
Нижний регистр необходим для простых моделей, и это самая основная форма нормализации текста, обеспечивающая преимущества создания более сильного и надежного сигнала (из-за более высокой частоты встречаемости слов) при одновременном сокращении размера словарного запаса. Для более продвинутых предварительно обученных языковых моделей (LM), которые поставляются со своими собственными токенизаторами, лучше всего позволить LM выполнять токенизацию исходного текста с использованием заглавных букв (например, с помощью bert-base-cased) может помочь модели повысить производительность при разборе предложений, распознавании имен и сущностей (NER) и тегировании частей речи (POS).
Выделение корней и Лемматизация обеспечивают те же преимущества, что и преобразование в нижний регистр, но являются более сложными и требуют гораздо больше времени для выполнения. Основание сокращает слова, используя фиксированные правила, которые не учитывают контекст слова и его использование в предложении, например university усекается до univers, но и universal тоже. Лемматизация учитывает контекст и требует использования больших LM, поэтому выполняется медленнее, чем поиск корней. Однако это гораздо точнее, т.е. university и universal остаются отдельными корневыми словами. Учитывая доступные сегодня вычислительные ресурсы, авторы Spacy утверждают, что точность важнее всего в производстве, и поэтому библиотека поддерживает только лемматизацию.
Расширение сокращений — это еще одна форма нормализации текста с теми же мотивами. Здесь can’t и you’ll расширяются до can not и you will. Простые модели, основанные на подсчете/частоте, выигрывают от этой стандартизации, но LM, подобные тем, что в Spacy, изначально обрабатывают сокращения за счет использования маркировки подслов (can’t преобразуется в ca, за которым следует n’t).
Нормализация текста предназначена для преобразования текста и символов в каноническую форму, чтобы модели могли лучше учиться. Они преобразуют аббревиатуры (например, BTW), орфографические ошибки (например, «определенно»), диакритические знаки (например, кафе/наивный → кафе/наивный), смайлики (например, ‹ухмылка› | :-) | ;) | 🙂 → <SMILE>, РОФЛ | ЛОЛ | ЛМАО | 😆 → <LAUGH>) и т. д. Без нормализации текста многим моделям НЛП будет трудно разобраться в сообщениях в Твиттере и социальных сетях!
Далее следует фильтрация — стоп-слова, знаки препинания, числа, лишние пробелы, смайлики (если не выполняется анализ тональности), теги HTML (например, ‹br›), управляющие символы HTML (например, '', '') , URL-адреса, хэштеги (например, #blackfriday) и упоминания (например, @xyz)
Последним этапом предварительной обработки является токенизация. Простую токенизацию можно выполнить с помощью регулярных выражений Python, но фреймворки NLP предоставляют специальные токенизаторы, написанные на C/C++ или Rust, которые гораздо более эффективны. При использовании предварительно обученных LM, например, из Hugging Face, крайне важно использовать точно такой же токенизатор (и веса), который используется LM при его обучении.
1.9 Изображения
Предварительная обработка изображений в настоящее время менее распространена с ростом популярности CNN. Однако на оборудовании с ограниченными ресурсами без графического процессора или когда требуется высокая частота кадров, эти методы составляют основу традиционных конвейеров обработки компьютерного зрения.
Преобразование цветового пространства может обеспечить небольшой прирост производительности при использовании простых CNN. Это исследование, например, показало, что преобразование набора данных CIFAR-10 в цветовое пространство L*a*b привело к повышению точности классификации примерно на 2%, но наилучшие результаты были получены при одновременном использовании нескольких цветовых пространств. Было обнаружено, что цветовые пространства с отдельными каналами цветности и яркости (например, YUV) полезны для раскрашивания изображения и передачи стиля. Я лично обнаружил, что специализированные цветовые преобразования, адаптированные для определенных областей (например, гематоксилин-эозин-DAB для гистопатологии), могут быть особенно полезными для повышения производительности модели.
Выравнивание гистограммы, особенно адаптивное выравнивание гистограммы (например, CLAHE), часто выполняется на медицинских изображениях для улучшения визуального контраста. Это особенно полезно, когда освещение неравномерно по всему изображению, а отличительные признаки малы по сравнению со всем кадром изображения, например, при обнаружении раковой ткани на маммографических изображениях. Было показано, что при визуализации глазного дна сетчатки, где качество изображения сильно различается во время получения изображения, выполнение коррекции неравномерного освещения улучшает точность оценки.
Традиционные методы извлечения признаков CV включают локальные бинарные шаблоны (LBP), гистограмму ориентированных градиентов (HOG) и банки фильтров Габора. Существует долгий опыт успешного использования этих экстракторов признаков с моделями, не основанными на CNN. Объединение этих старых методов (например, обучаемых фильтров Габора) со стандартными сверточными слоями может привести к более быстрой сходимости и большей точности для некоторых наборов данных (например, Dogs-vs-Cats).
На этом завершается часть I этой серии, посвященная разработке признаков. Во Части II мы обратим внимание на Создание функций, где рассмотрим извлечение и синтез совершенно новых функций. Это действительно то, где искусство встречается с наукой, и это то, что отличает гроссмейстера Kaggle от новичка!