Лаб. работа “Предобработка данных”
Лабораторная работа: Методы предобработки данных в интеллектуальных системах
Цель работы
Изучение и практическое применение основных методов предобработки данных: обработка пропусков, кодирование категориальных признаков, масштабирование числовых признаков и работа с выбросами. Формирование навыков подготовки наборов данных для их использования в моделях машинного обучения.
Краткие теоретические сведения
Предобработка данных (Data Preprocessing) — это этап подготовки “сырых” данных к анализу и построению моделей. Качество данных напрямую влияет на производительность и точность интеллектуальных систем. Основные задачи предобработки включают:
Обработка пропущенных значений: Данные могут отсутствовать по разным причинам. Основные стратегии:
- Удаление: Удаление строк или столбцов с пропусками. Целесообразно, если пропусков мало или столбец неинформативен.
- Заполнение (Imputation): Замена пропусков некоторым значением:
- Среднее (mean): Для числовых признаков без сильных выбросов.
- Медиана (median): Для числовых признаков с выбросами, так как медиана более устойчива к ним.
- Мода (mode): Для категориальных признаков (заполнение наиболее часто встречающимся значением).
- Константа: Заполнение нулем, строкой “unknown” и т.д.
Кодирование категориальных признаков: Большинство моделей машинного обучения работают с числами, поэтому текстовые категории нужно преобразовать.
- Label Encoding (Порядковое кодирование): Каждой уникальной категории присваивается целое число (0, 1, 2…). Подходит для порядковых признаков, где есть естественная иерархия (например, “плохо”, “хорошо”, “отлично”).
- One-Hot Encoding (Прямое кодирование): Для каждой категории создается новый бинарный столбец (0 или 1). Подходит для номинальных признаков, где нет порядка (например, “красный”, “зеленый”, “синий”).
Исходный признак Label Encoding One-Hot Encoding (color_red, color_green) red 0 1, 0 green 1 0, 1 red 0 1, 0 Масштабирование числовых признаков: Признаки с разными диапазонами значений (например, возраст от 0 до 100 и доход от 20 000 до 200 000) могут некорректно влиять на модели, основанные на расстоянии (kNN, SVM) или градиентном спуске.
- Стандартизация (Standardization): Приводит данные к распределению со средним \(0\) и стандартным отклонением \(1\). \[ Z = \frac{x - \mu}{\sigma} \] где \(\mu\) — среднее значение, \(\sigma\) — стандартное отклонение.
- Нормализация (Normalization): Масштабирует данные в заданный диапазон, обычно \([0, 1]\). \[ X_{norm} = \frac{x - x_{min}}{x_{max} - x_{min}} \] где \(x_{min}\) и \(x_{max}\) — минимальное и максимальное значения признака.
Обработка выбросов (Outliers): Выбросы — это значения, которые сильно отличаются от основной массы данных. Они могут искажать результаты обучения. Один из популярных методов их обнаружения — метод межквартильного размаха (IQR). Выбросами считаются значения, выходящие за пределы:
- Нижняя граница: \(Q_1 - 1.5 \times IQR\)
- Верхняя граница: \(Q_3 + 1.5 \times IQR\) где \(Q_1\) — первый квартиль (25-й перцентиль), \(Q_3\) — третий квартиль (75-й перцентиль), \(IQR = Q_3 - Q_1\).
Порядок выполнения работы
Работа выполняется в среде Python с использованием библиотек pandas, numpy, scikit-learn и matplotlib/seaborn.
Подготовка окружения. Установите необходимые библиотеки, если они отсутствуют:
Загрузка и первичное исследование данных. Мы будем использовать классический набор данных “Титаник”, который содержит пропуски, категориальные и числовые признаки.
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt # Загружаем датасет из библиотеки seaborn df = sns.load_dataset('titanic') # Выводим общую информацию о датасете print("Информация о датасете:") df.info() # Выводим первые 5 строк print("\nПервые 5 строк датасета:") print(df.head()) # Статистика по числовым признакам print("\nСтатистика по числовым признакам:") print(df.describe())Обработка пропущенных значений. Найдем столбцы с пропущенными значениями.
age(возраст): Заполним пропуски медианным значением, так как распределение возраста может быть скошенным.embarked(порт посадки): Это категориальный признак. Заполним пропуски модой.deck(палуба): Слишком много пропусков. Этот столбец проще удалить.embark_town: Дублирует информациюembarked, его тоже можно удалить.
# Заполнение 'age' медианой median_age = df['age'].median() df['age'].fillna(median_age, inplace=True) # Заполнение 'embarked' модой mode_embarked = df['embarked'].mode()[0] df['embarked'].fillna(mode_embarked, inplace=True) # Удаление столбцов df.drop(['deck', 'embark_town'], axis=1, inplace=True) # Проверяем, что пропусков не осталось (кроме 'age' и 'embarked') print("\nКоличество пропусков после обработки:") print(df.isnull().sum())Кодирование категориальных признаков. Преобразуем столбцы
sex,embarked,class,who,adult_male,alive,alone. Для примера используем One-Hot Encoding дляsexиembarked.# Применение One-Hot Encoding к 'sex' и 'embarked' df_processed = pd.get_dummies(df, columns=['sex', 'embarked'], drop_first=True) # Удалим и другие некатегориальные, но не числовые столбцы для упрощения # Или те, что не несут пользы для гипотетической модели df_processed.drop(['pclass', 'who', 'adult_male', 'class', 'alive', 'alone'], axis=1, inplace=True) print("\nДатасет после One-Hot Encoding:") print(df_processed.head())drop_first=Trueиспользуется для удаления одного из новых столбцов, чтобы избежать мультиколлинеарности (избыточности).Масштабирование числовых признаков. Применим стандартизацию к признакам
ageиfare.from sklearn.preprocessing import StandardScaler scaler = StandardScaler() # Выбираем столбцы для масштабирования cols_to_scale = ['age', 'fare'] df_processed[cols_to_scale] = scaler.fit_transform(df_processed[cols_to_scale]) print("\nДатасет после масштабирования 'age' и 'fare':") print(df_processed.head())Работа с выбросами (на примере
fare). Визуализируем признакfareдо и после обработки выбросов.plt.figure(figsize=(10, 4)) plt.subplot(1, 2, 1) sns.boxplot(y=df_processed['fare']) plt.title('Boxplot для Fare (до обработки выбросов)') # Расчет IQR для 'fare' Q1 = df_processed['fare'].quantile(0.25) Q3 = df_processed['fare'].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR # Ограничение выбросов (Capping) df_processed['fare'] = np.where(df_processed['fare'] > upper_bound, upper_bound, df_processed['fare']) df_processed['fare'] = np.where(df_processed['fare'] < lower_bound, lower_bound, df_processed['fare']) plt.subplot(1, 2, 2) sns.boxplot(y=df_processed['fare']) plt.title('Boxplot для Fare (после обработки выбросов)') plt.tight_layout() plt.show() print("\nФинальный вид обработанного датасета:") print(df_processed.head())
Задания для самостоятельной работы
Задание 1
- Повторить все шаги, описанные в разделе “Порядок выполнения работы”.
- В отчете подробно описать каждый шаг, приложить фрагменты кода и результаты его выполнения (вывод
info,head,describe, графики). - В заключении ответить на вопрос: почему для заполнения
ageбыла выбрана медиана, а не среднее?
Задание 2
- Загрузить датасет “Титаник”.
- Для обработки пропусков в столбце
ageиспользовать среднее значение. - Для кодирования признака
sexприменить Label Encoding вместо One-Hot Encoding. - Масштабировать признаки
ageиfareс помощью нормализации (MinMaxScaler). - Сравнить статистические показатели (
describe()) датасета до и после масштабирования. - В заключении проанализировать, в каких случаях применение Label Encoding для признака
sexможет быть некорректным.
Задание 3
- Загрузить датасет “Титаник”.
- Столбец
ageс пропусками не заполнять, а удалить все строки, где возраст не указан. Сравнить размер датасета до и после удаления. - Категориальные признаки
sexиembarkedзакодировать с помощью One-Hot Encoding. - Выполнить стандартизацию для признака
fare. - Найти и удалить выбросы в признаке
fareпо методу IQR (удалить строки, а не ограничить значения). - В заключении оценить, какой подход к обработке пропусков в
age(удаление строк или заполнение медианой) привел к большей потере данных.
Требования к отчету
Отчет по лабораторной работе должен содержать:
Цель работы.
Постановка задачи в соответствии с вариантом.
Ход работы: последовательное описание выполненных шагов с приведением ключевых фрагментов кода, скриншотов и/или таблиц с результатами (например, вывод
.info(),.describe(),.head()).Графики и их анализ (например, boxplot для выбросов).
Выводы по работе, включающие ответы на вопросы из задания по варианту и общую оценку проделанной работы.
Контрольные вопросы
- Зачем нужна предобработка данных? Какие проблемы она решает?
- В чем разница между заполнением пропусков средним, медианой и модой? Когда какой метод предпочтительнее?
- Объясните разницу между стандартизацией и нормализацией. Для каких алгоритмов масштабирование признаков критически важно?
- В чем принципиальное отличие One-Hot Encoding от Label Encoding? Приведите примеры признаков, для которых подходит каждый из этих методов.
- Что такое выбросы и какими методами их можно обнаружить и обработать?