GridSearchCV вернул отрицательную MAE: как не выбрать худшую модель

В таблице экспериментов стоят -5 и -12. Аналитик выбирает -12, потому что «ошибку нужно минимизировать». Но scikit-learn уже поменял знак, чтобы все scorer можно было максимизировать. Выбрана худшая модель.

Метрика и scorer имеют разное соглашение

mean_absolute_error возвращает неотрицательную ошибку: меньше лучше. Строка scoring="neg_mean_absolute_error" задаёт scorer с обратным знаком: больше лучше. GridSearchCV выбирает максимум scorer, поэтому -5 предпочтительнее -12.

Чтобы показать обычную MAE в отчёте, знак возвращают один раз после выбора. Нельзя брать модуль всех score без понимания: другие scorer, например R², допускают настоящий отрицательный результат, который не является отрицательной потерей.

Проверить соглашение на понятном baseline

Используем DummyRegressor, предсказывающий константу. Цели всех обучающих и проверочных строк равны 5. Константа 5 даёт нулевую MAE, константа 20 — ошибку 15. Поиск обязан выбрать первый вариант.

Задача специально проста для проверки направления оптимизации. Мы проверяем подключение scorer к реальному GridSearchCV, а не оцениваем способность модели учиться на этом наборе.

import numpy as np
from sklearn.dummy import DummyRegressor
from sklearn.model_selection import GridSearchCV, KFold
X = np.arange(12).reshape(-1, 1)
y = np.full(12, 5.0)
search = GridSearchCV(DummyRegressor(strategy="constant"),
    {"constant": [5.0, 20.0]}, scoring="neg_mean_absolute_error", cv=KFold(3))
search.fit(X, y)
losses = -search.cv_results_["mean_test_score"]
print({"MAE": losses.tolist(), "best_constant": search.best_params_["constant"]})
assert np.allclose(losses, [0, 15])
assert search.best_params_["constant"] == 5
assert -search.best_score_ == 0

Поиск выбрал константу 5 и вернул best_score_=0. Другой вариант имеет scorer -15 и обычную MAE 15. Направление выбора теперь проверено на ожидаемом результате.

Сохранить понятный отчёт эксперимента

Назовите колонки явно: cv_neg_mae для внутреннего scorer и cv_mae для положительной ошибки. Храните имя scoring рядом с числами. Колонка score без определения легко переживает несколько переименований и теряет смысл.

При нескольких метриках refit задаёт, по какой из них выбрать и переобучить модель. Убедитесь, что направление каждого пользовательского scorer соответствует договору. Для функции потерь make_scorer использует greater_is_better=False, чтобы инвертировать знак. Повторное ручное отрицание внутри функции создаст обратный эффект.

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

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

Закрепить на практике

В бесплатном уроке ошибок регрессии вы посчитаете MAE, MSE и RMSE в единицах цели. После этой основы проверьте, как та же ошибка передаётся в процедуру выбора модели через scoring. Откройте бесплатный урок и задачи. Полная последовательность тем — в бесплатном курсе.

Продолжить на практике