423 KiB
Лабораторная работа 2. Анализ нескольких датасетов.¶
1.Выбрать три набора данных, которые не соответствуют Вашему варианту задания¶
Выбранны варианты: Данные по инсультам(Вариант 4), Продажи домов(Вариант 6), Цены на мобильные устройства (Вариант 18)
2. Провести анализ сведений о каждом наборе данных со страницы загрузки в Kaggle. Какова проблемная область?¶
Данные по инсультам:¶
- Проблемная область: Анализ данных о пациентах с инсультом
- Цели: Анализ данных о пациентах с инсультом, определение факторов, влияющих на исход лечения
- Набор данных: 5111 записей, 12 переменных:
- id
- gender
- age
- hypertension
- heart_disease
- ever_married
- work_type
- residence_typr
- avg_glucose_level
- bmi
- smoking_status
- stroke
- Описание данных: Сведения о пациентах с инсультом, их лечении и исходе лечения
Продажи домов:¶
- Проблемная область: Анализ продаж домов и их цен в зависисмости от различных факторов
- Цели: Анализ продаж домов, определение факторов, влияющих на цены
- Набор данных: 21614 записей, 21 переменная:
- id
- date
- price
- bedrooms
- bathrooms
- sqft_living
- sqft_loft
- floors
- waterfront
- view
- condition
- grade
- sqft_above
- sqft_basment
- yr_build
- yr_renovated
- zipcode
- lat
- longsqft_living15
- sqft_lot15
- Описание данных: Сведения о проданных домах в King County, США
Цены на мобильные устройства:¶
- Проблемная область: Анализ цен на мобильные устройства
- Цели: Анализ цен на мобильные устройства, определение факторов, влияющих на цены
- Набор данных: 1371 записей, 18 переменных:
- id
- name
- rating
- spec_score
- no_of_sim
- ram
- battery
- camera
- external_memory
- android_version
- price
- company
- inbuild_memory
- fast_charging
- screen_resolution
- processor
- processor_name
- Описание данных: Сведения о ценах на мобильные устройства в зависимости от различных факторов
Данные по инсультам:¶
Каждая строка в датасете содержит соответствующую информацию о пациенте, что позволяет проводить анализ и строить модели для предсказания риска инсульта.
import pandas as pd
var4 = pd.read_csv("./datasets/var4/healthcare-dataset-stroke-data.csv")
var4
var4.dtypes
Продажи домов¶
Каждая строка в датасете содержит соответствующую информацию о доме, что позволяет проводить анализ и строить модели для предсказания его цены.
var6 = pd.read_csv("./datasets/var6/kc_house_data.csv")
var6
var6.dtypes
Цены на мобильные устройства¶
Каждая строка в датасете содержит соответствующую информацию о мобильном устройстве, что позволяет проводить анализ и строить модели для предсказания его цены.
var18 = pd.read_csv("./datasets/var18/mobile_phone_price_prediction.csv")
var18
var18.dtypes
3. Провести анализ содержимого каждого набора данных. Что является объектом/объектами наблюдения? Каковы атрибуты объектов? Есть ли связи между объектами?¶
- Датасет о риске инсульта
- Объект наблюжения: Пациенты
- Датасет о продажах недвижимости
- Объект наблюдения: Сделки по проданным домам в King Country, США
- Датасет о цене мобильных устройств
- Объект наблюдения: Модели телефонов и их цены
Все аттрибуты были перечислены выше.
4. Привести примеры бизнес-целей, для достижения которых могут подойти выбранные наборы данных. Каков эффект для бизнеса?¶
- Датасет о риске инсульта
- Бизнес-цель: Определить факторы риска инсульта и предохранить пациентов от инсульта.
- Эффект для бизнеса: Снижение количества случаев инсульта, снижение затрат на лечение и улучшение репутации клиники.
- Датасет о продажах недвижимости
- Бизнес-цель: Определить факторы, влияющие на продажи недвижимости
- Эффект для бизнеса: Улучшение стратегии продаж, повышение эффективности подбора имущества для последующего извлесения прибыли
- Датасет о цене мобильных устройств
- Бизнес-цель: Определить факторы, влияющие на цену мобильных устройств
- Эффект для бизнеса: Улучшение стратегии ценообразования, повышение эффективности продаж и прибыли.
5. Привести примеры целей технического проекта для каждой выделенной ранее бизнес-цели. Что поступает на вход, что является целевым признаком?¶
- Датасет о риске инсульта
- Бизнес-цель: Разработка системы раннего предупреждения инсульта.
- Цель технического проекта: Создание модели машинного обучения для прогнозирования вероятности инсульта.
- Входные данные: Пол Возраст Наличие гипертензии Наличие сердечных заболеваний Статус брака Тип работы Тип проживания Средний уровень глюкозы Индекс массы тела Статус курения и т.д.
- Целевой признак: Наличие инсульта (stroke).
- Датасет о продажах недвижимости
- Бизнес-цель: Развитие системы рекомендации недвижимости рекомендованной к покупке для последующей перепродажи.
- Цель технического проекта: Разработка модели машинного обучения для прогнозирования цены недвижимости.
- Входные данные: Площадь Площадь комнат Площадь участка Тип дома Тип комнат и другие признаки.
- Целевой признак: Цена недвижимости (Price).
- Датасет о цене мобильных устройств
- Бизнес-цель: Оптимизация ценообразования и улучшение стратегии продаж мобильных устройств.
- Цель технического проекта: Построение модели для предсказания рекомендованной цены мобильного устройства на основе характеристик.
- Входные данные: Имя Рейтинг Очки производительности Кол-во SIM-слотов Оперативная память Емкость аккумклятора Дисплей Камера Дополнительные слоты для карт памяти и остальное.
- Целевой признак: Очки производительности (Spec_score).
6. Определить проблемы выбранных наборов данных: зашумленность, смещение, актуальность, выбросы, просачивание данных.¶
7. Привести примеры решения обнаруженных проблем для каждого набора данных¶¶
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# 1. Проверка на зашумленность ---- количество пропусков в процентах от общего кол-ва
def check_noise(dataframe):
total_values = dataframe.size
missing_values = dataframe.isnull().sum().sum()
noise_percentage = (missing_values / total_values) * 100
return f"Зашумленность: {noise_percentage:.2f}%"
# 2. Проверка на смещение ----- объем уникальных значений внутри определнной колонки
def check_bias(dataframe, target_column):
if target_column in dataframe.columns:
unique_values = dataframe[target_column].nunique()
total_values = len(dataframe)
bias_percentage = (unique_values / total_values) * 100
return f"Смещение по {target_column}: {bias_percentage:.2f}% уникальных значений"
return "Целевой признак не найден."
# 3. Проверка на дубликаты
def check_duplicates(dataframe):
duplicate_percentage = dataframe.duplicated().mean() * 100
return f"Количество дубликатов: {duplicate_percentage:.2f}%"
# 4. Проверка на выбросы
def check_outliers(dataframe, column):
if column in dataframe.columns:
Q1 = dataframe[column].quantile(0.25)
Q3 = dataframe[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outlier_count = dataframe[(dataframe[column] < lower_bound) | (dataframe[column] > upper_bound)].shape[0]
total_count = dataframe.shape[0]
outlier_percentage = (outlier_count / total_count) * 100
return f"Выбросы по {column}: {outlier_percentage:.2f}%"
return f"Признак {column} не найден."
# 5. Проверка на просачивание данных
def check_data_leakage(dataframe, target_column):
if target_column in dataframe.columns:
correlation_matrix = dataframe.select_dtypes(include=[np.number]).corr()
leakage_info = correlation_matrix[target_column].abs().nlargest(10)
leakage_report = ", ".join([f"{feature}: {value:.2f}" for feature, value in leakage_info.items() if feature != target_column])
return f"Признаки просачивания данных: {leakage_report}"
return "Целевой признак не найден."
Датасет о риске инсульта:¶
noise_columns = check_noise(var4)
bias_info = check_bias(var4, 'avg_glucose_level')
duplicate_count = check_duplicates(var4)
outliers_data = check_outliers(var4, 'avg_glucose_level')
leakage_info = check_data_leakage(var4, 'stroke')
print(noise_columns)
print(bias_info)
print(duplicate_count)
print(outliers_data)
print(leakage_info)
Датасет о продажах недвижимости:¶
noise_columns = check_noise(var6)
bias_info = check_bias(var6, 'price')
duplicate_count = check_duplicates(var6)
outliers_data = check_outliers(var6, 'yr_renovated')
leakage_info = check_data_leakage(var6, 'condition')
print(noise_columns)
print(bias_info)
print(duplicate_count)
print(outliers_data)
print(leakage_info)
Датасет о цене мобильных устройств:¶
noise_columns = check_noise(var18)
bias_info = check_bias(var18, 'company')
duplicate_count = check_duplicates(var18)
outliers_data = check_outliers(var18, 'Spec_score')
leakage_info = check_data_leakage(var18, 'Rating')
print(noise_columns)
print(bias_info)
print(duplicate_count)
print(outliers_data)
print(leakage_info)
9. Устранить проблему пропущенных данных. Для каждого набора данных использовать разные методы: удаление, подстановка константного значения (0 или подобное), подстановка среднего значения¶
# Инсульт
var4.isnull().sum()
var4['bmi'] = var4['bmi'].fillna(var4['bmi'].mean())
var4.isnull().sum()
#Дома
var6.isnull().sum()
#Мобильные устройства
var18.isnull().sum()
var18['Android_version'] = var18['Android_version'].fillna('No info')
var18['Inbuilt_memory'] = var18['Android_version'].fillna('No info')
var18['fast_charging'] = var18['Android_version'].fillna('No info')
var18['Screen_resolution'] = var18['Android_version'].fillna('No info')
var18['Processor'] = var18['Android_version'].fillna('No info')
var18.isnull().sum()
10. Выполнить разбиение каждого набора данных на обучающую, контрольную и тестовую выборк趶
from sklearn.model_selection import train_test_split
# Разбиение var4 (Инсульт)
original_var4_size = len(var4)
train_var4, temp_var4 = train_test_split(var4, test_size=0.2, random_state=42)
val_var4, test_var4 = train_test_split(temp_var4, test_size=0.5, random_state=42)
print("var4 Dataset:")
print(f"Train: {len(train_var4)/original_var4_size*100:.2f}%")
print(f"Validation: {len(val_var4)/original_var4_size*100:.2f}%")
print(f"Test: {len(test_var4)/original_var4_size*100:.2f}%\n")
# Разбиение var6 (Дома)
original_var6_size = len(var6)
train_var6, temp_var6 = train_test_split(var6, test_size=0.2, random_state=42)
val_var6, test_var6 = train_test_split(temp_var6, test_size=0.5, random_state=42)
print("var6 Dataset:")
print(f"Train: {len(train_var6)/original_var6_size*100:.2f}%")
print(f"Validation: {len(val_var6)/original_var6_size*100:.2f}%")
print(f"Test: {len(test_var6)/original_var6_size*100:.2f}%\n")
# Разбиение var18 (Мобильные устройства)
original_var18_size = len(var18)
train_var18, temp_var18 = train_test_split(var18, test_size=0.2, random_state=42)
val_var18, test_var18 = train_test_split(temp_var18, test_size=0.5, random_state=42)
print("var18 Dataset:")
print(f"Train: {len(train_var18)/original_var18_size*100:.2f}%")
print(f"Validation: {len(val_var18)/original_var18_size*100:.2f}%")
print(f"Test: {len(test_var18)/original_var18_size*100:.2f}%\n")
11. Оценить сбалансированность выборок для каждого набора данных. Оценить необходимость использования методов приращения (аугментации) данных.¶
12. Выполнить приращение данных методами выборки с избытком (oversampling) и выборки с недостатком (undersampling). Должны быть представлены примеры реализации обоих методов для выборок каждого набора данных.¶
def plot_sample_balance(y, sample_name):
plt.figure(figsize=(8, 5))
sns.histplot(y, bins=30, kde=True)
plt.title(f'Распределение целевой переменной для {sample_name}')
plt.xlabel(sample_name)
plt.ylabel('Частота')
plt.show()
# Оценка сбалансированности выборок
plot_sample_balance(train_var6['price'], 'Train var6')
plot_sample_balance(val_var6['price'], 'Validation var6')
plot_sample_balance(test_var6['price'], 'Test var6')
Распределения выборок у данного датасета выглядят схоже. Это говорит о сбалансированности выборок.
plot_sample_balance(train_var4['stroke'], 'Train var4')
plot_sample_balance(val_var4['stroke'], 'Validation var4')
plot_sample_balance(test_var4['stroke'], 'Test var4')
Выборки выглядят схоже, но у всех трех имеется явный дисбаланс классов. Это проблема, т.к в дальнейшем не сможем обучить какую-либо модель.
plot_sample_balance(train_var18['Spec_score'], 'Train var18')
plot_sample_balance(val_var18['Spec_score'], 'Validation var18')
plot_sample_balance(test_var18['Spec_score'], 'Test var18')
Распределения выборок у данного датасета выглядят схоже. Это говорит о сбалансированности выборок. Однако в тренировочной выборке значительно больший размах значений
12. Выполнить приращение данных методами выборки с избытком (oversampling) и выборки с недостатком (undersampling). Должны быть представлены примеры реализации обоих методов для выборок каждого набора данных¶
Инсульт¶
from imblearn.over_sampling import SMOTE
X_var4 = var4.drop('stroke', axis=1)
y_var4 = var4['stroke']
# Кодирование категориальных признаков
for column in X_var4.select_dtypes(include=['object']).columns:
X_var4[column] = X_var4[column].astype('category').cat.codes
# Теперь применяем SMOTE
smote = SMOTE(random_state=42)
X_resampled_var4, y_resampled_var4 = smote.fit_resample(X_var4, y_var4)
# Получаем результаты
print(f'После oversampling (var4): {pd.Series(y_resampled_var4).value_counts()}')
from imblearn.under_sampling import RandomUnderSampler
# Undersampling для var4
undersample = RandomUnderSampler(random_state=42)
X_under_var4, y_under_var4 = undersample.fit_resample(X_var4, y_var4)
print(f'После undersampling (var4): {pd.Series(y_under_var4).value_counts()}')
Дома¶
X_var6 = var6.drop('Price', axis=1)
y_var6 = var6['Price']
# Кодирование категориальных признаков
for column in X_var6.select_dtypes(include=['object']).columns:
X_var6[column] = X_var6[column].astype('category').cat.codes
# Теперь применяем SMOTE
smote = SMOTE(random_state=42)
X_resampled_var6, y_resampled_var6 = smote.fit_resample(X_var6, y_var6)
# Получаем результаты
print(f'После oversampling (var6): {pd.Series(y_resampled_var6).value_counts()}')
X_var18 = var18.drop('Price', axis=1)
y_var18 = var18['Price']
# Кодирование категориальных признаков
for column in X_var18.select_dtypes(include=['object']).columns:
X_var18[column] = X_var18[column].astype('category').cat.codes
# Теперь применяем SMOTE
smote = SMOTE(random_state=42)
X_resampled_var18, y_resampled_var18 = smote.fit_resample(X_var18, y_var18)
# Получаем результаты
print(f'После oversampling (var18): {pd.Series(y_resampled_var18).value_counts()}')
from imblearn.under_sampling import RandomUnderSampler
# Undersampling для var4
undersample = RandomUnderSampler(random_state=42)
X_under_var4, y_under_var4 = undersample.fit_resample(X_var4, y_var4)
print(f'После undersampling (var4): {pd.Series(y_under_var4).value_counts()}')
В данном случае у нас есть только один датасет, предназначенный для решения задачи классификации (инсульт). Проблему дисбаланса в нем мы решили применив undersampling & oversampling.
Два остальных датасета не содержат классов, т.к предназначены для решения задачи регрессии (предсказания цен на недвижимость или цены мобильного устройства), поэтому выполнять приращение данных не требуется.