377 KiB
Подключили датафрейм и выгрузили данные
import pandas as pd
from sklearn import set_config
set_config(transform_output="pandas")
random_state = 42
df = pd.read_csv("data/diabetes.csv")
print(df.columns)
df
Бизнес-цели¶
- Предсказание риска развития диабета. Будем классифицировать пациентов на основе медданных для того, чтобы определить у кого есть риск развития диабета(будем использовать целевой признак "Outcome"). Актуальность для раннего выявления диабета.
- Анализ ключевых факторов, влияющих на диабет. Предсказание вероятности развития диабета на основе медданных. Актуальность для планирвоания лечения.
Определение достижимого уровня качества модели для первой задачи¶
Разделение данных на обучающую и тестовые выборки 80/20 для задачи классификации
from typing import Tuple
import pandas as pd
from pandas import DataFrame
from sklearn.model_selection import train_test_split
random_state = 42
def split_stratified_into_train_val_test(
df_input,
stratify_colname="y",
frac_train=0.6,
frac_val=0.15,
frac_test=0.25,
random_state=None,
) -> Tuple[DataFrame, DataFrame, DataFrame, DataFrame, DataFrame, DataFrame]:
if frac_train + frac_val + frac_test != 1.0:
raise ValueError(
"fractions %f, %f, %f do not add up to 1.0"
% (frac_train, frac_val, frac_test)
)
if stratify_colname not in df_input.columns:
raise ValueError("%s is not a column in the dataframe" % (stratify_colname))
X = df_input
y = df_input[
[stratify_colname]
]
df_train, df_temp, y_train, y_temp = train_test_split(
X, y, stratify=y, test_size=(1.0 - frac_train), random_state=random_state
)
if frac_val <= 0:
assert len(df_input) == len(df_train) + len(df_temp)
return df_train, pd.DataFrame(), df_temp, y_train, pd.DataFrame(), y_temp
relative_frac_test = frac_test / (frac_val + frac_test)
df_val, df_test, y_val, y_test = train_test_split(
df_temp,
y_temp,
stratify=y_temp,
test_size=relative_frac_test,
random_state=random_state,
)
assert len(df_input) == len(df_train) + len(df_val) + len(df_test)
return df_train, df_val, df_test, y_train, y_val, y_test
X_train, X_val, X_test, y_train, y_val, y_test = split_stratified_into_train_val_test(
df, stratify_colname="Outcome", frac_train=0.80, frac_val=0, frac_test=0.20, random_state=random_state
)
display("X_train", X_train)
display("y_train", y_train)
display("X_test", X_test)
display("y_test", y_test)
Формирование конвейера для классификации данных¶
preprocessing_num -- конвейер для обработки числовых данных: заполнение пропущенных значений и стандартизация
preprocessing_cat -- конвейер для обработки категориальных данных: заполнение пропущенных данных и унитарное кодирование
features_preprocessing -- трансформер для предобработки признаков
features_engineering -- трансформер для конструирования признаков
drop_columns -- трансформер для удаления колонок
features_postprocessing -- трансформер для унитарного кодирования новых признаков
pipeline_end -- основной конвейер предобработки данных и конструирования признаков
Конвейер выполняется последовательно.
Трансформер выполняет параллельно для указанного набора колонок.
import numpy as np
import pandas as pd
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
# Построение конвейеров предобработки
class DiabetesFeatures(BaseEstimator, TransformerMixin):
def __init__(self):
pass
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
# Добавим признак отношения индекса массы тела и возраста.
X = X.copy()
X["Glucose_Insulin"] = X["Glucose"] / X["Insulin"]
return X
def get_feature_names_out(self, features_in):
new_features = ["Glucose_Insulin"]
return np.append(features_in, new_features, axis=0)
# Обработка числовых данных. Числовой конвейр: заполнение пропущенных значений медианой и стандартизация
preprocessing_num_class = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
preprocessing_cat_class = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore', sparse_output=False, drop='first'))
])
columns_to_drop = []
numeric_columns = ["Pregnancies", "Glucose", "BloodPressure", "SkinThickness", "Insulin",
"BMI", "DiabetesPedigreeFunction", "Age"]
cat_columns = ["Outcome"]
features_preprocessing = ColumnTransformer(
verbose_feature_names_out=False,
transformers=[
("preprocessing_num", preprocessing_num_class, numeric_columns),
("preprocessing_cat", preprocessing_cat_class, cat_columns),
],
remainder="passthrough"
)
drop_columns = ColumnTransformer(
verbose_feature_names_out=False,
transformers=[
("drop_columns", "drop", columns_to_drop),
],
remainder="passthrough",
)
features_postprocessing = ColumnTransformer(
verbose_feature_names_out=False,
transformers=[
('preprocessing_cat', preprocessing_cat_class, ["Outcome"]),
],
remainder="passthrough",
)
pipeline_end = Pipeline(
[
("features_preprocessing", features_preprocessing),
("custom_features", DiabetesFeatures()),
("drop_columns", drop_columns),
]
)
Работа конвейера:
preprocessing_result = pipeline_end.fit_transform(X_train)
preprocessed_df = pd.DataFrame(
preprocessing_result,
columns=pipeline_end.get_feature_names_out(),
)
preprocessed_df
Формирование набора моделей для классификации¶
logistic -- логистическая регрессия
ridge -- гребневая регрессия
decision_tree -- дерево решений
knn -- k-ближайших соседей
naive_bayes -- наивный Байесовский классификатор
gradient_boosting -- метод градиентного бустинга (набор деревьев решений)
random_forest -- метод случайного леса (набор деревьев решений)
mlp -- многослойный персептрон (нейронная сеть)
from sklearn import ensemble, linear_model, naive_bayes, neighbors, neural_network, tree
random_state = 42
class_models = {
"logistic": {"model": linear_model.LogisticRegression(random_state=random_state)},
"ridge": {"model": linear_model.LogisticRegression(penalty="l2", class_weight="balanced", random_state=random_state)},
"decision_tree": {
"model": tree.DecisionTreeClassifier(max_depth=7, random_state=random_state)
},
"knn": {"model": neighbors.KNeighborsClassifier(n_neighbors=7)},
"naive_bayes": {"model": naive_bayes.GaussianNB()},
"gradient_boosting": {
"model": ensemble.GradientBoostingClassifier(n_estimators=210, random_state=random_state)
},
"random_forest": {
"model": ensemble.RandomForestClassifier(
max_depth=11, class_weight="balanced", random_state=random_state
)
},
"mlp": {
"model": neural_network.MLPClassifier(
hidden_layer_sizes=(7,),
max_iter=500,
early_stopping=True,
random_state=random_state,
)
},
}
Обучение моделей на обучающем наборе данных и оценка на тестовом
import numpy as np
from sklearn import metrics
for model_name in class_models.keys():
print(f"Model: {model_name}")
model = class_models[model_name]["model"]
model_pipeline = Pipeline([("pipeline", pipeline_end), ("model", model)])
model_pipeline = model_pipeline.fit(X_train, y_train.values.ravel())
y_train_predict = model_pipeline.predict(X_train)
y_test_probs = model_pipeline.predict_proba(X_test)[:, 1]
y_test_predict = np.where(y_test_probs > 0.5, 1, 0)
class_models[model_name]["pipeline"] = model_pipeline
class_models[model_name]["probs"] = y_test_probs
class_models[model_name]["preds"] = y_test_predict
class_models[model_name]["Precision_train"] = metrics.precision_score(
y_train, y_train_predict
)
class_models[model_name]["Precision_test"] = metrics.precision_score(
y_test, y_test_predict
)
class_models[model_name]["Recall_train"] = metrics.recall_score(
y_train, y_train_predict
)
class_models[model_name]["Recall_test"] = metrics.recall_score(
y_test, y_test_predict
)
class_models[model_name]["Accuracy_train"] = metrics.accuracy_score(
y_train, y_train_predict
)
class_models[model_name]["Accuracy_test"] = metrics.accuracy_score(
y_test, y_test_predict
)
class_models[model_name]["ROC_AUC_test"] = metrics.roc_auc_score(
y_test, y_test_probs
)
class_models[model_name]["F1_train"] = metrics.f1_score(y_train, y_train_predict)
class_models[model_name]["F1_test"] = metrics.f1_score(y_test, y_test_predict)
class_models[model_name]["MCC_test"] = metrics.matthews_corrcoef(
y_test, y_test_predict
)
class_models[model_name]["Cohen_kappa_test"] = metrics.cohen_kappa_score(
y_test, y_test_predict
)
class_models[model_name]["Confusion_matrix"] = metrics.confusion_matrix(
y_test, y_test_predict
)
Сводная таблица оценок качества для использованных моделей классификации
from sklearn.metrics import ConfusionMatrixDisplay
import matplotlib.pyplot as plt
n_rows = int(len(class_models) / 2)
n_cols = 2
fig, ax = plt.subplots(n_rows, n_cols, figsize=(12, 10), sharex=False, sharey=False)
for index, key in enumerate(class_models.keys()):
c_matrix = class_models[key]["Confusion_matrix"]
disp = ConfusionMatrixDisplay(
confusion_matrix=c_matrix, display_labels=["No Diabetes", "Diabetes"]
).plot(ax=ax.flat[index])
disp.ax_.set_title(key)
plt.subplots_adjust(top=1, bottom=0, hspace=0.4, wspace=0.1)
plt.show()
Значение 100 - это количество вернных диагнозов (True Positives), там модель верно определила людей у которых нет диабета "No Diabetes".
Значение 54 у некоторых моделей - это количество неверных диагнозов (False Negatives), там модель неверно определила людей с диабетом, те, у кого нет диабета "No Diabetes" были отнесены к классу "Diabetes".
Исходя из истинных и ложных значений (True Positives и False Negatives), можно сделать вывод, что модель имеет высокую точность при предсказании людей без диабета "No Diabetes". Уровень ложных результатов в некотоорых моделях со значением 54 говорит о том, что есть такие данные, которые модель пропускает.
Точность, полнота, верность (аккуратность), F-мера
class_metrics = pd.DataFrame.from_dict(class_models, "index")[
[
"Precision_train",
"Precision_test",
"Recall_train",
"Recall_test",
"Accuracy_train",
"Accuracy_test",
"F1_train",
"F1_test",
]
]
class_metrics.sort_values(
by="Accuracy_test", ascending=False
).style.background_gradient(
cmap="plasma",
low=0.3,
high=1,
subset=["Accuracy_train", "Accuracy_test", "F1_train", "F1_test"],
).background_gradient(
cmap="viridis",
low=1,
high=0.3,
subset=[
"Precision_train",
"Precision_test",
"Recall_train",
"Recall_test",
],
)
Почти все модели в данной выборке, а именно логистическая регрессия, ридж-регрессия, дерево решений, наивный байесовский классификатор, случайный лес, градиентный бустинг, KNN демонстрируют неплохие значения по всем метрикам на обучающих и тестовых наборах данных. Модель MLP не так эффективна по сравнению с другими, но в некоторых метриках показывает неплохие результаты.
class_metrics = pd.DataFrame.from_dict(class_models, "index")[
[
"Accuracy_test",
"F1_test",
"ROC_AUC_test",
"Cohen_kappa_test",
"MCC_test",
]
]
class_metrics.sort_values(by="ROC_AUC_test", ascending=False).style.background_gradient(
cmap="plasma",
low=0.3,
high=1,
subset=[
"ROC_AUC_test",
"MCC_test",
"Cohen_kappa_test",
],
).background_gradient(
cmap="viridis",
low=1,
high=0.3,
subset=[
"Accuracy_test",
"F1_test",
],
)
Такой же вывод можно сделать и для следующих метрик: Accuracy, F1, ROC AUC, Cohen's Kappa и MCC. Все модели, кроме KNN и MLP, указывают на хорошо-развитую способность к выделению классов
best_model = str(class_metrics.sort_values(by="MCC_test", ascending=False).iloc[0].name)
display(best_model)
Вывод данных с ошибкой предсказания для оценки
preprocessing_result = pipeline_end.transform(X_test)
preprocessed_df = pd.DataFrame(
preprocessing_result,
columns=pipeline_end.get_feature_names_out(),
)
y_pred = class_models[best_model]["preds"]
error_index = y_test[y_test["Outcome"] != y_pred].index.tolist()
display(f"Error items count: {len(error_index)}")
error_predicted = pd.Series(y_pred, index=y_test.index).loc[error_index]
error_df = X_test.loc[error_index].copy()
error_df.insert(loc=1, column="Predicted", value=error_predicted)
error_df.sort_index()
Пример использования обученной модели (конвейера) для предсказания
model = class_models[best_model]["pipeline"]
example_id = 190
test = pd.DataFrame(X_test.loc[example_id, :]).T
test_preprocessed = pd.DataFrame(preprocessed_df.loc[example_id, :]).T
display(test)
display(test_preprocessed)
result_proba = model.predict_proba(test)[0]
result = model.predict(test)[0]
real = int(y_test.loc[example_id].values[0])
display(f"predicted: {result} (proba: {result_proba})")
display(f"real: {real}")
Подбор гиперпараметров методом поиска по сетке
from sklearn.model_selection import GridSearchCV
optimized_model_type = "random_forest"
random_forest_model = class_models[optimized_model_type]["pipeline"]
param_grid = {
"model__n_estimators": [10, 50, 100],
"model__max_features": ["sqrt", "log2"],
"model__max_depth": [5, 7, 10],
"model__criterion": ["gini", "entropy"],
}
gs_optomizer = GridSearchCV(
estimator=random_forest_model, param_grid=param_grid, n_jobs=-1
)
gs_optomizer.fit(X_train, y_train.values.ravel())
gs_optomizer.best_params_
Обучение модели с новыми гиперпараметрами
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestClassifier
import numpy as np
from sklearn import metrics
import pandas as pd
numeric_features = X_train.select_dtypes(include=['float64', 'int64']).columns.tolist()
random_state = 42
# Определение трансформера
pipeline_end = ColumnTransformer([
('numeric', StandardScaler(), numeric_features),
])
optimized_model = RandomForestClassifier(
random_state=random_state,
criterion="gini",
max_depth=5,
max_features="sqrt",
n_estimators=50,
)
result = {}
# Обучение модели
result["pipeline"] = Pipeline([
("pipeline", pipeline_end),
("model", optimized_model)
]).fit(X_train, y_train.values.ravel())
# Прогнозирование и расчет метрик
result["train_preds"] = result["pipeline"].predict(X_train)
result["probs"] = result["pipeline"].predict_proba(X_test)[:, 1]
result["preds"] = np.where(result["probs"] > 0.5, 1, 0)
# Метрики для оценки модели
result["Precision_train"] = metrics.precision_score(y_train, result["train_preds"])
result["Precision_test"] = metrics.precision_score(y_test, result["preds"])
result["Recall_train"] = metrics.recall_score(y_train, result["train_preds"])
result["Recall_test"] = metrics.recall_score(y_test, result["preds"])
result["Accuracy_train"] = metrics.accuracy_score(y_train, result["train_preds"])
result["Accuracy_test"] = metrics.accuracy_score(y_test, result["preds"])
result["ROC_AUC_test"] = metrics.roc_auc_score(y_test, result["probs"])
result["F1_train"] = metrics.f1_score(y_train, result["train_preds"])
result["F1_test"] = metrics.f1_score(y_test, result["preds"])
result["MCC_test"] = metrics.matthews_corrcoef(y_test, result["preds"])
result["Cohen_kappa_test"] = metrics.cohen_kappa_score(y_test, result["preds"])
result["Confusion_matrix"] = metrics.confusion_matrix(y_test, result["preds"])
Формирование данных для оценки старой и новой версии модели
optimized_metrics = pd.DataFrame(columns=list(result.keys()))
optimized_metrics.loc[len(optimized_metrics)] = pd.Series(
data=class_models[optimized_model_type]
)
optimized_metrics.loc[len(optimized_metrics)] = pd.Series(
data=result
)
optimized_metrics.insert(loc=0, column="Name", value=["Old", "New"])
optimized_metrics = optimized_metrics.set_index("Name")
Оценка параметров старой и новой модели
optimized_metrics[
[
"Precision_train",
"Precision_test",
"Recall_train",
"Recall_test",
"Accuracy_train",
"Accuracy_test",
"F1_train",
"F1_test",
]
].style.background_gradient(
cmap="plasma",
low=0.3,
high=1,
subset=["Accuracy_train", "Accuracy_test", "F1_train", "F1_test"],
).background_gradient(
cmap="viridis",
low=1,
high=0.3,
subset=[
"Precision_train",
"Precision_test",
"Recall_train",
"Recall_test",
],
)
optimized_metrics[
[
"Accuracy_test",
"F1_test",
"ROC_AUC_test",
"Cohen_kappa_test",
"MCC_test",
]
].style.background_gradient(
cmap="plasma",
low=0.3,
high=1,
subset=[
"ROC_AUC_test",
"MCC_test",
"Cohen_kappa_test",
],
).background_gradient(
cmap="viridis",
low=1,
high=0.3,
subset=[
"Accuracy_test",
"F1_test",
],
)
_, ax = plt.subplots(1, 2, figsize=(10, 4), sharex=False, sharey=False
)
for index in range(0, len(optimized_metrics)):
c_matrix = optimized_metrics.iloc[index]["Confusion_matrix"]
disp = ConfusionMatrixDisplay(
confusion_matrix=c_matrix, display_labels=["No Diabetes", "Diabetes"]
).plot(ax=ax.flat[index])
plt.subplots_adjust(top=1, bottom=0, hspace=0.4, wspace=0.3)
plt.show()
Значение 100 означает количество верно классифицированных объектов, которые относятся к классу "No Diabetes". Можно сделать вывод, что модель отлично идентифицирует объекты этого класса.
Значения 0 означают количество верно классифицированных объектов, которые относятся к классу "Diabetes". Можно сделать вывод, что это не высокая точность модели в определении объектов данного класса
Определение достижимого уровня качества модели для второй задачи (задача регрессии)¶
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn import set_config
random_state = 42
set_config(transform_output="pandas")
df = pd.read_csv("data/diabetes.csv")
df = df.drop(columns=["Outcome"])
df = df.sample(n=700, random_state=random_state).reset_index(drop=True)
print(df.shape)
display(df)
import pandas as pd
df = pd.read_csv("data/diabetes.csv")
required_columns = ["Pregnancies", "Glucose", "BloodPressure", "SkinThickness", "Insulin", "BMI", "DiabetesPedigreeFunction", "Age"]
missing_columns = [col for col in required_columns if col not in df.columns]
if missing_columns:
raise ValueError(f"Отсутствуют столбцы: {missing_columns}")
df["diabetes_risk_index"] = (
df["Glucose"] * 0.3
+ df["BMI"] * 0.3
+ df["Age"] * 0.2
+ df["BloodPressure"] * 0.1
+ df["Insulin"] * 0.1
)
print(df[["Pregnancies", "Glucose", "BloodPressure", "SkinThickness", "Insulin", "BMI", "DiabetesPedigreeFunction", "Age", "diabetes_risk_index"]].head())
Разделение набора данных на обучающую и тестовые выборки (80/20) для задачи регрессии
from typing import Tuple
import pandas as pd
from pandas import DataFrame
from sklearn.model_selection import train_test_split
def split_into_train_test(
df_input: DataFrame,
target_colname: str = "diabetes_risk_index",
frac_train: float = 0.8,
random_state: int = None,
) -> Tuple[DataFrame, DataFrame, DataFrame, DataFrame]:
if not (0 < frac_train < 1):
raise ValueError("Fraction must be between 0 and 1.")
if target_colname not in df_input.columns:
raise ValueError(f"{target_colname} is not a column in the DataFrame.")
X = df_input.drop(columns=[target_colname])
y = df_input[[target_colname]]
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=(1.0 - frac_train),
random_state=random_state
)
return X_train, X_test, y_train, y_test
X_train, X_test, y_train, y_test = split_into_train_test(
df,
target_colname="diabetes_risk_index",
frac_train=0.8,
random_state=42
)
display("X_train", X_train.head())
display("y_train", y_train.head())
display("X_test", X_test.head())
display("y_test", y_test.head())
Определение перечня алгоритмов решения задачи аппроксимации (регрессии)
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn import linear_model, tree, neighbors, ensemble, neural_network
random_state = 42
models = {
# Линейная регрессия
"linear": {
"model": linear_model.LinearRegression(n_jobs=-1)
},
# Полиномиальная регрессия степени 2
"linear_poly": {
"model": make_pipeline(
PolynomialFeatures(degree=2),
StandardScaler(),
linear_model.LinearRegression(fit_intercept=False, n_jobs=-1),
)
},
# Полиномиальная регрессия с взаимодействиями
"linear_interact": {
"model": make_pipeline(
PolynomialFeatures(interaction_only=True),
StandardScaler(),
linear_model.LinearRegression(fit_intercept=False, n_jobs=-1),
)
},
# Ridge-регрессия
"ridge": {
"model": make_pipeline(
StandardScaler(),
linear_model.RidgeCV()
)
},
# Регрессия на основе дерева решений
"decision_tree": {
"model": tree.DecisionTreeRegressor(max_depth=7, random_state=random_state)
},
# Метод ближайших соседей (kNN)
"knn": {
"model": make_pipeline(
StandardScaler(),
neighbors.KNeighborsRegressor(n_neighbors=7, n_jobs=-1)
)
},
# Случайный лес (Random Forest)
"random_forest": {
"model": ensemble.RandomForestRegressor(
max_depth=7, random_state=random_state, n_jobs=-1
)
},
# Нейронная сеть (MLPRegressor)
"mlp": {
"model": make_pipeline(
StandardScaler(),
neural_network.MLPRegressor(
activation="tanh",
hidden_layer_sizes=(3,),
max_iter=500,
early_stopping=True,
random_state=random_state,
)
)
},
}
Обучение и оценка моделей с помощью различных алгоритмов
import math
from pandas import DataFrame
from sklearn import metrics
for model_name in models.keys():
print(f"Model: {model_name}")
fitted_model = models[model_name]["model"].fit(
X_train.values, y_train.values.ravel()
)
y_train_pred = fitted_model.predict(X_train.values)
y_test_pred = fitted_model.predict(X_test.values)
models[model_name]["fitted"] = fitted_model
models[model_name]["train_preds"] = y_train_pred
models[model_name]["preds"] = y_test_pred
models[model_name]["RMSE_train"] = math.sqrt(
metrics.mean_squared_error(y_train, y_train_pred)
)
models[model_name]["RMSE_test"] = math.sqrt(
metrics.mean_squared_error(y_test, y_test_pred)
)
models[model_name]["RMAE_test"] = math.sqrt(
metrics.mean_absolute_error(y_test, y_test_pred)
)
models[model_name]["R2_test"] = metrics.r2_score(y_test, y_test_pred)
Вывод результатов оценки
reg_metrics = pd.DataFrame.from_dict(models, "index")[
["RMSE_train", "RMSE_test", "RMAE_test", "R2_test"]
]
reg_metrics.sort_values(by="RMSE_test").style.background_gradient(
cmap="viridis", low=1, high=0.3, subset=["RMSE_train", "RMSE_test"]
).background_gradient(cmap="plasma", low=0.3, high=1, subset=["RMAE_test", "R2_test"])
Вывод реального и "спрогнозированного" результата для обучающей и тестовой выборок
Получение лучшей модели
best_model = str(reg_metrics.sort_values(by="RMSE_test").iloc[0].name)
display(best_model)
Подбор гиперпараметров методом поиска по сетке
import pandas as pd
import numpy as np
from sklearn import metrics
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import StandardScaler
# Удаление пропущенных значений (если есть)
df.dropna(inplace=True)
X = df[["Pregnancies", "Glucose", "BloodPressure", "SkinThickness", "Insulin",
"BMI", "DiabetesPedigreeFunction", "Age"]]
y = df["diabetes_risk_index"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
model = RandomForestRegressor(random_state=42)
param_grid = {
'n_estimators': [50, 100, 150],
'max_depth': [10, 20, 30],
'min_samples_split': [5, 10, 15]
}
grid_search = GridSearchCV(
estimator=model,
param_grid=param_grid,
scoring='neg_mean_squared_error',
cv=3,
n_jobs=-1,
verbose=2
)
grid_search.fit(X_train, y_train)
print("Лучшие параметры:", grid_search.best_params_)
print("Лучший результат (MSE):", -grid_search.best_score_)
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
mse = metrics.mean_squared_error(y_test, y_pred)
r2 = metrics.r2_score(y_test, y_pred)
print(f"Ошибка на тестовой выборке (MSE): {mse:.4f}")
print(f"Коэффициент детерминации (R²): {r2:.4f}")
Обучение модели с новыми гиперпараметрами и сравнение новых и старых данных
import pandas as pd
import numpy as np
from sklearn import metrics
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split, GridSearchCV
import matplotlib.pyplot as plt
old_param_grid = {
'n_estimators': [50, 100],
'max_depth': [ 10, 20],
'min_samples_split': [5, 10]
}
old_grid_search = GridSearchCV(estimator=RandomForestRegressor(),
param_grid=old_param_grid,
scoring='neg_mean_squared_error', cv=3, n_jobs=-1, verbose=2)
old_grid_search.fit(X_train, y_train)
old_best_params = old_grid_search.best_params_
old_best_mse = -old_grid_search.best_score_
new_param_grid = {
'n_estimators': [100],
'max_depth': [20],
'min_samples_split': [10]
}
new_grid_search = GridSearchCV(estimator=RandomForestRegressor(),
param_grid=new_param_grid,
scoring='neg_mean_squared_error', cv=2)
new_grid_search.fit(X_train, y_train)
new_best_params = new_grid_search.best_params_
new_best_mse = -new_grid_search.best_score_
model_best = RandomForestRegressor(**new_best_params)
model_best.fit(X_train, y_train)
model_oldbest = RandomForestRegressor(**old_best_params)
model_oldbest.fit(X_train, y_train)
y_pred = model_best.predict(X_test)
y_oldpred = model_oldbest.predict(X_test)
mse = metrics.mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
print("Старые параметры:", old_best_params)
print("Лучший результат (MSE) на старых параметрах:", old_best_mse)
print("\n")
print("Новые параметры:", new_best_params)
print("Лучший результат (MSE) на новых параметрах:", new_best_mse)
print("Среднеквадратическая ошибка (MSE) на тестовых данных:", mse)
print("Корень среднеквадратичной ошибки (RMSE) на тестовых данных:", rmse)
plt.figure(figsize=(10, 5))
plt.scatter(range(len(y_test)), y_test, label="Актуальные значения", color="green", alpha=0.5)
plt.scatter(range(len(y_test)), y_pred, label="Новые параметры", color="blue", alpha=0.5)
plt.scatter(range(len(y_test)), y_oldpred, label="Старые параметры", color="red", alpha=0.5)
plt.xlabel("Выборка")
plt.ylabel("Значения")
plt.legend()
plt.title("Новые и старые параметры")
plt.show()