Python: категориальные признаки

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

contries

Категориальные признаки называют по-разному: факторными, номинальными. Их значения определяют факт принадлежности к какой-то категории. Примеры таких признаков: пол, страна проживания, номер группы, категория товаров и т.п. Ясно, что для компьютерной обработки вместо «понятного для человека» значения (в случае страны — ‘Russia’, ‘GB’, ‘France’ и т.п.) хранят числа. Вот ниже поговорим, как эти числа получать… Некоторый обзор разных способов кодировок можно найти в моей статье.

1. Как автоматически найти все категориальные признаки

Универсального средства нет, но если перед Вами табличка «объект-признак», и Вам хочется засунуть её в какой-нибудь sklearn-овский алгоритм, то надо, по крайней мере, что-то сделать со столбцами, в которых записаны строковые значения. Также подозрения всегда вызывают столбцы с небольшим числом уникальных значений (см. функцию pandas.nuniques).

pic01

2. Как создавать новые категориальные признаки

Самый частый приём — конъюнкция. Скажем, конъюнкция двух признаков — это признак, значениями которого являются пары (значение первого признака, значение второго признака). В пакете pandas это делается до неприличия просто: значения приводятся к строковому типу и суммируются (см. рис).

pic02

3. Как кодировать

Есть простейший кодировщий sklearn.preprocessing.LabelEncoder, который каждой категории сопоставляет некоторое целое число (собственно, номер категории). Даже если бы его не было, то такую кодировку несложно написать самому с помощью функции map. Для этого предварительно задаётся словарь, в котором указывается, что и чем кодировать.

pic03

4. Dummy-кодирование

Ясно, что предыдущий метод сильно упрощает данные, фактически проецируя категориальный признак на вещественную прямую. Весь смысл категориальности теряется. Более того, появляются ложные интерпретации. Например, в примере на рис. теперь London + Kiev = Moscow, но это не свойство данных, а свойство выбранной нами кодировки. Есть простейший метод, лишённый этого недостатка, его часто называют наивным / глупым (dummy) кодированием или one-hot-кодированием. Для кодируемого категориального признака создаются N новых признаков, где N — число категорий. Каждый i-й новый признак — бинарный характеристический признак i-й категории. На рис. показана реализация с помощью sklearn.preprocessing.OneHotEncoder и «ручная» реализация этого метода (которая хороша тем, что работает с исходными строковыми признаками, но очень медленная на больших таблицах).

pic04

После one-hot-кодирования признаковая матрица «раздувается» и её хранят в sparse-формате (собственно, по умолчанию она как раз разреженная).

5. Умные способы кодирования

Когда не хотят заполонять признаковую матрицу кучей бинарных признаков, применяют кодировки, в которых категории кодируются какими-то интерпретируемыми значениями. Например, если это категория товаров в интернет-магазине, то логично её закодировать средней ценой товара. Тогда, по крайней мере, наш новый признак упорядочивает категории по дороговизне. В любом случае, делается это с помощью функции map и groupby. Кстати, даже если бы функции map не было, можно было бы обойтись выражением data[feature].apply(lambda x: dct[x]).

pic05

Самый примитивный способ кодирования — заменить каждую категорию числом входящих в неё объектов (т.е. знания других признаков вообще не нужно). Это делается в одну строчку кода: data[newfeature] = data[feature].map(data.groupby(feature).size()).

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

pic07

Реклама

