284 KiB
284 KiB
In [5]:
import pandas as pd;
df = pd.read_csv("data/diabetes.csv")
df.columns
Out[5]:
Определение бизнес целей:¶
- Предсказание риска развития диабета. Данная цель поможет определить людей с высоким риском заболевания, что полезно для профилактических программ и эффективного медицинского вмешательства.
- Анализ ключевых факторов, влияющих на диабет. Позволит выявить основные факторы риска и разработать рекомендации для улучшения здоровья населения.
Определение целей технического проекта:¶
- Построить модель, которая сможет прогнозировать наличие диабета, основываясь на других параметрах.
- Провести анализ данных для выявления факторов, которые больше всего влияют на риск развития диабета.
Проверим данные на пустые значения¶
In [6]:
for i in df.columns:
null_rate = df[i].isnull().sum() / len(df) * 100
if null_rate > 0:
print(f'{i} Процент пустых значений: %{null_rate:.2f}')
print(df.isnull().sum())
df.isnull().any()
Out[6]:
Пустые и номинальные значения отсутствуют. Разделение данных на обучающую, тестовую и контрольную выборки
In [7]:
from sklearn.model_selection import train_test_split
train_data, test_data = train_test_split(df, test_size=0.2, random_state=42)
train_data, val_data = train_test_split(df, test_size=0.2, random_state=42)
print("Размер обучающей выборки: ", len(train_data))
print("Размер контрольной выборки: ", len(val_data))
print("Размер тестовой выборки: ", len(test_data))
Оценка сбалансированности целевой переменной (Outcome). Визуализация распределения целевой переменной в выборках (гистограмма)
In [8]:
import seaborn as sns
import matplotlib.pyplot as plt
def plot_outcome_distribution(data, title):
sns.histplot(data['Outcome'], kde=True)
plt.title(title)
plt.xlabel('Outcome')
plt.ylabel('Частота')
plt.show()
plot_outcome_distribution(train_data, 'Распределение Outcome в обучающей выборке')
plot_outcome_distribution(val_data, 'Распределение Outcome в контрольной выборке')
plot_outcome_distribution(test_data, 'Распределение Outcome в тестовой выборке')
print("Среднее значение Outcome в обучающей выборке: ", train_data['Outcome'].mean())
print("Среднее значение Outcome в контрольной выборке: ", val_data['Outcome'].mean())
print("Среднее значение Outcome в тестовой выборке: ", test_data['Outcome'].mean())
In [9]:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
sns.countplot(x=train_data['Outcome'])
plt.title('Распределение Outcome в обучающей выборке')
plt.xlabel('Outcome')
plt.ylabel('Частота')
plt.show()
ros = RandomOverSampler(random_state=42)
X_train = train_data.drop(columns=['Outcome'])
y_train = train_data['Outcome']
X_resampled, y_resampled = ros.fit_resample(X_train, y_train)
sns.countplot(x=y_resampled)
plt.title('Распределение Outcome после oversampling')
plt.xlabel('Outcome')
plt.ylabel('Частота')
plt.show()
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_resampled, y_resampled)
sns.countplot(x=y_resampled)
plt.title('Распределение Outcome после undersampling')
plt.xlabel('Outcome')
plt.ylabel('Частота')
plt.show()
print("Размер обучающей выборки после oversampling и undersampling: ", len(X_resampled))
Конструирование признаков¶
Унитарное кодирование - замена категориальных признаков бинарными значениями.
Дискретизация числовых признаков - процесс преобразования непрерывных числовых значений в дискретные категории или интервалы (бины).
In [10]:
categorical_features = ['Pregnancies', 'Outcome']
train_data_encoded = pd.get_dummies(train_data, columns=categorical_features)
val_data_encoded = pd.get_dummies(val_data, columns=categorical_features)
test_data_encoded = pd.get_dummies(test_data, columns=categorical_features)
print("Столбцы train_data_encoded:", train_data_encoded.columns.tolist())
print("Столбцы val_data_encoded:", val_data_encoded.columns.tolist())
print("Столбцы test_data_encoded:", test_data_encoded.columns.tolist())
train_data_encoded['Glucose_binned'] = pd.cut(train_data_encoded['Glucose'], bins=5, labels=False)
val_data_encoded['Glucose_binned'] = pd.cut(val_data_encoded['Glucose'], bins=5, labels=False)
test_data_encoded['Glucose_binned'] = pd.cut(test_data_encoded['Glucose'], bins=5, labels=False)
Ручной синтез¶
Создание новых признаков на основе экспертных знаний и логики предметной области. К примеру, можно создать признак, который отражает соотношение уровня глюкозы к индексу массы тела
In [11]:
train_data_encoded['glucose_to_bmi'] = train_data_encoded['Glucose'] / train_data_encoded['BMI']
val_data_encoded['glucose_to_bmi'] = val_data_encoded['Glucose'] / val_data_encoded['BMI']
test_data_encoded['glucose_to_bmi'] = test_data_encoded['Glucose'] / test_data_encoded['BMI']
test_data_encoded
Out[11]:
Масштабирование признаков¶
Масштабирование признаков - это процесс изменения диапазона признаков, чтобы равномерно распределить значения.
In [12]:
from sklearn.preprocessing import StandardScaler
numerical_features = ['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
scaler = StandardScaler()
train_data_encoded[numerical_features] = scaler.fit_transform(train_data_encoded[numerical_features])
val_data_encoded[numerical_features] = scaler.transform(val_data_encoded[numerical_features])
test_data_encoded[numerical_features] = scaler.transform(test_data_encoded[numerical_features])
Конструирование признаков с применением фреймворка Featuretools¶
In [13]:
import featuretools as ft
print("Столбцы в df:", df.columns.tolist())
print("Столбцы в train_data_encoded:", train_data_encoded.columns.tolist())
print("Столбцы в val_data_encoded:", val_data_encoded.columns.tolist())
print("Столбцы в test_data_encoded:", test_data_encoded.columns.tolist())
# Удаление дубликатов по всем столбцам (если нет уникального идентификатора)
df = df.drop_duplicates()
duplicates = train_data_encoded[train_data_encoded.duplicated(keep=False)]
#Создание EntitySet
es = ft.EntitySet(id='diabetes_data')
#Добавление датафрейма в EntitySet
es = es.add_dataframe(dataframe_name='patients', dataframe=train_data_encoded, index='id')
#Генерация признаков
feature_matrix, feature_defs = ft.dfs(entityset=es, target_dataframe_name='patients', max_depth=2)
feature_matrix
Out[13]:
Оценка качества¶
In [ ]:
import time
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# Разделение данных на обучающую и валидационную выборки. Удаляем целевую переменную
X = df.drop('Glucose', axis=1)
y = df['Glucose']
# One-hot encoding для категориальных переменных (преобразование категориальных объектов в числовые)
X = pd.get_dummies(X, drop_first=True)
# Проверяем, есть ли пропущенные значения, и заполняем их медианой или другим подходящим значением
X.fillna(X.median(), inplace=True)
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
# Обучение модели
model = LinearRegression()
# Начинаем отсчет времени
start_time = time.time()
model.fit(X_train, y_train)
# Время обучения модели
train_time = time.time() - start_time
# Предсказания и оценка модели
val_predictions = model.predict(X_val)
mse = mean_squared_error(y_val, val_predictions)
r2 = r2_score(y_val, val_predictions)
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
print(f'Коэффициент детерминации (R²): {r2:.2f}')
# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.scatter(y_val, val_predictions, alpha=0.5)
plt.plot([y_val.min(), y_val.max()], [y_val.min(), y_val.max()], 'k--', lw=2)
plt.xlabel('Фактический уровень глюкозы')
plt.ylabel('Прогнозируемый уровень глюкозы')
plt.title('Фактический уровень глюкозы по сравнению с прогнозируемым')
plt.show()