1. Рассчитаем количество комбинаций и обучений.

from sklearn.datasets import make_regression

from sklearn.model_selection import (

    train_test_split,

    GridSearchCV

)

from sklearn.ensemble import GradientBoostingRegressor

 

max_depth = [2, 3, 4, 5]

learning_rate = [0.01, 0.05, 0.1]

cv_folds = 5

 

combinations = len(max_depth) * len(learning_rate)

fits = combinations * cv_folds

 

print("Комбинаций:", combinations)

print("Обучений в CV:", fits)

 

X, y = make_regression(

    n_samples=300,

    n_features=5,

    noise=15,

    random_state=42

)

 

X_train, X_test, y_train, y_test = train_test_split(

    X, y,

    test_size=0.2,

    random_state=42

)

 

search = GridSearchCV(

    GradientBoostingRegressor(

        n_estimators=50,

        random_state=42

    ),

    param_grid={

        "max_depth": max_depth,

        "learning_rate": learning_rate

    },

    cv=cv_folds,

    scoring="neg_mean_squared_error"

)

 

search.fit(X_train, y_train)

 

print("Лучшие параметры:", search.best_params_)

print("Тестовый R²:", round(search.score(X_test, y_test), 3))

Результат расчёта:

Кроме 60 обучений для перекрёстной проверки, GridSearchCV по умолчанию выполняет дополнительное обучение лучшей конфигурации на всей обучающей выборке.

Тестовые данные не используются при подборе гиперпараметров, поскольку должны обеспечивать независимую итоговую оценку.

2. Сравним полный и случайный поиск.

from sklearn.datasets import make_classification

from sklearn.model_selection import (

    train_test_split,

    GridSearchCV,

    RandomizedSearchCV

)

from sklearn.tree import DecisionTreeClassifier

from sklearn.metrics import accuracy_score

 

X, y = make_classification(

    n_samples=300,

    n_features=6,

    n_informative=4,

    n_redundant=0,

    random_state=42

)

 

X_train, X_test, y_train, y_test = train_test_split(

    X, y,

    test_size=0.2,

    stratify=y,

    random_state=42

)

 

params = {

    "max_depth": [2, 3, 4, 5, 6],

    "min_samples_leaf": [1, 2, 3, 4]

}

 

grid = GridSearchCV(

    DecisionTreeClassifier(random_state=42),

    param_grid=params,

    cv=5

)

 

random_search = RandomizedSearchCV(

    DecisionTreeClassifier(random_state=42),

    param_distributions=params,

    n_iter=8,

    cv=5,

    random_state=42

)

 

for name, search in [

    ("Grid Search", grid),

    ("Random Search", random_search)

]:

    search.fit(X_train, y_train)

 

    predictions = search.predict(X_test)

 

    print(name)

    print("Конфигураций:", len(search.cv_results_["params"]))

    print("Лучшие параметры:", search.best_params_)

    print(

        "Тестовая точность:",

        round(accuracy_score(y_test, predictions), 3)

    )

Grid Search проверяет все 20 комбинаций гиперпараметров, что соответствует 100 обучениям при cv=5.

Random Search проверяет 8 комбинаций, что соответствует 40 обучениям при cv=5.

Оба метода дополнительно обучают лучшую модель на всей обучающей выборке.

Grid Search обеспечивает полный перебор заданной сетки. Random Search позволяет ограничить число проверяемых конфигураций.

3. Исследуем важность признаков и чувствительность модели к шуму.

import numpy as np

from sklearn.datasets import make_classification

from sklearn.model_selection import train_test_split

from sklearn.ensemble import RandomForestClassifier

from sklearn.inspection import permutation_importance

from sklearn.metrics import accuracy_score

 

X, y = make_classification(

    n_samples=400,

    n_features=5,

    n_informative=3,

    n_redundant=0,

    random_state=42

)

 

X_train, X_test, y_train, y_test = train_test_split(

    X, y,

    test_size=0.2,

    stratify=y,

    random_state=42

)

 

model = RandomForestClassifier(

    n_estimators=100,

    random_state=42

)

 

model.fit(X_train, y_train)

 

original_accuracy = accuracy_score(

    y_test,

    model.predict(X_test)

)

 

importance = permutation_importance(

    model,

    X_test,

    y_test,

    n_repeats=10,

    random_state=42

)

 

rng = np.random.default_rng(42)

 

X_test_noisy = X_test + rng.normal(

    loc=0,

    scale=0.1,

    size=X_test.shape

)

 

noisy_accuracy = accuracy_score(

    y_test,

    model.predict(X_test_noisy)

)

 

print("Исходная точность:", round(original_accuracy, 3))

print("Точность с шумом:", round(noisy_accuracy, 3))

 

for i, value in enumerate(importance.importances_mean):

    print(f"Признак {i}:", round(value, 4))

Permutation Importance показывает, насколько меняется качество модели при перемешивании отдельного признака.

Сравнение точности на исходных и зашумлённых данных позволяет исследовать чувствительность модели к небольшим изменениям входных значений.

Однако один эксперимент с шумом не является полной проверкой устойчивости модели.

Важность признаков и методы интерпретации, включая SHAP, объясняют поведение модели, но не доказывают причинно-следственные связи.

При оценке надёжности также необходимо учитывать возможный сдвиг распределения данных, шум измерений и требования к справедливости решений.