Предварительная обработка данных в машинном обучении: инструкция, инструменты, полезные ресурсы для начинающих
В статье рассказываем, зачем обрабатывать данные перед загрузкой в модель, как провести предобработку и какие инструменты использовать.
Data Scientist, Альфа-Банк
Что такое предобработка данных
Предобработка — это подготовка набора данных перед загрузкой в модель. Данные в исходном виде часто содержат артефакты, такие как шум, пропуски или дубликаты, которые усложняют их анализ и снижают качество работы алгоритмов.
Артефакты могут появляться по разным причинам:
Человеческий фактор: ошибки при ручном вводе — опечатки, пропуски или неправильные значения.
Неполные данные: информация может быть недоступна, например, сотрудник не указал свое место проживания.
Ошибки при сборе: сбои в автоматических системах, например, временные проблемы с сетью, из-за чего часть данных теряется.
Объединение данных из разных источников: разные форматы или отсутствие значений при объединении нескольких баз.
Технические ограничения: например, система принимает только положительные числа, а передали отрицательное значение.
Устаревшая информация: данные не обновляются вовремя, из-за чего информация устаревает.
Ошибки при миграции: повреждение или потеря данных при переносе из одной системы в другую.
Пример датасета с артефактами:
ID | Имя | Возраст | Зарплата | Город | Дата приема | Отдел |
1 | Иванов Иван | 28 | 100000 | Москва | 2018–05–20 | Продажи |
2 | NaN | NaN | 60000 | Санкт-Петербург | 2019–03–15 | Маркетинг |
3 | Ольга Петрова | 35 | -1500 | Новосибирск | NaN | Разработка |
4 | Андрей Сидоров | NaN | 70000 | Неизвестно | 2021–11–10 | NaN |
5 | NaN | 45 | 80000 | Казань | 2020–08–01 | HR |
6 | Елена Белова | 29 | NaN | NaN | 2017–09–23 | Продажи |
Пропуски: пропущенные значения в столбцах: Имя, Возраст, Зарплата, Город, Дата приема на работу, Отдел (NaN).
Ошибки в данных: отрицательное значение в столбце Зарплата (значение »-1500»).
Неоднородные данные:
В столбце Город указан заполнитель «Неизвестно» вместо названия города;
Разное представление пропущенных или неизвестных значений:
NaN (Not a Number) автоматически используется в некоторых системах, например, при выгрузке данных из баз или при считывании в библиотеке для анализа данных (такие как pandas);
«Неизвестно» — это пример текстового заполнителя, который вводят вручную, когда нет информации, — его также нужно обрабатывать как пропуск.
Предобработка помогает устранить все эти проблемы, а в результате — улучшить качество данных и повысить точность модели.
Как автоматизировать предобработку данных
Автоматизация предобработки сокращает время на рутинные задачи и снижает риск ошибок.
Для этого можно использовать различные инструменты и подходы:
Использование библиотек для предобработки: библиотеки, такие как Scikit-Learn, предоставляют множество готовых инструментов: например, SimpleImputer для заполнения пропусков, StandardScaler для масштабирования, LabelEncoder для кодирования категориальных данных.
Эти инструменты можно объединить в Pipeline — последовательность шагов для автоматической обработки данных.
Pipeline из Scikit-Learn: объединяет несколько этапов предобработки в один процесс, облегчая повторное применение тех же шагов к разным наборам данных и делая код более структурированным и понятным.
Пример: создание Pipeline для автоматического выполнения всех необходимых шагов предобработки, таких как заполнение пропусков, масштабирование и кодирование признаков.
Автоматизация с помощью библиотек для подготовки данных:
Pandas: часто используют для ручной предобработки, но можно создать функции, которые автоматически заполняют пропуски, масштабируют данные и кодируют признаки.
Feature-engine: библиотека с удобными функциями для автоматизации задач: создание новых признаков, кодирование категорий и работа с выбросами.
Polars: новая библиотека для высокоэффективной работы с данными и их анализа на Python, альтернатива Pandas для работы с очень большими объемами данных.
Другие подходы:
Платформы для машинного обучения: инструменты AutoML, такие как H2O.ai, LAMA и TPOT, автоматически подбирают модели и выполняют предобработку данных, что упрощает процесс для пользователя.
Написание собственных функций: можно написать функции для типовых задач, например, заполнения пропусков медианой или удаления выбросов, и использовать их каждый раз для обработки данных. Это экономит время и обеспечивает единообразие.
Как проводится предобработка данных — на примере
Предобработка данных — это главная стадия подготовки набора данных перед загрузкой в модель машинного обучения.
На каждом этапе можно выполнить ручную обработку, использовать автоматические инструменты для упрощения задачи или комбинировать оба способа.
Представим, что у нас есть набор данных о квартирах:
ID | Площадь (кв. м) | Число комнат | Возраст дома (лет) | Стоимость (млн руб.) | Тип недвижимости | Район |
1 | 80 | 3 | 20 | 8 | квартира | А |
2 | 100 | NaN | 150 | 10 | дом | Б |
3 | 2000 | 2 | NaN | 50 | квартира | А |
4 | 100 | 4 | 30 | 6 | апартаменты | В |
5 | 150 | 3 | 5 | NaN | дом | Б |
6 | 500 | 5 | 300 | 70 | квартира | А |
7 | 100 | 3 | 25 | 14 | дом | Б |
8 | 80 | 3 | -5 | 8 | апартаменты | В |
9 | -150 | 3 | 15 | 12 | дом | Б |
10 | 100 | 3 | 25 | 14 | квартира | А |
Разберем поэтапно обработку данных с использованием информации выше.
Используем следующие инструменты:
Pandas: библиотека для работы с таблицами данных (DataFrame), очистки данных, заполнения пропусков, удаления дубликатов и фильтрации данных.
Scikit-Learn: библиотека для машинного обучения. Включает инструменты для предобработки данных, которые используются для заполнения пропусков, масштабирования признаков и работы с выбросами.
Matplotlib и Seaborn: библиотеки для визуализации данных, используемые для анализа, в том числе обнаружения выбросов и шумов.
Numpy: библиотека для быстрой и эффективной работы с числовыми массивами, включая сложные математические преобразования.
Этап 1 — сбор и анализ данных
На первом этапе важно собрать данные и проанализировать их качество, так как это напрямую влияет на качество модели. На этом этапе можно понять структуру данных, выявить проблемы (пропуски, дубликаты, выбросы) и спланировать методы их устранения.
Сбор данных вручную. Данные можно получить из различных источников: баз данных, веб-скрейпинга, API, CSV-файлов и др. Например, вы можете загрузить данные с использованием Pandas:
Пример кода для загрузки данных:
import pandas as pd
# Создание DataFrame с данными о недвижимости
data = {
'ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Площадь (кв. м)': [80, 100, 2000, None, 150, 500, 120, 80, -150, 100],
'Число комнат': [3, None, 2, 4, 3, 5, 3, 3, 3, 3],
'Возраст дома (лет)': [20, 150, None, 30, 5, 300, 25, -5, 15, 25],
'Цена (млн руб.)': [8, 10, 50, 6, None, 70, 14, 8, 12, 14],
'Тип недвижимости': ['квартира', 'дом', 'квартира', 'апартаменты', 'дом', 'квартира', 'дом', 'апартаменты', 'дом', 'квартира'],
'Район': ['А', 'Б', 'А', 'В', 'Б', 'А', 'Б', 'В', 'Б', 'А']
}
df = pd.DataFrame(data)
Автоматизированный сбор данных: Сбор данных можно автоматизировать, чтобы уменьшить время и трудозатраты на подготовку. Примеры автоматизации включают:
API-запросы: использование библиотек, таких как requests, для получения данных по API.
import requests
import pandas as pd
response = requests.get('https://api.example.com/data')
data = response.json()
df = pd.DataFrame(data)
Веб-скраппинг: использование библиотек, таких как BeautifulSoup и Selenium, для сбора данных с веб-сайтов.
from bs4 import BeautifulSoup
import requests
url = 'https://example.com/data'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# Пример извлечения данных и создания DataFrame
table_data = soup.find_all('table')[0] # Найти таблицу
df = pd.read_html(str(table_data))[0]
Интеграция с базами данных: Использование библиотек, таких как SQLAlchemy или pyodbc, для подключения и извлечения данных из баз.
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('sqlite:///example.db')
df = pd.read_sql('SELECT * FROM data_table', con=engine)
Анализ данных
После сбора нужно провести анализ для понимания структуры данных и выявления проблем, которые требуют предобработки.
Можно использовать готовые функции из Pandas для того, чтобы выявить проблемы, такие как пропуски или выбросы:
head () выводит первые несколько строк таблицы, чтобы вы могли примерно ознакомиться с содержимым данных.
info () показывает количество непустых значений в каждом столбце и тип данных в них (целые числа, вещественные числа и т.д.).
describe () предоставляет сводную статистику, по числовым признакам: среднее, стандартное отклонение, минимальное и максимальное значения; для категориальных: количество уникальных категорий и частота самой ТОПовой.
Пример кода для анализа данных:
# Просмотр первых строк таблицы
display(df.head())
# Получение информации о типах данных и наличии пропусков
display(df.info())
# Статистическое описание числовых признаков
display(df.describe())
# Проверка на наличие дубликатов
duplicates_count = df.duplicated().sum()
print(f"\nКоличество дубликатов: {duplicates_count}")
Важно: display можно заменить на print, если вы работаете не в Jupyter-notebook, но тогда вывод на экран будет не таким наглядным.
На этом этапе можно найти следующие проблемы, которые потребуют дальнейшей предобработки:
Пропуски. В столбцах «Площадь (кв. м)», «Число комнат», «Возраст дома (лет)» и «Цена (млн руб.)» — пропуски, которые нужно заполнить или обработать.
Некорректные значения:
В столбце «Возраст дома (лет)» присутствует значение -5.
В столбце «Площадь (кв. м)» указано ошибочное отрицательное значение -150.
Выбросы:
Значения, такие как площадь 2000 кв. м и 500 кв. м, подозрительно высокие для квартир и могут считаться выбросами.
Цена 70 млн руб. также выделяется среди остальных значений, что может указывать на выброс.
Этап 2 — очистка данных
После анализа данных можно приступать к очистке. Цель этапа — устранить проблемы, такие как пропуски, ошибки и выбросы, чтобы повысить качество датасета и, как следствие, предсказания модели.
Ручная очистка данных. Для удаления дубликатов или строк с ошибками можно использовать методы Pandas, для работы с NaN-значениями пригодится Numpy:
import numpy as np
# Удаление дубликатов
df = df.drop_duplicates()
# Удаление строк с некорректным значением возраста
df = df[df['Возраст дома (лет)'] >= 0]
# Замена ошибочных значений на NaN для последующей обработки
df.loc[df['Площадь (кв. м)'] < 0, 'Площадь (кв. м)'] = np.nan
Автоматизация очистки данных
Для автоматической очистки данных можно использовать библиотеку Scikit-Learn, например, SimpleImputer для заполнения пропусков.
Если у вас есть ошибочные значения, которые удобнее обработать как пропуски, перед использованием SimpleImputer их нужно заменить на NaN.
В этом случае пример кода будет выглядеть так:
from sklearn.impute import SimpleImputer
# Замена отрицательных значений на NaN
df.loc[df['Площадь (кв. м)'] < 0, 'Площадь (кв. м)'] = np.nan
# Использование SimpleImputer для заполнения пропусков
imputer = SimpleImputer(strategy='mean')
df[['Площадь (кв. м)', 'Число комнат', 'Возраст дома (лет)']] = imputer.fit_transform(df[['Площадь (кв. м)', 'Число комнат', 'Возраст дома (лет)']])
Вообще, пропуски в данных могут возникать по разным причинам: отсутствие информации, ошибки при сборе данных и т.д. Для их обработки можно использовать еще несколько подходов.
Удаление строк или столбцов с пропусками
Если пропуски присутствуют в небольшом количестве в одном признаке и не содержат важной информации, такие строки можно просто удалить. А если их много в одном столбце — можно полностью его удалить.
# Удаление всех строк, содержащих хотя бы один пропуск
df = df.dropna()
# Удаление всех столбцов, содержащих хотя бы один пропуск
df = df.dropna(axis=1)
Этот метод используется, когда данных достаточно, и потеря нескольких строк не повлияет на анализ.
Заполнение пропусков
Среднее или медиана: для числовых данных можно использовать среднее значение или медиану. Упрощенная альтернатива SimpleImputer — метод filina из библиотеки Pandas.
Пример:
# Заполнение пропусков средним значением
df['Площадь (кв. м)'] = df['Площадь (кв. м)'].fillna(df['Площадь (кв. м)'].mean())
Медиану стоит применять, когда данные содержат выбросы, потому что она менее чувствительна к экстремальным значениям. Например, для признака «зарплата» медиана подходит лучше среднего, если в данных встречаются несколько аномально высоких зарплат.
Метод ближайших соседей (KNN): учитывает значения признаков ближайших объектов для заполнения пропусков. Перед применением метода нужно закодировать или удалить категориальные признаки, потому что он работает только с числовыми.
Пример:
from sklearn.impute import KNNImputer
from sklearn.preprocessing import LabelEncoder
# Кодирование категориального признака
encoder = LabelEncoder()
df['Тип недвижимости'] = encoder.fit_transform(df['Тип недвижимости'])
# Заполнение пропусков с использованием KNNImputer
imputer = KNNImputer(n_neighbors=2)
df[['Площадь (кв. м)', 'Число комнат', 'Возраст дома (лет)', 'Цена (млн руб.)']] = imputer.fit_transform(df[['Площадь (кв. м)', 'Число комнат', 'Возраст дома (лет)', 'Цена (млн руб.)']])
Метод полезен, когда значения признаков взаимосвязаны и пропуски можно логически предсказать на основе других значений.
Заполнение специальными значениями: Например, можно заполнить пропуски значением «неизвестно» для категориальных признаков или »0» для числовых, если это имеет смысл в контексте данных.
Обработка выбросов и устранение шумов
Выбросы — это значения, которые сильно отличаются от остальных данных. Они могут находиться далеко от большинства и обычно возникают из-за ошибок сбора данных или редких, необычных событий.
Шумы — это случайные или непреднамеренные вариации значений, которые не содержат полезной информации. Могут возникать из-за ошибок измерения, проблем с оборудованием, влияния внешних факторов или просто случайных изменений, которые не связаны с основной задачей анализа.
Шумы и выбросы могут привести к неверным выводам модели, затрудняя выделение значимых признаков. Например, если использовать алгоритм линейной регрессии — он пытается найти линию, которая минимизирует ошибки между прогнозом и фактом. Выбросы, которые сильно отличаются от остальных данных, могут «тянуть» эту линию и искажать результат.
Методы работы с выбросами
Обнаружение выбросов
Boxplot («Ящик с усами»): используется для визуализации выбросов. Выбросы отображаются как точки, находящиеся за пределами «усов» графика.
Пример:
import matplotlib.pyplot as plt
import seaborn as sns
# Визуализация выбросов с помощью boxplot
plt.figure(figsize=(8, 5))
sns.boxplot(x=df['Цена (млн руб.)'])
plt.title('Выбросы в цене квартир')
plt.show()
Такой график поможет быстро оценить, какие значения сильно выбиваются из общего распределения
Метод межквартильного размаха (IQR): статистический метод, который используется для определения выбросов. Значения за пределами диапазона [Q1 — 1.5 * IQR, Q3 + 1.5 * IQR] считаются выбросами. Если данные содержат множество выбросов, можно использовать более жесткое ограничение, например, [Q1 — 3 * IQR, Q3 + 3 * IQR].
Пример:
# Определение границ для выбросов
Q1 = df['Цена (млн руб.)'].quantile(0.25)
Q3 = df['Цена (млн руб.)'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Обнаружение выбросов
outliers = df[(df['Цена (млн руб.)'] < lower_bound) | (df['Цена (млн руб.)'] > upper_bound)]
print(f"Количество выбросов: {len(выбросы)}")
print("Найдены выбросы:\n", outliers)
Обработка выбросов
Удаление выбросов: если выбросы — это результат ошибок или они не отражают реальные данные, их можно удалить.
Пример:
# Удаление выбросов
df = df[(df['Цена (млн руб.)'] >= lower_bound) & (df['Цена (млн руб.)'] <= upper_bound)]
Трансформация данных: если выбросы связаны с высокой вариативностью признака, можно использовать логарифмическую или другую нелинейную трансформацию.
Обратите внимание, что логарифмическая трансформация применима только к положительным значениям.
Пример:
# Логарифмическая трансформация признака
df['Цена (млн руб.)'] = df['Цена (млн руб.)'].apply(lambda x: np.log1p(x) if x > 0 else x)
Логарифмирование помогает уменьшить влияние больших значений и сделать распределение данных более симметричным.
Использование робастных моделей. Некоторые модели устойчивы к выбросам, что помогает минимизировать их влияние. В отличие от линейной регрессии, робастные методы, такие как RANSAC, адаптируются к выбросам, исключая аномальные точки при создании модели.
Пример:
from sklearn.linear_model import RANSACRegressor
from sklearn.linear_model import LinearRegression
# Пример использования робастной регрессии
model = RANSACRegressor(base_estimator=LinearRegression(), random_state=42)
X = df[['Площадь (кв. м)', 'Число комнат', 'Возраст дома (лет)']]
y = df['Цена (млн руб.)']
model.fit(X, y)
Методы обработки шумов
Обнаружение шумов
Шумы могут быть обнаружены с помощью визуализации данных. Методы вроде анализа временных графиков помогают увидеть колебания, которые можно считать шумом. Для временных рядов можно использовать скользящие средние, чтобы лучше понять общие тренды и отбросить случайные колебания.
Сглаживание данных
Сглаживание данных используется, чтобы уменьшить влияние случайных колебаний. Это особенно полезно для временных рядов, где присутствуют нерегулярные скачки. Сглаживание можно выполнить с помощью скользящего среднего.
Удаление или сглаживание шумов
Применение фильтров, таких как медианный или фильтр скользящего среднего, помогает сгладить шумы, особенно во временных данных. Первый эффективен для устранения выбросов, а второй подходит для сглаживания временных данных.
Пример:
# Пример сглаживания с использованием скользящего среднего
df['Цена (млн руб.)'] = df['Цена (млн руб.)'].rolling(window=3, min_periods=1).mean()
Этот код сглаживает цену, используя среднее значение соседних трех элементов. Параметр min_periods=1 помогает избежать появления NaN в начале ряда.
Устранение аномальных значений
Робастные методы. В случае табличных данных шумы могут быть похожи на выбросы. Например, незначительные ошибки, такие как «цена на 5% выше или ниже ожидаемого значения», можно сгладить с помощью робастных методов, которые менее чувствительны к небольшим отклонениям. Также такие методы, как RANSAC или Theil-Sen Estimator, помогают уменьшить влияние выбросов. Они присваивают меньший вес значениям, которые сильно отклоняются от общей тенденции.
Сглаживание кривых (Spline Fitting). Подходит для данных с трендом, которые содержат случайные колебания. Сплайны представляют данные в виде гладкой функции, чтобы устранить мелкие шумы и сохранить основную структуру, в первую очередь используются для аппроксимации данных.
Этап 3 — кодирование категориальных данных
На этом этапе категориальные признаки преобразуются в числовую форму, потому что большинство алгоритмов машинного обучения могут работать только с числовыми данными. В нашем датасете есть два категориальных признака: «Тип недвижимости» и «Район».
Для этого используют несколько методов.
Label Encoding
Метод, при котором каждой категории присваивается уникальное числовое значение. Подходит для категорий с естественным порядком (например, «низкий», «средний», «высокий») или небольшим количеством вариантов.
Важно: если порядок категорий не имеет значения, использование Label Encoding может привести к некорректной интерпретации данных моделью.
Пример кода:
from sklearn.preprocessing import LabelEncoder
# Применение Label Encoding к столбцу "Тип недвижимости" (если категории имеют естественный порядок)
encoder = LabelEncoder()
df['Тип недвижимости'] = encoder.fit_transform(df['Тип недвижимости'])
print(df[['ID', 'Тип недвижимости']])
В результате применения LabelEncoder категории «квартира», «дом», «апартаменты» будут преобразованы в числовые значения, например, 0, 1, 2.
One-Hot Encoding
Метод, который для каждой категории создает отдельный бинарный признак, указывающий на принадлежность объекта к этой категории. Полезен, если категории не обладают естественным порядком.
Обратите внимание: при большом количестве уникальных категорий One-Hot Encoding может сильно увеличить размер данных. Это снизит производительность и потребует больше памяти. В таких случаях лучше использовать альтернативы, например, Target Encoding.
Пример кода One-Hot Encoding:
# Применение One-Hot Encoding к столбцу "Район"
df = pd.get_dummies(df, columns=['Район'], prefix='Район')
print(df.head())
В результате применения One-Hot Encoding к столбцу «Район» будут созданы новые столбцы: «Район_А», «Район_Б», «Район_В» со значениями 0 или 1, указывающие, к какому району принадлежит каждая строка.
Пример кода Target Encoding
# Применение Target Encoding к категориальному признаку "Район"
mean_encoding = df.groupby('Район')['Цена (млн руб.)'].mean().to_dict()
df['Район_encoded'] = df['Район'].map(mean_encoding)
df[['ID', 'Район', 'Район_encoded']]
Этап 4 — разделение данных на обучающую и тестовую выборки
Этот этап помогает оценить, как хорошо модель будет справляться с новыми данными, а также помогает вовремя обнаружить переобучение.
Основные подходы
Разделение на обучающую и тестовую выборки (Train-Test Split)
Обычно данные делятся на две части: обучающая выборка (80% данных) и тестовая выборка (20% данных), которая используется для оценки точности на данных, которые модель ранее не видела.
Пример кода:
from sklearn.model_selection import train_test_split
# Разделение данных на обучающую и тестовую выборки
X = df.drop(columns=['Цена (млн руб.)', 'ID']) # Признаки (features), удаляем ID как неинформативный признак
y = df['Цена (млн руб.)'] # Целевая переменная (target)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print("Размер обучающей выборки:", X_train.shape)
print("Размер тестовой выборки:", X_test.shape)
В этом коде мы используем функцию train_test_split из библиотеки Scikit-Learn для разделения данных. Параметр test_size=0.2 указывает, что 20% информации будет использовано для тестирования, а параметр random_state=42 нужен, чтобы при каждом запуске код делил данные одинаково.
Делить данные на выборки можно с учётом времени (out-of-time подход, в тестирование таким образом попадают более новые объекты) или без этого (out-of-sample).
Кросс-валидация (Cross-Validation)
Используется для более точной оценки модели. Вместо одного разделения данные разбиваются на несколько частей (folds), и модель обучается на k-1 частях, тестируясь на оставшейся. Процесс повторяется k раз, чтобы каждая часть данных побывала в тестовой выборке.
Перемешивание данных (shuffle=True) помогает избежать смещения и помогает получить более точную оценку.
Пример кода:
from sklearn.model_selection import KFold
# Создание объекта KFold для кросс-валидации
kf = KFold(n_splits=5, shuffle=True, random_state=42)
for train_index, test_index in kf.split(X):
X_train, X_test = X.loc[train_index], X.loc[test_index]
y_train, y_test = y.loc[train_index], y.loc[test_index]
# Обучение и тестирование модели происходит внутри этого цикла
В примере выше KFold делит данные на 5 частей и повторяет процесс обучения 5 раз: каждый раз на одной из частей запускается тест, а на остальных –- обучение.
Если решается задача классификации, и целевая переменная несбалансирована, стоит использовать StratifiedKFold, который сохраняет пропорцию классов в каждой выборке.
Этап 5 — масштабирование признаков
Масштабирование нужно для приведения числовых признаков к единому масштабу. Это важно для алгоритмов, таких как линейная регрессия, SVM и KNN, чтобы улучшить их сходимость.
Важно: прежде чем проводить масштабирование, нужно разделить данные на обучающую и тестовую выборки. Это помогает избежать утечки данных и оценить качество модели на новой информации.
Разберем основные методы масштабирования.
Стандартизация (Standardization)
Приведение признаков к нулевому среднему и стандартному отклонению, равному единице. Стандартизация делает признаки сопоставимыми по масштабу, но не обязательно приводит их к нормальному распределению.
Пример кода:
from sklearn.preprocessing import StandardScaler
# Применение стандартизации к числовым признакам (сначала обучаем скейлер на обучающих данных)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test) # Применение обученного скейлера к тестовой выборке
print(X_train_scaled[:5]) # Пример первых пяти строк стандартизированных данных
В результате применения StandardScaler, признаки, такие как «Площадь (кв. м)» и «Цена (млн руб.)», будут иметь среднее значение около 0 и стандартное отклонение 1. Но это не означает, что их распределение станет нормальным.
Нормализация (Min-Max Scaling)
Нормализация приводит значения признака к диапазону от 0 до 1, чтобы сделать их сопоставимыми. Она полезна, если у данных разные масштабы, что может мешать работе модели.
Нормализация важна для алгоритмов, чувствительных к масштабу признаков, таких как KNN или SVM. Но, если в данных есть выбросы, Min-Max нормализация может сжать остальные значения, потому что учитывает экстремальные.
Пример кода:
from sklearn.preprocessing import MinMaxScaler
# Применение нормализации к числовым признакам
minmax_scaler = MinMaxScaler()
X_train_scaled = minmax_scaler.fit_transform(X_train[numeric_features])
X_test_scaled = minmax_scaler.transform(X_test[numeric_features])
print(X_train_scaled[:5])
После применения MinMaxScaler, все числовые признаки будут находиться в диапазоне [0, 1].
Робастное масштабирование (Robust Scaling):
Использование медианы и межквартильного размаха для приведения данных к единому масштабу. Этот метод полезен, если в данных присутствуют выбросы, потому что он менее чувствителен к аномально большим значениям.
Пример кода:
from sklearn.preprocessing import RobustScaler
# Применение робастного масштабирования к числовым признакам
robust_scaler = RobustScaler()
X_train_scaled_robust = robust_scaler.fit_transform(X_train[numeric_features])
X_test_scaled_robust = robust_scaler.transform(X_test[numeric_features])
print(X_train_scaled_robust[:5])
RobustScaler помогает уменьшить влияние выбросов, сохраняя важную информацию в данных.
Этап 6 — Feature Engineering
Формально Feature Engineering, или генерация признаков, — это отдельный этап в ML, который не относится к предобработке данных. Но мы включили его, чтобы показать, как завершается работа с данными перед обучением модели.
Специалисты извлекают, создают или трансформируют признаки, чтобы алгоритм лучше распознавал важные закономерности.
Примеры:
Создание новых признаков на основе существующих («цена за квадратный метр»).
Разделение числовых признаков на категории (группировка возраста дома на «новый», «средний», «старый»).
Извлечение временных признаков (например, выделение дня недели или месяца из даты).
Эти действия помогают модели лучше понимать структуру данных и улучшить качество предсказаний.
Полезные материалы и ссылки по теме
Документация Pandas: подробное руководство по использованию библиотеки для предобработки данных, включая работу с пропусками, фильтрацию и другие полезные методы.
Документация Scikit-Learn: разделы по предобработке данных, включая стандартные скейлеры, кодирование категориальных данных и создание Pipeline.
Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow, Aurélien Géron: книга содержит примеры и практические советы по предобработке данных с фокусом на использовании Python и Scikit-Learn.
Python for Data Analysis, Wes McKinney: основной ресурс по Pandas, написанный создателем библиотеки. В книге разбираются различные техники предобработки, очистки и анализа данных.
StatQuest — видеозаписи на YouTube с ясными и доступными объяснениями базовых понятий предобработки данных и ML-алгоритмов.
Kaggle Learn: курсы и практические задания по предобработке данных с использованием реальных датасетов.
Kaggle: платформа, где можно найти датасеты и проекты, попробовать выполнить предобработку данных самостоятельно и участвовать в соревнованиях.
Google Colab: интерактивная среда для написания и запуска Python-кода, в которой можно бесплатно работать с большими датасетами и библиотеками, такими как Pandas и Scikit-Learn.
ТГУ и Skillfactory создали магистерскую программу для тех, кто хочет глубже погрузиться в Data Science и машинное обучение. Она охватывает различные области применения — от IT и маркетинга до медицины. Студенты освоят базу по математике и программированию на Python, научатся работать с реальными данными на кейсах IT-компаний — партнеров программы.