20 thoughts on “Python: категориальные признаки

  1. Здравствуйте!
    В своей статье, на которую вы ссылаетесь в этом посте, вы пишете:

    «Отметим, что 94.21% объектов в задаче – из класса 1, поэтому мера AUC ROC хорошо подходит для оценки качества.»

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

    Спасибо

    • Здравствуйте! Спасибо за вопрос, к тому же очень дельный.

      В целом Вы правы, но тут есть много «НО».

      1. Первое и главное, эти меры качества немного для разных задач (по крайней мере, с точки зрения требований к ответу). Именно поэтому точность и полноту любят в информационном поиске, а AUC ROC в обычной классификации. Вот в этой ветке есть подробный ответ, с которым я, в целом, согласен:
      https://www.kaggle.com/forums/f/15/kaggle-forum/t/7517/precision-recall-auc-vs-roc-auc-for-class-imbalance-problems/
      Кстати, там ещё ссылка на классную статью.

      2. В соревновании, с которого взяты данные, использовалась как раз мера качества AUC ROC. И на кэгле почти всегда в подобных задачах используется AUC ROC. С ней действительно, проще и удобнее работать.
      https://www.kaggle.com/c/amazon-employee-access-challenge

      3. Во многих классических «несбалансированных» задачах (как раз похожих по смыслу к описанной) используется именно AUC ROC. Например, в кредитном скоринге (только AUC ROC или Gini, что, по сути, одно и то же). Хотя в кредитном скоринге всегда дисбаланс классов!

      И, наконец, если Вы внимательно посмотрите на примеры, которые приводят, когда говорят, что AUC PRC лучше (см. например тут ~11мин
      https://ru.coursera.org/learn/vvedenie-mashinnoe-obuchenie/lecture/fPkI2/mietriki-kachiestva-klassifikatsii-2
      ), то увидите в чём их искусственность… на практике не бывает так, чтобы алгоритм выдал 50000 объектов класса 0, потом 100 класса 1, потом остальные класса 0. Всё-таки алгоритм «размазывает» и «перемешивает» объекты разных классов. Вот когда говорят, что плохо использовать обычную точность (% верных ответов), поскольку алгоритмы начинают выдавать просто номер самого представительного класса — это действительно так — они реально выдают константу. Поэтому на практике AUC ROC не так плох.

  2. Вот хорошо что подняли тему не сбалансированных данных, таких данных очень много, и это в первую очередь «натуральные» данные, собранные по реальным процессам природы.

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

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

    • 3% это не проблема от слова совсем. В зависимости от количества данных решается использованием over- или undersampling. Есть и более изощренные подходы, но они выстреливают обычно в строго определенных случаях, так что если Вы решаете прикладную задачу (а не на соревновании выступаете), 2 вышеуказанных методов вполне достаточно. AUC (ROC) или Gini при 3% исходов вполне себе работают.
      Проблемы начинаются, когда доля исходов, например, ниже 0,01% или 0,001% (самое экстремальное, с чем я сталкивался, это 1 инцидент на ~ 100 млн событий), вот там уже все веселее. В таких задачах действительно приходится использовать Precision&Recall и производные от них интегральные метрики.

    • Вообще, если популярные методы дают не очень хорошие результаты на несбалансированных данных, то это, быть может, не их проблема, а проблема их некорректного применения. Универсальный совет в этом (и не только) случае — задачу классификации решайте как задачу регрессии, т.е. фактически предсказывайте вероятность того, что объект принадлежит редкому классу «1». Тогда для реальной классификации надо будет ещё порог подобрать. Но это сразу снимет проблему, что у Вас всё загоняется в большой класс «0».

      Поясню. Допустим у нас есть задача с редким классом «1» (синий) https://alexanderdyakonov.files.wordpress.com/2016/05/tmp.png
      Возьмём любой классический метод. Ну, пусть ближайший сосед.
      Он всё загонит в класс «0», даже если kNN, то при росте k будет не лучше,
      всё равно всё в классе «0». А вот если использовать регрессионный kNN,
      то в районе «полосы класса 1» будут значения выше, чем вдали.

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

  3. Я считаю что как раз over- или undersampling годятся только для «соревнований».
    На реальных данных нет никакого смысла делать копии событий.
    Так как от этого копирования процессы новые в исходных данных не появятся.

    Про «изощренные подходы» я и спрашиваю.

  4. На реальных данных, если их достаточно, undersampling (cлучайное удаление примеров мажоритарного класса) используется более чем активно, в розничных кредитных рисках, например. Можете на riskofficer.ru зайти в соответствующий раздел форума и убедиться. В т.ч. потому, что это самый ПРОСТОЙ способ решить проблему (и самый надежный как следствие)
    По поводу oversampling Вы не правы, Александр, возможно, прокомментирует.
    Не претендую на всеведение, но я ни разу не слышал, чтобы при разработке промышленных моделей в банках ТОП-10 кто-то активно использовал Tomek Links, Condensed Nearest Neighbor Rule или что-то подобное. Максимум с SMOTE люди экспериментировали. В ряде случаев он показывает интересные результаты.
    Но тут вот какая проблема. Для использования какой-то экзотики нужно четко понимать, что Вы имеете дело с тем или иным специфическим случаем.
    Например, SMOTE крайне плохо работает, если миноритарные исходы ~ равномерно распределены среди мажоритарных. На этот случай есть, конечно, усложнение SMOTE под названием Adaptive Synthetic Minority Oversampling, но если такими усложнениями увлекаться, можно столкнуться с тем, что на валидационном наборе модель себя покажет, возможно, еще неплохо, но «в бою» будет дикий провал качества модели. Это как с reject inference — формальное улучшение модели еще не означает, что мы модель действительно улучшили. «Сильные» предположения вообще очень опасны. На практике такие вещи применяют только при постоянном A/B тестировании, иначе можно влететь так, что небо с овчинку покажется. Это как с сильными лекарствами — чем забористее препарат, тем больше противопоказаний и побочных действий, так что при приеме таких препаратов анализы нужно сдавать едва ли не ежедневно. Учитывая, что в России количество организаций, имеющих инфраструктуру для автоматизированных A/B тестов, перечислить можно по пальцам, это не то направление, с которого надо начинать, ИМХО.

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

    По большому счету, все это такая же экзотика как ФОРЕЛ в кластерном анализе. Ну вот есть и такой метод. До которого обычно никогда руки не доходят на практике.

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

    P.S. Если Александр эту тему подробнее разберет будет, конечно, интересно. Особенно, если затронуть тему с «экстремально» несбалансированными классами, где исходы 1 на миллион или даже реже. У меня в этой области, например, теоретическая подготовка тоже хромает. Задумываешься иногда, могут ли быть полезны в таких случаях какие-то подходы на основе байесовского вывода или глубинное/глубокое обучение, какие требования к данными в таких ситуациях возникают и т.п..

  5. Сусанин, спасибо за подробный ответ !
    Вы видимо работаете в банке. А у меня метеоданные, это совсем не те данные, которые в банках.
    Я пытаюсь прогнозировать экстремальный дождь.
    И именно простые метода тут немного работают. Хотя их точность не очень.

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

  6. Я скажу банальную вещь: надо смотреть на данные. Деревья это, возможно, и не лучший способ для предсказывания редких событий, но если у Вас доля исходов 3%, они должны нормально работать, если данные аккуратно подготовлены и качество у данных более-менее. Как данные готовить — см. все вышеперечисленное от undersampling до ASMO. Например, тут кратко на русском можно почитать:
    https://basegroup.ru/community/articles/imbalance-datasets
    Ну и надо учитывать, что в среднем, подходы на основе деревьев решений отличаются довольно высокой чувствительностью и если данные сильно зашумлены, то лучше выбрать более робастный метод, ИМХО.
    Если вспомнить про реалии российской метеорологии (количество базовых станций сократили по сравнению с СССР в разы, своих метеоспутников нет), у Вас просто данные могут быть не слишком подходящими для использования деревьев.
    Запихните, например, в логрегрессию и посмотрите, что получается (от необходимости правильно данные семплировать это Вас не освобождает — прим. мое). Только постройте предварительно матрицу корреляций и посмотрите на корреляцию предикторов плюс проконтролируйте VIF. Если будет больше 3, используйте что-то типа L1-регуляризации. Если в итоге получится что-то более-менее приличное, то добавьте к предикторам x1, x2, x3 кроссы x1x2, x2x3 и посмотрите на результат. Если качество повысится, то, возможно, деревья в этой задаче могут неплохо выстрелить, если их правильно приготовить.

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

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

    Давайте по порядку.
    1. Сколько у Вас наблюдений по порядку величины? (10 в какой степени?)
    2. Доля миноритарного класса?
    3. Количество исходов миноритарного класса больше или меньше 100? 1000?
    4. Как Вы оцениваете качество данных? Насколько они зашумлены/какая погрешность измерений ?
    5. Насколько сильно коррелируют предикторы?
    6. Связь предикторов с целевой переменной скорее линейная или нет?
    7. Проверьте, что учтен фактор времени. Если мне не изменяет память и остатки знаний по школьной географии и физике атмосферы, то режим циркуляции атмосферы меняется в зависимости от сезона, а значимость различных барических центров неодинакова в разное время года.
    8. Миноритарные исходы распределены примерно равномерно среди мажоритарных или нет?
    Примените метод KNN и оцените, сколько среди 100 ближайших соседей миноритарных исходов примеров из мажоритарного класса хотя бы для 100-200 случайно отобранных миноритарных исходов.
    9. Проверьте еще раз корректность данных. Например, что в выборку не включены наблюдения из зон с температурной инверсией без указания на этот замечательный факт, или что Вы не пытаетесь анализировать данные собранные выше и ниже оси Воейкова, например.

  7. Очень большое спасибо, такого подробного ответа я не получал уже давно !

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

    Мы берем например данные отсюда :

    http://meteo.ssc-ras.ru/#

    станция 1001 как самая полная по наличию данных, измерения через 10 минут, тоже не очень хорошо, но это лучшее что есть сейчас.

    Там около 85 000 измерений за два года.

    Общая характеристика данных конечно важна.

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

    Например при слабом ветре и температуре +25 корреляции одни, а при ветре 30 м/сек и ливневом экстремальном дожде «корреляции» становятся совсем другими.
    Кроме того очевидно имеются нелинейные взаимосвязи, которые выражены явно, но корреляция их будет около нуля.
    Доля миноритарного класса — менее 1%, за два года всего 2 экстремальных дождя. Всех дождей, включая слабые и микро — менее 3% от данных. Но экстремальный дождь — это одно, а обычный дождь — это другое.

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

    Предикты иногда сильно коррелируют, а иногда слабо.

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

    Миноритарные данные распределены внутри мажоритарных кусками. Один такой кусок — это и есть экстремальный дождь.

    Температурную инверсию нельзя подтвердить или опровергнуть, данных о вертикали температуры просто нет. Хотя косвенные признаки (визуальные наблюдения) инверсии есть.

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

    Вторая группа — это так называемые Дождевые Супер Ячейки, когда ливневой дождь выпадает локально на площади 10-15 км2. Они то и есть самые опасные.

    Насчет оси Воейкова — просьба пояснить или можно ссылку.

  8. 1. Если Вы анализируете данные по одной погодной станции, то вопрос про ось Воейкова снимается.
    Вообще говоря, это полоса высокого атмосферного давления, простирающейся через Евразию приблизительно вдоль 50-ой параллели. «Ветрораздел» в некотором смысле. Вопрос был условным. Я хотел уточнить, не пытаетесь ли Вы построить модель, которая будет предсказывать дожди в любой точке страны или континента. Судя по всему — нет.
    2. По 2 исходам модель классификации построить точно не удастся. Если конечная задача это именно предсказание экстремального дождя, то можно попробовать подходы т.н. anomaly detection, например, на основе одноклассовой классификации типа One-Class SVM или SVDD. Но 2 кейса это очень сурово, проверить корректность такой модели будет нереально. Попробуйте достать данные хотя бы пары соседних погодных станций. По идее сдвиг в сторону на несколько десятков км не должен привести к радикально иным стат. зависимостям.
    3. Если станция снимает параметры каждые 10 минут и фиксируется непрерывный ряд по ряду ключевых параметров, а экстремальный дождь характеризуется какими-то серьезными аномалиями, то, возможно, Вам стоит подумать о такой вещи как использование теории разладки. Например CUSUM (статистика кумулятивных сумм) по идее позволит выявить момент, когда перестройка процессов в атмосфере будет указывать на то, что сейчас будет что-то нехорошее. Надо, конечно, на данные смотреть, но шансы, что Вы это увидите за пару часов до начала ИМХО неплохие.

    От себя замечу, что машинное обучение это далеко не панацея. Из попыток Яндекса применить Матрикснет на данных ЦЕРН, например, так ничего и не вышло (по словам знакомого из оного ЦЕРН).

    • Спасибо за интересную дискуссию. Я ответил на изначальный вопрос (ответ выше в этой ленте).

      Хм… про ЦЕРН интересно. Всегда думал, что вряд ли это к чему-то приведёт, но, тем не менее, машинлёрнингом для ЦЕРНА сейчас, вроде, много кто занимается… неужели ни у кого ничего не выйдет?!

      • Смотря за что браться, ИМХО. Условный пример: можно ли повысить при помощи теории разладки надежность каких-то подсистем коллайдера? Вполне реализуемо, ИМХО.
        Задача не настолько амбициозная, как поиск отклонений от Стандартной модели, но не менее полезная.
        В целом же…машинное/статистическое обучение, во-первых, только один из многих разделов математики, а не панацея. Условно, лет 40 назад везде дифуры пихали, сейчас — машинное обучение, через 30 лет будут так же с квантовыми вычислениями носиться, с криками о прорыве, который изменит мир раз и навсегда уже к следующей пятнице.
        Во-вторых, в середине 50-х энтузиасты нейронных сетей предсказывали, что машина одолеет чемпиона мира по шахматам через 10 лет. Некоторые оппоненты в пику заявляли, что машины никогда не обыграют человека в шахматы, ну или не ранее, чем будет создан ИИ. Неправы оказались все.. Машина смогла обыграть чемпиона мира по шахматам, но на это потребовалось более 40 лет, а не 10. И это не был внезапный прорыв: уровня мастера машины достигли в начале 80-х, гроссмейстера — в конце 80-х, обыграли чемпиона мира еще через 10 лет. А ИИ у нас и спустя 20 лет нет. И еще через 20 лет тоже не будет. При том, что к этому моменту у нас вполне могут быть роботы-водители, например, причем в качестве массового продукта, а не экзотики.

      • Александр, спасибо за советы и рекомендации !

  9. […] Самой популярной публикацией из не-интервьюшных стала прошлогодняя заметка Знакомьтесь, Джини (она хорошо гуглится по соответствующему запросу). На втором месте — статья уже этого года Python: категориальные признаки. […]

  10. […] Но стоит помнить о том, что правильное применение стекинга — это не взять кучу разных алгоритмов и «состекать». Дело в том, что для разных алгоритмов нужны разные признаковые пространства. Скажем, если есть категориальные признаки с малым (3-4) числом категорий, то алгоритму «случайный лес» их можно подавать «как есть», а вот для регрессионных (ridge, log_reg) нужно предварительно выполнить one-hot-кодировку. […]

  11. Здравствуйте. Столкнулся с проблемой того, когда в trainset нет категорий признака, который встречается в testset.
    Есть ли в этом случае какие-то известные решения?

    • В целом, это и не проблема вовсе. Главное: чётко понимать, какой моделью Вы решаете и как генерируете признаки. Допустим Вы делаете one-hot-encoding и решаете с помощью логистической регрессии. Допустим, у Вас задача с 2 классами и классы сбалансированы. Тогда всё просто: Ваше решение это искривлённая сигмоидой линейная комбинация. Нулевая комбинация соответствует вероятности 0.5 принадлежности к любому из классов. Положительные коэф. в линейной комбинации увеличивают вероятность одного класса, а отрицательные — другого. Если у Вас встретилась вдруг новая категория, то коэффициент при соответствующем признаке нулевой и на классификацию будут влиять другие признаки (что очень логично!).

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

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s