801 KiB
801 KiB
In [9]:
# Импорт необходимых библиотек
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# Загрузка данных
data = pd.read_csv("data/healthcare-dataset-stroke-data.csv")
# Первичный обзор данных
print("Размеры датасета:", data.shape)
data.head()
Out[9]:
Конструирование признаков
In [10]:
from sklearn.preprocessing import LabelEncoder, MinMaxScaler
# Преобразование целевой переменной
data["stroke"] = data["stroke"].map({1: 1, 0: 0}) # Целевая переменная уже числовая
# Бинарные категориальные признаки
binary_cols = [
"hypertension",
"heart_disease",
]
for col in binary_cols:
if col in data.columns:
data[col] = data[col].map({1: 1, 0: 0})
# Преобразование признака пола
data["gender"] = data["gender"].map({"Female": 1, "Male": 0, "Other": None})
# Нормализация числовых данных
scaler = MinMaxScaler()
numeric_cols = ["age", "avg_glucose_level", "bmi"]
data[numeric_cols] = scaler.fit_transform(data[numeric_cols])
# Преобразование категориальных переменных с помощью LabelEncoder
label_encoder = LabelEncoder()
# Преобразуем 'ever_married', 'work_type', 'Residence_type', и 'smoking_status'
categorical_cols = ["ever_married", "work_type", "Residence_type", "smoking_status"]
for col in categorical_cols:
if col in data.columns:
data[col] = label_encoder.fit_transform(data[col])
print("Обработка данных завершена. Размеры итогового датасета:", data.shape)
data
Out[10]:
In [11]:
# Проверка данных на пропуски
print("Обзор пропусков в данных:")
print(data.isnull().sum())
# Вывод статистик по данным
print("Статистические характеристики данных:")
print(data.describe())
# Удаление или обработка пропущенных данных
# Пример: удаление строк с пропусками (если применимо)
data = data.dropna()
print("Размеры данных после обработки пропусков:", data.shape)
Выборки
In [12]:
from sklearn.model_selection import train_test_split
# Разделение данных на признаки (X) и целевую переменную (y)
X = data.drop(columns=["stroke"])
y = data["stroke"]
# Разделение на обучающую и тестовую выборки (80% на обучение, 20% на тестирование)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"Размер обучающей выборки: {X_train.shape[0]} строк")
print(f"Размер тестовой выборки: {X_test.shape[0]} строк")
Обучение
In [13]:
from sklearn.metrics import (
accuracy_score,
classification_report,
confusion_matrix,
roc_auc_score,
roc_curve,
)
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
# Функция для визуализации матрицы ошибок
def plot_confusion_matrix(conf_matrix, model_name):
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt="d", cmap="Blues", cbar=False)
plt.xlabel("Предсказанный класс")
plt.ylabel("Истинный класс")
plt.title(f"Матрица ошибок для {model_name}")
plt.show()
# Инициализация моделей
log_reg = LogisticRegression(random_state=42, max_iter=1000)
rf_clf = RandomForestClassifier(random_state=42)
gb_clf = GradientBoostingClassifier(random_state=42)
# Словарь моделей для перебора
models = {
"Logistic Regression": log_reg,
"Random Forest": rf_clf,
"Gradient Boosting": gb_clf,
}
# Словарь для хранения результатов
results = {}
# Обучение и оценка моделей
for name, model in models.items():
model.fit(X_train, y_train) # Обучаем модель
y_pred = model.predict(X_test) # Предсказываем на тестовой выборке
accuracy = accuracy_score(y_test, y_pred) # Точность
auc_score = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) # ROC AUC
classification_rep = classification_report(
y_test, y_pred, output_dict=True
) # Отчет по классификации
conf_matrix = confusion_matrix(y_test, y_pred) # Матрица ошибок
# Сохраняем результаты
results[name] = {
"accuracy": accuracy,
"auc": auc_score,
"classification_report": classification_rep,
"confusion_matrix": conf_matrix,
}
# Вывод результатов
for name, metrics in results.items():
print(f"\nМодель: {name}")
print(f"Точность: {metrics['accuracy']:.4f}")
print(f"ROC AUC: {metrics['auc']:.4f}")
plot_confusion_matrix(metrics["confusion_matrix"], name)
print("Отчет по классификации:")
print(classification_report(y_test, models[name].predict(X_test)))
import seaborn as sns
Оценка моделей. Матрица ошибок и ROC
In [ ]:
from sklearn.metrics import (
accuracy_score,
precision_score,
recall_score,
f1_score,
roc_auc_score,
confusion_matrix,
ConfusionMatrixDisplay,
)
# Перебор всех моделей и вывод результатов
for name, model in models.items():
print(f"\nОценка модели: {name}")
# Обучаем модель
model.fit(X_train, y_train)
# Предсказания
y_pred = model.predict(X_test)
# Метрики
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
roc_auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1])
print(f"Точность (Accuracy): {accuracy:.4f}")
print(f"Точность (Precision): {precision:.4f}")
print(f"Полнота (Recall): {recall:.4f}")
print(f"F1-Score: {f1:.4f}")
print(f"AUC: {roc_auc:.4f}")
# Матрица ошибок
conf_matrix = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(
confusion_matrix=conf_matrix,
display_labels=["No Heart Disease", "Heart Disease"],
)
disp.plot(cmap="Blues")
plt.title(f"Матрица ошибок: {name}")
plt.show()
# ROC-кривая
fpr, tpr, thresholds = roc_curve(y_test, model.predict_proba(X_test)[:, 1])
plt.figure()
plt.plot(fpr, tpr, label=f"ROC curve (AUC = {roc_auc:.2f})")
plt.plot([0, 1], [0, 1], linestyle="--")
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title(f"ROC-кривая для {name}")
plt.legend(loc="lower right")
plt.show()
Настройки гипермараметров
In [15]:
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, roc_auc_score
# Параметры для настройки RandomForest
param_grid_rf = {
"n_estimators": [100, 200, 300, 500], # Увеличено количество деревьев
"max_depth": [10, 20, 30, 50, None], # Больше вариантов глубины
"min_samples_split": [2, 5, 10, 15], # Более широкий диапазон
"min_samples_leaf": [1, 2, 4, 6], # Увеличено минимальное число в листе
"max_features": ["sqrt", "log2", None], # Добавлена настройка признаков для деления
}
grid_search_rf = GridSearchCV(
estimator=RandomForestClassifier(random_state=42),
param_grid=param_grid_rf,
cv=5, # Кросс-валидация с 5 фолдами
scoring="roc_auc", # Оценка по метрике AUC
n_jobs=-1,
verbose=2, # Вывод прогресса
)
grid_search_rf.fit(X_train, y_train)
# Лучшие параметры и результаты
print("Лучшие параметры для RandomForest:", grid_search_rf.best_params_)
best_rf_model = grid_search_rf.best_estimator_
y_pred_rf = best_rf_model.predict(X_test)
accuracy_rf = accuracy_score(y_test, y_pred_rf)
roc_auc_rf = roc_auc_score(y_test, best_rf_model.predict_proba(X_test)[:, 1])
print(f"Точность RandomForest: {accuracy_rf:.4f}")
print(f"AUC RandomForest: {roc_auc_rf:.4f}")
Логическая регрессия
In [16]:
# Параметры для настройки LogisticRegression
param_grid_lr = {
"C": [
0.01,
0.1,
1,
5,
10,
], # Регуляризационный параметр, добавлено больше вариантов
"solver": ["liblinear", "saga"], # Алгоритм оптимизации
"max_iter": [100, 200, 300], # Максимальное количество итераций
"penalty": ["l2", "elasticnet"], # Добавлена настройка для типа регуляризации
}
# GridSearchCV для LogisticRegression
grid_search_lr = GridSearchCV(
estimator=LogisticRegression(random_state=42),
param_grid=param_grid_lr,
cv=5, # Увеличена кросс-валидация до 5 фолдов
scoring="roc_auc", # Используется AUC вместо accuracy для более точной оценки
n_jobs=-1,
verbose=2, # Вывод прогресса выполнения
)
grid_search_lr.fit(X_train, y_train)
# Лучшие параметры для LogisticRegression
print("Лучшие параметры для LogisticRegression:", grid_search_lr.best_params_)
# Обучение модели с лучшими параметрами
best_lr_model = grid_search_lr.best_estimator_
# Оценка лучшей модели
y_pred_lr = best_lr_model.predict(X_test)
accuracy_lr = accuracy_score(y_test, y_pred_lr)
roc_auc_lr = roc_auc_score(y_test, best_lr_model.predict_proba(X_test)[:, 1])
print(f"Точность LogisticRegression: {accuracy_lr:.4f}")
print(f"AUC LogisticRegression: {roc_auc_lr:.4f}")
In [17]:
# Параметры для настройки GradientBoosting
param_grid_gb = {
"n_estimators": [100, 200, 300], # Количество деревьев
"learning_rate": [0.01, 0.05, 0.1], # Скорость обучения
"max_depth": [3, 5, 7], # Глубина деревьев
"subsample": [0.8, 0.9, 1.0], # Доля выборки для обучения
"min_samples_split": [2, 5], # Минимальное количество образцов для разделения узла
}
# GridSearchCV для GradientBoosting
grid_search_gb = GridSearchCV(
estimator=GradientBoostingClassifier(random_state=42),
param_grid=param_grid_gb,
cv=5, # Увеличена кросс-валидация до 5 фолдов
scoring="roc_auc", # Используется AUC вместо accuracy для более точной оценки
n_jobs=-1,
verbose=2, # Вывод прогресса выполнения
)
grid_search_gb.fit(X_train, y_train)
# Лучшие параметры для GradientBoosting
print("Лучшие параметры для GradientBoosting:", grid_search_gb.best_params_)
# Обучение модели с лучшими параметрами
best_gb_model = grid_search_gb.best_estimator_
# Оценка лучшей модели
y_pred_gb = best_gb_model.predict(X_test)
accuracy_gb = accuracy_score(y_test, y_pred_gb)
roc_auc_gb = roc_auc_score(y_test, best_gb_model.predict_proba(X_test)[:, 1])
print(f"Точность GradientBoosting: {accuracy_gb:.4f}")
print(f"AUC GradientBoosting: {roc_auc_gb:.4f}")
In [24]:
import pandas as pd
feature_importances = pd.Series(
best_rf_model.feature_importances_, index=X_train.columns
)
feature_importances.sort_values(ascending=False).plot(kind="bar")
plt.title("Важность признаков (RandomForest)")
plt.show()
feature_importances = pd.Series(
best_gb_model.feature_importances_, index=X_train.columns
)
feature_importances.sort_values(ascending=False).plot(kind="bar")
plt.title("Важность признаков (Gradient Boosting)")
plt.show()
# Извлечение коэффициентов модели
coefficients = best_lr_model.coef_[0]
# Получение имен признаков
feature_names = X_train.columns # если X_train это DataFrame
# Сортировка признаков по важности (по абсолютным значениям коэффициентов)
importance = np.abs(coefficients)
sorted_idx = np.argsort(importance)[::-1] # Индексы сортировки по убыванию
# Построение графика
plt.figure(figsize=(10, 6))
plt.barh(range(len(importance)), importance[sorted_idx], align="center")
plt.yticks(range(len(importance)), np.array(feature_names)[sorted_idx])
plt.xlabel("Важность признака")
plt.title("Важность признаков для Logistic Regression")
plt.show()
In [26]:
from sklearn.model_selection import learning_curve
train_sizes, train_scores, test_scores = learning_curve(
best_rf_model, X_train, y_train, cv=3, scoring="accuracy", n_jobs=-1
)
train_scores_mean = train_scores.mean(axis=1)
test_scores_mean = test_scores.mean(axis=1)
plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_scores_mean, label="Точность на обучении", color="blue")
plt.plot(train_sizes, test_scores_mean, label="Точность на валидации", color="orange")
plt.xlabel("Размер обучающей выборки")
plt.ylabel("Точность")
plt.title("Кривая обучения (RandomForest)")
plt.legend()
plt.grid()
plt.show()
train_sizes, train_scores, test_scores = learning_curve(
best_gb_model, X_train, y_train, cv=3, scoring="accuracy", n_jobs=-1
)
train_scores_mean = train_scores.mean(axis=1)
test_scores_mean = test_scores.mean(axis=1)
plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_scores_mean, label="Точность на обучении", color="blue")
plt.plot(train_sizes, test_scores_mean, label="Точность на валидации", color="orange")
plt.xlabel("Размер обучающей выборки")
plt.ylabel("Точность")
plt.title("Кривая обучения (Gradient Boosting)")
plt.legend()
plt.grid()
plt.show()
train_sizes, train_scores, test_scores = learning_curve(
best_lr_model, X_train, y_train, cv=3, scoring="accuracy", n_jobs=-1
)
train_scores_mean = train_scores.mean(axis=1)
test_scores_mean = test_scores.mean(axis=1)
plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_scores_mean, label="Точность на обучении", color="blue")
plt.plot(train_sizes, test_scores_mean, label="Точность на валидации", color="orange")
plt.xlabel("Размер обучающей выборки")
plt.ylabel("Точность")
plt.title("Кривая обучения (Logistic Regression)")
plt.legend()
plt.grid()
plt.show()
In [22]:
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# Применяем PCA для снижения размерности до 2D
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_test) # Масштабируем данные
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
# Устанавливаем диапазон для сетки
x_min, x_max = X_pca[:, 0].min() - 1, X_pca[:, 0].max() + 1
y_min, y_max = X_pca[:, 1].min() - 1, X_pca[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1), np.arange(y_min, y_max, 0.1))
# Создаем новые данные на основе сетки для предсказаний
grid_points = pca.inverse_transform(
np.c_[xx.ravel(), yy.ravel()]
) # Возвращаем в исходное пространство
Z = best_rf_model.predict(grid_points)
Z = Z.reshape(xx.shape)
# Визуализация
plt.figure(figsize=(10, 6))
plt.contourf(xx, yy, Z, alpha=0.8, cmap=ListedColormap(("orange", "blue")))
plt.scatter(
X_pca[:, 0],
X_pca[:, 1],
c=y_test,
edgecolor="k",
cmap=ListedColormap(("red", "green")),
)
plt.title("Разделение классов (RandomForest, PCA)")
plt.xlabel("PCA Component 1")
plt.ylabel("PCA Component 2")
plt.show()