Привет, Хабр! Меня зовут Иван Сивков, я наставник на курсе «Специалист по Data Science» в Яндекс Практикуме. В этой статье покажу, как построить пайплайн в библиотеке scikit-learn на базе встроенных инструментов и сократить количество кода при преобразовании данных. Эта статья рассчитана на новичков, которые только начинают изучать Data Science, но уже знают основные понятия. В тексте упоминается scikit-learn — одна из самых популярных Python-библиотек для классического машинного обучения. Кроме большого числа алгоритмов машинного обучения, с помощью scikit-learn можно строить пайплайны. Это цепочки функций, через которые можно проводить данные. Пайплайны похожи на конвейеры, где каждое звено выступает в роли преобразователя (трансформера) или модели-предсказателя (обычно это последнее звено). Важный этап обработки данных  — их преобразование. Без пайплайна данные должны проходить через отдельные преобразователи: энкодеры (преобразуют категориальные признаки в числовые векторы), импьютеры (заполняют пропуски в данных) и скейлеры (приводят признаки к одному масштабу). Каждый инструмент по отдельности нужно натренировать на обучающей выборке, преобразовать её и отдельно сделать преобразование тестовой выборки. В результате получается много повторяющегося кода. Пайплайн собирает все инструменты в один конвейер без повторяющегося кода. Достаточно обучить этот конвейер на обучающей выборке и использовать его для всех нужных преобразований одной командой. Он принимает на вход признаки, преобразует их и выдаёт результат.  Ниже соберём пайплайн из отдельных инструментов, обучим его на обучающей выборке данных и сделаем предсказание. Первым шагом установим минимально нужную версию библиотеки — 1.1. Если выполняете код в Jupiter Hub Яндекс Практикума, то базовая версия sklearn — 0.24. Нужно установить более позднюю, чтобы избежать проблем с совместимостью. Затем импортируем pandas для загрузки данных, а также все инструменты sklearn, которые понадобятся в этом примере: скейлеры, энкодеры и импьютеры. В списке есть вспомогательные инструменты для разделения выборок, рассчитывания метрик и других операций. Убедимся, что версия библиотеки не ниже требуемой. Показываю для примера — в реальной разработке этот шаг не нужен. Отключим предупреждения о будущем изменении названия аргумента sparse объекта OneHotEncoder на sparse_output, чтобы не мешало отображению вывода.  Впрочем это предупреждение будет выводиться только, если используете версию scikit-learn 1.2 и выше. Также ограничим вывод датафреймов восемью столбцами.   В таком виде они будут влезать на один экран, и работать с ними будет удобнее.  Для этого примера возьмём популярный бесплатный датасет с информацией о стоимости недвижимости в Калифорнии, который часто упоминают в обучающих статьях и книгах по Data Science. Скачаем его с сайта компании Hugging Face — разработчика библиотеки Transformers (содержит нейронные сети и другие инструменты для работы с текстовыми данными). Следующим шагом выбираем целевой признак medium_house_value — это медианная цена за дом для округа. Численными признаками будут медианное значение возраста домов, общее количество комнат и спален в них, население, число домов, медианный доход на семью. А категориальный признак — положение относительно океана. А затем разделяем датасет на рабочую и тестовую выборки: На этом подготовительная часть закончена — перейдём к созданию пайплайна.  Для наглядности создадим два отдельных пайплайна — для численных и категориальных признаков, а затем соберем их в один. Начнём с численных. Задача пайплайна pipe_num на этом этапе — заполнить пропуски и, если они есть, провести масштабирование признаков.  Для этого используем инструмент SimpleImputer, заполним с его помощью пропуски медианным значением признака. StandardScaler стандартизирует данные — вычитает среднее и делит на среднее квадратичное обучающей выборки. В последней строке задаём объект класса Pipeline. При этом передаём на вход список, каждый элемент в котором — кортеж из двух значений. Это трансформер и его название, которое мы задаём самостоятельно, чтобы в случае необходимости обратиться к нему. Следующим шагом через pipe_num вызываем fit_transform — происходит то же самое, как если бы мы отдельно применяли SimpleImputer и StandardScaler. Здесь используются все признаки, кроме категориального. Трансформатор выше возвращает данные в виде NumPy-массива, столбцы в котором не названы. Чтобы вернуть названия столбцов для удобства работы с данными, можно использовать метод get_feature_names_out объекта пайплайна. В данном случае названия можно взять и напрямую из датафрейма, так как этот пайплайн сохраняет исходный набор признаков. Но если после преобразования набор столбцов меняется, например с применением энкодера, такой способ не подойдёт. Использование get_feature_names_out — более универсальный подход, поэтому будем использовать его для всех пайплайнов.  В конце для проверки выводим результат преобразования численных признаков: Это служебная строка, в которой мы проверяем, что в данных нет пропусков. В итоговый пайплайн она не попадёт и нужна исключительно для демонстрации. Теперь создадим пайплайн для категориальных признаков. С помощью SimpleImputer заменим пропуски на значение ‘unknown’, а OneHotEncoder используем для кодирования категориальных признаков в числовые значения, понятные моделям. Аргумент handle_unknown=’ignore’ нужен для исключения ошибок в случаях, если при тестировании встречаются категории, которых не было в обучающей выборке. В конце создаём пайплайн из импьютера и энкодера и проверяем, что он сработал. Хотя в этом датасете в категориальном признаке нет пропусков, они могут возникнуть, если при использовании модели на практике появятся новые данные. На этот случай нужно решение, которое позволит коду не упасть, — для этого и нужен импьютер. Теперь объединяем признаки в один пайплайн. Здесь есть нюанс: поставить категориальные и численные признаки просто друг за другом не удастся, их надо обрабатывать по-разному. В scikit-learn есть инструмент ColumnTransformer, который работает как компоновщик пайплайнов. С его помощью можно распараллелить пайплайн: для одной части столбцов может применяться один пайплайн, для второй — другой. При задании объекта Column Transformer передаётся список кортежей. В каждом кортеже кроме названия и трансформера, как при создании объекта Pipeline, дополнительно указывается, для каких столбцов он применяется. Стоит отметить, что кроме элементарных трансформеров (SimpleImputer, StandardScaler и др.) Column Transformer может принимать в качестве преобразователя и объекты Pipeline.  С помощью инструмента list comprehension создаём списки численных и категориальных столбцов. В нашем примере датасет небольшой, и можно было бы задать списки вручную. Но на практике столбцов может быть намного больше, поэтому лучше автоматизировать процесс. В коде ниже проверяется тип столбца: если он object, то считается как категориальный, если нет — как численный.  В этой строке возвращаем результат выполнения пайплайна: Преобразуем результат в датафрейм. При этом уберём дополнительную информацию в названиях столбцов — автоматически метод get_feature_names_out объекта ColumnTransformer добавляет название трансформера, с помощью которого были получены столбцы. Из-за этого на страницу влезает меньше столбцов, и пользоваться выводом становится неудобно. Собираем готовый пайплайн, компонуя его части с помощью Column Transformer. Он состоит из предобработки и модели Ridge из библиотеки scikit-learn — это линейная регрессия с регуляризацией. Это одна из простых моделей, которая предсказывает целевой признак на основе суммы других признаков, умноженных на коэффициенты. Обучаем финальный пайплайн на обучающей выборке и делаем предсказание.  Если объединить пайплайн целиком и исключить из него демонстрационные фрагменты кода, то он будет выглядеть так: В итоге весь код для предобработки, обучения и предсказания занимает буквально полстраницы. В следующих статьях изучим тонкости использования пайплайнов вместе с инструментами кросс-валидации scikit-learn и покажем, как делать более сложные кастомизированные конвейеры и использовать их в своих пет-проектах. Научиться работать с датасетами, пайплайнами, Jupyter Notebook и многими другими инструментами, не упомянутыми в этой статье, можно на курсе «Специалист по Data Science» от Практикума. В зависимости от вашего расписания и привычного темпа работы, можно освоить программу за 5, 8 или 16 месяцев.  Специалист по DataScience, преподаватель ЯП