Один мужик сделал операцию по омоложению лица. "Ну, надо бы походить, поспрашивать народ - помолодел ли я?" Вышел, идёт, довольный идёт. Подошёл к остановке. — Девушка, как вы думаете - сколько мне лет? — Ну, думаю 27 — Нет, мне 42! Пришёл в бар мужик. — Сколько мне лет? - спрашивает он у людей около данной стойки — 32? 30? 29? - начали гадать посетители бара — Нет-нет-нет! Мне 42. Вернулся мужик к остановке, довольный собой. Видит, бабушка стоит. — Здравствуйте! Как думаете, сколько мне лет? — У меня, сынок, зрение - ни к черту, давай я тебя "там" потрогаю - сразу определю. Ну, мужику интересно стало - как это так, по яйцам, она определит - и согласился. Мнёт старуха минуту, мнёт две. Наконец, говорит. — Тебе 42 года. — Как вы узнали!? - удивился мужик — В баре услышала.
1.1 MiB
Сбор и подготовка данных¶
Датасет №1. Продажи домов¶
Проблемная область: Данный набор данных о продажах домов касается недвижимости.
Объекты наблюдения: Объектом наблюдения в данном случае является каждый отдельный дом (единица недвижимости), который был продан. Каждая строка в таблице представляет собой один дом.
Атрибуты объектов:
id
— уникальный идентификатор дома.date
— дата продажи.price
— цена продажи дома (целевая переменная).bedrooms
— количество спален.bathrooms
— количество ванных комнат.sqft_living
— общая жилая площадь (в квадратных футах).sqft_lot
— площадь участка.floors
— количество этажей.waterfront
— есть ли выход на воду.view
— наличие вида из окон.condition
— состояние дома (оценка).grade
— оценка качества дома.sqft_above
— площадь дома над землей.sqft_basement
— площадь подвала.yr_built
— год постройки.yr_renovated
— год последнего ремонта.zipcode
— почтовый индекс.lat
иlong
— географические координаты дома.sqft_living15
иsqft_lot15
— средняя площадь жилой площади и участка для 15 ближайших домов.
Бизнес-цель: Улучшенное прогнозирование цен поможет продавцам устанавливать конкурентные цены, а покупателям — принимать более взвешенные решения о покупке. Это также даст риелторам возможность лучше ориентироваться на рынке и оптимизировать стратегию продажи.
Техническая цель: Прогнозирование цен на жилье
Входные данные: Исторические данные о продажах домов, включая все признаки (количество комнат, площадь, состояние, местоположение и др.).
Целевая переменная: Цена (price
).
import pandas as pd
df = pd.read_csv(".//static//csv//kc_house_data.csv")
df.head()
Отбросим лишний признак id
, который не будет принимать участие в анализе данного набора данных
df.drop(columns=['id'], inplace=True)
Получение сведений о пропущенных данных¶
# Количество пустых значений признаков
print(df.isnull().sum())
print()
# Есть ли пустые значения признаков
print(df.isnull().any())
print()
# Процент пустых значений признаков
for i in df.columns:
null_rate = df[i].isnull().sum() / len(df) * 100
if null_rate > 0:
print(f"{i} процент пустых значений: %{null_rate:.2f}")
Пропущенных данных в датасете не обнаружено
Проверка набора данных на выбросы¶
import matplotlib.pyplot as plt
import seaborn as sns
# Выбираем столбцы для анализа
columns_to_check = ['price', 'sqft_living', 'bathrooms', 'yr_built']
# Функция для подсчета выбросов
def count_outliers(df, columns):
outliers_count = {}
for col in columns:
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Считаем количество выбросов
outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)]
outliers_count[col] = len(outliers)
return outliers_count
# Подсчитываем выбросы
outliers_count = count_outliers(df, columns_to_check)
# Выводим количество выбросов для каждого столбца
for col, count in outliers_count.items():
print(f"Количество выбросов в столбце '{col}': {count}")
# Создаем гистограммы
plt.figure(figsize=(15, 10))
for i, col in enumerate(columns_to_check, 1):
plt.subplot(2, 3, i)
sns.histplot(df[col], kde=True)
plt.title(f'Histogram of {col}')
plt.tight_layout()
plt.show()
Признак yr_built
не имеет выбросов, а для признаков price
, sqft_living
и bathrooms
необходимо использовать метод решения проблемы выбросов. Так как в рассматриваемом наборе данных количество наблюдений достаточно велико (более 21 тыс.), то для решения проблемы выбросов данных воспользуемся методом удаления наблюдений с такими выбросами:
# Выбираем столбцы для очистки
columns_to_clean = ['price', 'sqft_living', 'bathrooms']
# Функция для удаления выбросов
def remove_outliers(df, columns):
for col in columns:
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Удаляем строки, содержащие выбросы
df = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)]
return df
# Удаляем выбросы
df_cleaned = remove_outliers(df, columns_to_clean)
# Выводим количество удаленных строк
print(f"Количество удаленных строк: {len(df) - len(df_cleaned)}")
df = df_cleaned
Оценим выбросы в выборке после удаления некоторых наблюдений:
columns_to_check = ['price', 'sqft_living', 'bathrooms']
# Подсчитываем выбросы
outliers_count = count_outliers(df, columns_to_check)
# Выводим количество выбросов для каждого столбца
for col, count in outliers_count.items():
print(f"Количество выбросов в столбце '{col}': {count}")
# Создаем гистограммы
plt.figure(figsize=(15, 10))
for i, col in enumerate(columns_to_check, 1):
plt.subplot(2, 3, i)
sns.histplot(df[col], kde=True)
plt.title(f'Histogram of {col}')
plt.tight_layout()
plt.show()
Судя по данным на диаграмме выше, количество выбросов значительно сократилось и не превышает допустимые диапозоны.
Разбиение датасета на выборки¶
from sklearn.model_selection import train_test_split
train_data, temp_data = train_test_split(df, test_size=0.3, random_state=42)
val_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42)
# Средние значения цены
print("Средняя цена в обучающей выборке:", train_data['price'].mean())
print("Средняя цена в контрольной выборке:", val_data['price'].mean())
print("Средняя цена в тестовой выборке:", test_data['price'].mean())
print()
# Стандартное отклонение цены
print("Стандартное отклонение цены в обучающей выборке:", train_data['price'].std())
print("Стандартное отклонение цены в контрольной выборке:", val_data['price'].std())
print("Стандартное отклонение цены в тестовой выборке:", test_data['price'].std())
print()
# Проверка распределений по количеству объектов в диапазонах
print("Распределение по квартилам (обучающая):")
print(train_data['price'].quantile([0.25, 0.5, 0.75]))
print()
print("Распределение по квартилам (контрольная):")
print(val_data['price'].quantile([0.25, 0.5, 0.75]))
print()
print("Распределение по квартилам (тестовая):")
print(test_data['price'].quantile([0.25, 0.5, 0.75]))
# Построение гистограмм для каждой выборки
plt.figure(figsize=(12, 6))
sns.histplot(train_data['price'], color='blue', label='Train', kde=True)
sns.histplot(val_data['price'], color='green', label='Validation', kde=True)
sns.histplot(test_data['price'], color='red', label='Test', kde=True)
plt.legend()
plt.xlabel('Price')
plt.ylabel('Frequency')
plt.title('Распределение цены в обучающей, контрольной и тестовой выборках')
plt.show()
Выборки оказались недостаточно сбалансированными. Используем методы приращения данных с избытком и с недостатком:
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
def oversample(df, target_column):
X = df.drop(target_column, axis=1)
y = df[target_column]
oversampler = RandomOverSampler(random_state=42)
x_resampled, y_resampled = oversampler.fit_resample(X, y)
resampled_df = pd.concat([x_resampled, y_resampled], axis=1)
return resampled_df
def undersample(df, target_column):
X = df.drop(target_column, axis=1)
y = df[target_column]
undersampler = RandomUnderSampler(random_state=42)
x_resampled, y_resampled = undersampler.fit_resample(X, y)
resampled_df = pd.concat([x_resampled, y_resampled], axis=1)
return resampled_df
train_df_oversampled = oversample(train_data, 'price')
val_df_oversampled = oversample(val_data, 'price')
test_df_oversampled = oversample(test_data, 'price')
train_df_undersampled = undersample(train_data, 'price')
val_df_undersampled = undersample(val_data, 'price')
test_df_undersampled = undersample(test_data, 'price')
# Построение гистограмм для каждой выборки
plt.figure(figsize=(12, 6))
sns.histplot(train_df_undersampled['price'], color='blue', label='Train', kde=True)
sns.histplot(val_df_undersampled['price'], color='green', label='Validation', kde=True)
sns.histplot(test_df_undersampled['price'], color='red', label='Test', kde=True)
plt.legend()
plt.xlabel('Price')
plt.ylabel('Frequency')
plt.title('Распределение цены в обучающей, контрольной и тестовой выборках (андерсемплинг)')
plt.show()
# Построение гистограмм для каждой выборки
plt.figure(figsize=(12, 6))
sns.histplot(train_df_oversampled['price'], color='blue', label='Train', kde=True)
sns.histplot(val_df_oversampled['price'], color='green', label='Validation', kde=True)
sns.histplot(test_df_oversampled['price'], color='red', label='Test', kde=True)
plt.legend()
plt.xlabel('Price')
plt.ylabel('Frequency')
plt.title('Распределение цены в обучающей, контрольной и тестовой выборках (оверсемплинг)')
plt.show()
Датасет №2. Ближайшие к Земле объекты¶
Проблемная область: Данный набор данных связан с наблюдением за объектами, которые проходят рядом с Землей.
Объекты наблюдения: Объектами наблюдения являются "Ближайшие к Земле объекты", которые представляют собой астероиды или кометы, проходящие относительно близко к орбите Земли.
Атрибуты объектов:
id
— уникальный идентификатор объекта.name
— название или идентификатор объекта (например, имя или дата открытия).est_diameter_min
— минимальный оценочный диаметр объекта (в километрах или других единицах).est_diameter_max
— максимальный оценочный диаметр объекта.relative_velocity
— относительная скорость объекта (по отношению к Земле) в км/ч.miss_distance
— расстояние между объектом и Землей в момент его ближайшего прохождения (в километрах).orbiting_body
— небесное тело, вокруг которого объект совершает орбитальное движение (в данном случае это Земля).sentry_object
— булевый показатель (True/False), указывающий, отслеживается ли объект системой Sentry для оценки возможных столкновений в будущем.absolute_magnitude
— абсолютная звездная величина объекта, которая помогает определить его яркость и, соответственно, размер.hazardous
— булевый показатель (True/False), который указывает, представляет ли объект потенциальную опасность для Земли (включает анализ его размера, скорости и расстояния).
Бизнес-цель: Разработка стратегии защиты планеты, создание технологий защиты, что может привести к увеличению инвестиций в аэрокосмическую индустрию и соответствующие разработки.
Техническая цель: Оптимизация стратегии отклонения или разрушения опасных объектов.
Входные данные: Данные о космических объектах, включая все признаки (диаметр объекта, расстояние между объектом и Землей и др.).
Целевая переменная: Опасность (hazardous
).
import pandas as pd
df = pd.read_csv(".//static//csv//neo_v2.csv")
df.head()
Отбросим признаки orbiting_body
и sentry_object
, так как все они имеют одинаковое значение во всех записях. Также отбросим признак name
, так как он не будет иметь пользу при прогнозировании опасности объекта.
df = df.drop(columns=['name', 'orbiting_body', 'sentry_object'])
Получение сведений о пропущенных данных¶
# Количество пустых значений признаков
print(df.isnull().sum())
print()
# Есть ли пустые значения признаков
print(df.isnull().any())
print()
# Процент пустых значений признаков
for i in df.columns:
null_rate = df[i].isnull().sum() / len(df) * 100
if null_rate > 0:
print(f"{i} процент пустых значений: %{null_rate:.2f}")
Пропущенных данных в датасете не обнаружено
Проверка набора данных на выбросы¶
import matplotlib.pyplot as plt
import seaborn as sns
# Выбираем столбцы для анализа
columns_to_check = ['est_diameter_min', 'est_diameter_max', 'relative_velocity', 'miss_distance', 'absolute_magnitude']
# Функция для подсчета выбросов
def count_outliers(df, columns):
outliers_count = {}
for col in columns:
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Считаем количество выбросов
outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)]
outliers_count[col] = len(outliers)
return outliers_count
# Подсчитываем выбросы
outliers_count = count_outliers(df, columns_to_check)
# Выводим количество выбросов для каждого столбца
for col, count in outliers_count.items():
print(f"Количество выбросов в столбце '{col}': {count}")
# Создаем гистограммы
plt.figure(figsize=(15, 10))
for i, col in enumerate(columns_to_check, 1):
plt.subplot(2, 3, i)
sns.histplot(df[col], kde=True)
plt.title(f'Histogram of {col}')
plt.tight_layout()
plt.show()
Признак miss_distance
не имеет выбросов, у признака absolute_magnitude
количество выбросов находится в приемлемом диапазоне, а для признаков est_diameter_min
, est_diameter_max
и relative_velocity
необходимо использовать метод решения проблемы выбросов. Воспользуемся методом усреднения значений:
columns_to_fix = ['est_diameter_min', 'est_diameter_max', 'relative_velocity']
for column in columns_to_fix:
q1 = df[column].quantile(0.25)
q3 = df[column].quantile(0.75)
iqr = q3 - q1
# Определяем границы для выбросов
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr
# Устраняем выбросы: заменяем значения ниже нижней границы на саму нижнюю границу, а выше верхней — на верхнюю
df[column] = df[column].apply(lambda x: lower_bound if x < lower_bound else upper_bound if x > upper_bound else x)
Оценим выбросы в выборке после усреднения:
columns_to_check = ['est_diameter_min', 'est_diameter_max', 'relative_velocity']
# Подсчитываем выбросы
outliers_count = count_outliers(df, columns_to_check)
# Выводим количество выбросов для каждого столбца
for col, count in outliers_count.items():
print(f"Количество выбросов в столбце '{col}': {count}")
# Создаем гистограммы
plt.figure(figsize=(15, 10))
for i, col in enumerate(columns_to_check, 1):
plt.subplot(2, 3, i)
sns.histplot(df[col], kde=True)
plt.title(f'Histogram of {col}')
plt.tight_layout()
plt.show()
Судя по данным на диаграмме выше, нам удалось избавиться от выбросов в соответствующих признаках.
Разбиение датасета на выборки¶
from sklearn.model_selection import train_test_split
train_data, temp_data = train_test_split(df, test_size=0.3, random_state=42)
val_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42)
print("Обучающая выборка: ", train_data.shape)
print(train_data.hazardous.value_counts())
hazardous_counts = train_data['hazardous'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(hazardous_counts, labels=hazardous_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов hazardous в обучающей выборке')
plt.show()
print("Контрольная выборка: ", val_data.shape)
print(val_data.hazardous.value_counts())
hazardous_counts = val_data['hazardous'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(hazardous_counts, labels=hazardous_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов hazardous в контрольной выборке')
plt.show()
print("Тестовая выборка: ", test_data.shape)
print(test_data.hazardous.value_counts())
hazardous_counts = test_data['hazardous'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(hazardous_counts, labels=hazardous_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов hazardous в тестовой выборке')
plt.show()
Как видно из круговых диаграмм, распределение классов сильно смещено, что может привести к проблемам в обучении модели, так как модель будет обучаться в основном на одном классе. В таком случае имеет смысл рассмотреть методы аугментации данных.
Аугментация данных методом оверсемплинга¶
Этот метод увеличивает количество примеров меньшинства.
from imblearn.over_sampling import ADASYN
# Создание экземпляра ADASYN
ada = ADASYN()
# Применение ADASYN
X_resampled, y_resampled = ada.fit_resample(train_data.drop(columns=['hazardous']), train_data['hazardous'])
# Создание нового DataFrame
df_train_adasyn = pd.DataFrame(X_resampled)
df_train_adasyn['hazardous'] = y_resampled # Добавление целевой переменной
# Вывод информации о новой выборке
print("Обучающая выборка после оверсемплинга: ", df_train_adasyn.shape)
print(df_train_adasyn['hazardous'].value_counts())
hazardous_counts = df_train_adasyn['hazardous'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(hazardous_counts, labels=hazardous_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов hazardous в обучающей выборке после оверсемплинга')
plt.show()
Аугментация данных методом андерсемплинга¶
Проведём также приращение данных методом выборки с недостатком (андерсемплинг). Этот метод помогает сбалансировать выборку, уменьшая количество экземпляров класса большинства, чтобы привести его в соответствие с классом меньшинства.
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler()
# Применение RandomUnderSampler
X_resampled, y_resampled = rus.fit_resample(train_data.drop(columns=['hazardous']), train_data['hazardous'])
# Создание нового DataFrame
df_train_undersampled = pd.DataFrame(X_resampled)
df_train_undersampled['hazardous'] = y_resampled # Добавление целевой переменной
# Вывод информации о новой выборке
print("Обучающая выборка после андерсемплинга: ", df_train_undersampled.shape)
print(df_train_undersampled['hazardous'].value_counts())
# Визуализация распределения классов
hazardous_counts = df_train_undersampled['hazardous'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(hazardous_counts, labels=hazardous_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов hazardous в обучающей выборке после андерсемплинга')
plt.show()
Датасет №3. Данные о диабете индейцев Пима¶
Проблемная область: Данный набор данных связан с наблюдением о наличии диабета у женщин из группы коренного народа Пима, основываясь на медицинских показателях. Диабет является хроническим заболеванием, которое требует длительного лечения и оказывает значительное влияние на качество жизни пациентов.
Объекты наблюдения: Каждая строка (запись) в наборе данных соответствует одному пациенту из группы индейцев Пима.
Атрибуты объектов:
Pregnancies
- количество беременностей у пациента.Glucose
- уровень глюкозы в крови.BloodPressure
- диастолическое артериальное давление (мм рт. ст.).SkinThickness
- толщина кожной складки на трицепсе (мм).Insulin
- уровень инсулина в сыворотке крови (мЕд/мл).BMI
- индекс массы тела (вес в кг/кв. м роста).DiabetesPedigreeFunction
- коэффициент наследственной предрасположенности к диабету.Age
- возраст пациента.Outcome
- целевой признак, показывающий наличие (1) или отсутствие (0) диабета.
Бизнес-цель: Оптимизация страховых предложений. Страховые компании могут предложить индивидуализированные тарифы, исходя из вероятности возникновения у пациента диабета, что позволит снизить риски и сделать страхование доступнее.
Техническая цель: Разработка предсказательной модели для классификации пациентов по риску. На основании этого риска можно сформировать динамические предложения для клиентов.
Входные данные: Данные о пациентах.
Целевая переменная: Диагноз диабета (Outcome
).
import pandas as pd
df = pd.read_csv(".//static//csv//diabetes.csv")
df.head()
Получение сведений о пропущенных данных¶
# Количество пустых значений признаков
print(df.isnull().sum())
print()
# Есть ли пустые значения признаков
print(df.isnull().any())
print()
# Процент пустых значений признаков
for i in df.columns:
null_rate = df[i].isnull().sum() / len(df) * 100
if null_rate > 0:
print(f"{i} процент пустых значений: %{null_rate:.2f}")
Пропущенных данных в датасете не обнаружено
Проверка набора данных на выбросы¶
import matplotlib.pyplot as plt
import seaborn as sns
# Выбираем столбцы для анализа
columns_to_check = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
# Функция для подсчета выбросов
def count_outliers(df, columns):
outliers_count = {}
for col in columns:
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Считаем количество выбросов
outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)]
outliers_count[col] = len(outliers)
return outliers_count
# Подсчитываем выбросы
outliers_count = count_outliers(df, columns_to_check)
# Выводим количество выбросов для каждого столбца
for col, count in outliers_count.items():
print(f"Количество выбросов в столбце '{col}': {count}")
# Создаем гистограммы
plt.figure(figsize=(15, 10))
for i, col in enumerate(columns_to_check, 1):
plt.subplot(2, 4, i)
sns.histplot(df[col], kde=True)
plt.title(f'Histogram of {col}')
plt.tight_layout()
plt.show()
Объемы выбросов по различным признакам оказались в приемлемых границах. Усреднение выбросов не требуется.
Разбиение датасета на выборки¶
from sklearn.model_selection import train_test_split
train_data, temp_data = train_test_split(df, test_size=0.3, random_state=42)
val_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42)
print("Обучающая выборка: ", train_data.shape)
print(train_data.Outcome.value_counts())
outcome_counts = train_data['Outcome'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(outcome_counts, labels=outcome_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов Outcome в обучающей выборке')
plt.show()
print("Контрольная выборка: ", val_data.shape)
print(val_data.Outcome.value_counts())
outcome_counts = val_data['Outcome'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(outcome_counts, labels=outcome_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов Outcome в контрольной выборке')
plt.show()
print("Тестовая выборка: ", test_data.shape)
print(test_data.Outcome.value_counts())
outcome_counts = test_data['Outcome'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(outcome_counts, labels=outcome_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов Outcome в тестовой выборке')
plt.show()
Как видно из круговых диаграмм, распределение классов достаточно смещено, что может привести к проблемам в обучении модели, так как модель будет обучаться в большей степени на одном классе. В таком случае имеет смысл рассмотреть методы аугментации данных.
Аугментация данных методом оверсемплинга¶
Этот метод увеличивает количество примеров меньшинства.
from imblearn.over_sampling import ADASYN
# Создание экземпляра ADASYN
ada = ADASYN()
# Применение ADASYN
X_resampled, y_resampled = ada.fit_resample(train_data.drop(columns=['Outcome']), train_data['Outcome'])
# Создание нового DataFrame
df_train_adasyn = pd.DataFrame(X_resampled)
df_train_adasyn['Outcome'] = y_resampled # Добавление целевой переменной
# Вывод информации о новой выборке
print("Обучающая выборка после оверсемплинга: ", df_train_adasyn.shape)
print(df_train_adasyn['Outcome'].value_counts())
counts = df_train_adasyn['Outcome'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(counts, labels=counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов Outcome в обучающей выборке после оверсемплинга')
plt.show()
Аугментация данных методом андерсемплинга¶
Проведём также приращение данных методом выборки с недостатком (андерсемплинг). Этот метод помогает сбалансировать выборку, уменьшая количество экземпляров класса большинства, чтобы привести его в соответствие с классом меньшинства.
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler()
# Применение RandomUnderSampler
X_resampled, y_resampled = rus.fit_resample(train_data.drop(columns=['Outcome']), train_data['Outcome'])
# Создание нового DataFrame
df_train_undersampled = pd.DataFrame(X_resampled)
df_train_undersampled['Outcome'] = y_resampled # Добавление целевой переменной
# Вывод информации о новой выборке
print("Обучающая выборка после андерсемплинга: ", df_train_undersampled.shape)
print(df_train_undersampled['Outcome'].value_counts())
# Визуализация распределения классов
hazardous_counts = df_train_undersampled['Outcome'].value_counts()
plt.figure(figsize=(2, 2))
plt.pie(hazardous_counts, labels=hazardous_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Распределение классов hazardous в обучающей выборке после андерсемплинга')
plt.show()