Введение
Pandas — прекрасная библиотека в экосистеме Python для анализа данных и машинного обучения. Она идеально соединяет мир данных, где живут файлы Excel/CSV и таблицы SQL, и мир моделирования, где свою магию творят Scikit-learn или TensorFlow.
Поток в науке о данных чаще всего представляет собой последовательность шагов: наборы данных должны быть очищены, нормализованы и проверены перед тем, как будут готовы к использованию этим мощным алгоритмом машинного обучения.
Эти задачи, разумеется, можно выполнить с помощью множества одношаговых функций или методов, предложенных в Pandas и ей подобных пакетах, но более элегантный путь — это использование конвейеров. В большинстве случаев конвейеры снижают шанс возникновения ошибки и экономят время за счет автоматизации повторяющихся задач.
В мире науки о данных великолепными примерами пакетов с конвейерами являются dplyr в R и Scikit-learn в экосистеме Python.
Pandas также предлагает метод pipe
, который можно использовать для аналогичных целей с функциями, определенными пользователем. Тем не менее в этой статье мы поговорим о прекрасной маленькой библиотеке pdpipe, разработанной для реализации конвейеров с Pandas DataFrame.
Конвейеры с Pandas
Пример конвейера можно найти в моем репозитории на Github. Давайте посмотрим, как создавать полезные конвейеры при помощи этой библиотеки.
Набор данных
В демонстрационных целях используем набор данных с ценами на дома в США из каталога Kaggle. Мы можем загрузить набор данных в Pandas и увидеть сводную статистику:
В наборе также есть поле “Address”, содержащее текстовые данные:
Добавление колонки size (размер дома)
Для демонстрации добавим к набору данных колонку, содержащую размер дома, используя следующий код:
После этого набор данных выглядит так:
Простейший конвейер — одна операция
Начнем с простейшего конвейера, содержащего только одну операцию (не беспокойтесь, скоро мы добавим сложности).
Скажем, команда машинного обучения и предметные специалисты утверждают, что для моделирования мы можем пренебречь данными Avg. Area House Age
. Следовательно, мы удалим эту колонку из набора данных.
Для этой задачи создадим объект конвейера drop_age
с методом ColDrop
из pdpipe и передадим DataFrame этому конвейеру.
import pdpipe as pdp
drop_age = pdp.ColDrop(‘Avg. Area House Age’)
df2 = drop_age(df)
Как и ожидалось, итоговый DataFrame выглядит следующим образом:
Объединяем этапы конвейера простым добавлением
Конвейеры практичны и удобны только в случае использования нескольких этапов. В pdpipeсуществует несколько методов сделать это, однако простейший и наиболее интуитивно понятный подход — это использование оператора +. Прямо как соединение труб вручную!
Допустим, кроме удаления колонки возраста мы хотим получить кодирование категорий колонки House_size
, чтобы алгоритм классификации или регрессии можно было легко запустить в наборе.
pipeline = pdp.ColDrop(‘Avg. Area House Age’)
pipeline+= pdp.OneHotEncode(‘House_size’)
df3 = pipeline(df)
Итак, сначала мы создали объект конвейера с методом ColDrop
, чтобы удалить колонку Avg. Area House Age
. После мы просто добавили к этому конвейеру метод OneHotEncode
, используя обычный +=
синтаксис Python.
Ниже итоговая таблица. Обратите внимание на две дополнительные колонки House_size_Medium
и House_size_Small
, созданные в процессе кодирования категорий.
Удаление строк на основе их значения
Далее можно удалить строки данных, основываясь на их значениях. Например, удалим все данные, где цена на дом ниже 250,000. У нас есть метод ApplybyCol
для применения к DataFrame любых заданных пользователем функций, а также метод ValDrop
для удаления строк на основе определенных значений. Мы легко можем добавить эти методы к конвейеру, чтобы выборочно удалять строки (мы добавляем их к тому же объекту pipeline
, который уже выполняет работу по удалению колонок и кодированию категорий).
def price_tag(x):
if x>250000:
return 'keep'
else:
return 'drop'
pipeline+=pdp.ApplyByCols('Price',price_tag,'Price_tag',drop=False)
pipeline+=pdp.ValDrop(['drop'],'Price_tag')
pipeline+= pdp.ColDrop('Price_tag')
Первый метод помечает строки на основе значения в колонке Price
, применяя заданную пользователем функцию price_tag()
:
Второй метод ищет строку drop
в колонке Price_tag
и удаляет соответствующие строки. И, наконец, третий метод удаляет колонку Price_tag
, очищая таблицу данных. Колонка Price_tag
нужна временно только для того, чтобы пометить определенные строки, поэтому после завершения своей задачи она должна быть удалена.
Все это сделано простым объединением этапов в одном конвейере!
Давайте вернемся и с самого начала рассмотрим, что наш конвейер делает с таблицей данных:
- удаляет определенную колонку;
- для моделирования применяет кодирование категорийных данных;
- помечает данные на основе заданной пользователем функции;
- удаляет строки на основе метки;
- удаляет временно помеченную колонку.
И все это за пять строк кода:
pipeline = pdp.ColDrop('Avg. Area House Age')
pipeline+= pdp.OneHotEncode('House_size')
pipeline+=pdp.ApplyByCols('Price',price_tag,'Price_tag',drop=False)
pipeline+=pdp.ValDrop(['drop'],'Price_tag')
pipeline+= pdp.ColDrop('Price_tag')
df5 = pipeline(df)
Обновление последней версии: удаление строк напрямую!
В разговоре с автором пакета я выяснил, что в последней версии удаление строки (удовлетворяющей заданному условию) будет выполняться одной строчкой кода с использованием лямбда-функции:
pdp.RowDrop({‘Price’: lambda x: x <= 250000})
Этапы Scikit-learn и NLTK
Существует множество более полезных и интуитивно понятных методов для манипуляций с DataFrame. Однако мы хотим показать, что даже некоторые операции из пакетов Scikit-learn и NLTK, включенные в pdpipe, позволяют создавать отличные конвейеры.
Оценка нормализации из Scikit-learn
Одна из наиболее распространенных задач в создании моделей машинного обучения — это нормализация данных. Scikit-learn предлагает несколько типов нормализации, таких как Min-Max или нормализация на основе стандартизации (где среднее значение из набора данных вычитается с последующим делением на стандартное отклонение).
Мы можем непосредственно связать подобные операции в конвейер. Нижеследующий код это демонстрирует:
pipeline_scale = pdp.Scale('StandardScaler',exclude_columns=['House_size_Medium','House_size_Small'])
df6 = pipeline_scale(df5)
Здесь мы применили функцию оценки StandardScaler
из пакета Scikit-learn, чтобы преобразовать данные для кластеризации или подгонки нейронной сети. Мы можем выборочно исключать из нормализации колонки, как было сделано здесь для колонок House_size_Medium
и House_size_Small
.
Вуаля! У нас есть нормализованный DataFrame:
Токенизатор NLTK
Заметим, что поле “Address” сейчас довольно бесполезно. Однако оно может пригодиться для некоторой визуализации или задач машинного обучения, если мы сможем выделить из него индекс или название штата.
Для этой цели можно использовать токенизатор слов. NLTK — это популярная и мощная библиотека Python для интеллектуального анализа текста и обработки естественного языка (NLP), которая предлагает ряд методов токенизатора. Здесь мы можем использовать такой токенизатор для расщепления текста в поле адреса и выделения из него названия штата. Мы знаем, что название штата является предпоследним словом в адресной строке. Следовательно, следующий конвейер выполнит для нас эту работу:
def extract_state(token):
return str(token[-2])
pipeline_tokenize=pdp.TokenizeWords('Address')
pipeline_state = pdp.ApplyByCols('Address',extract_state,
result_columns='State')
pipeline_state_extract = pipeline_tokenize + pipeline_state
df7 = pipeline_state_extract(df6)
Итоговый DataFrame выглядит так:
Итог
Все эти операции можно использовать в аналогичных типах наборов данных. И очень бы пригодился простой набор последовательных блоков кода для выполнения предварительной обработки набора данных для последующего моделирования.
Использование конвейеров — ключ к получению такого единого набора последовательных блоков кода. Pandas —это наиболее широко используемая библиотека Python для подобных задач предварительной обработки в командах машинного обучения или науки о данных,а pdpipe предоставляет простой, но мощный путь для создания конвейеров с операциями типа Pandas, которые непосредственно применяются к объектам Pandas DataFrame.
Исследуйте эту библиотеку самостоятельно и создавайте мощные конвейеры для своих специфических задач.
Читайте также:
- Что такое *args и **kwargs в Python?
- Простое руководство по аргументам командной строки Python
- Логи в Python. Настройка и централизация
Перевод статьи Tirthajyoti Sarkar: Build pipelines with Pandas using pdpipe