Поиск по сетке Sklearn с предопределенным разделением не соответствует отдельному классификатору

#python #validation #scikit-learn #grid-search #scoring

#python #проверка #scikit-learn #поиск по сетке #оценка

Вопрос:

Я использую sklearn GridSearch для поиска наилучших параметров для классификации случайного леса с использованием предопределенного набора проверки. Оценки от наилучшего оценщика, возвращаемые GridSearch, не соответствуют оценкам, полученным при обучении отдельного классификатора с теми же параметрами.

Определение разделения данных

 X = pd.concat([X_train, X_devel])
y = pd.concat([y_train, y_devel])
test_fold = -X.index.str.contains('train').astype(int)
ps = PredefinedSplit(test_fold)
  

Определение GridSearch

 n_estimators = [10]
max_depth = [4]
grid = {'n_estimators': n_estimators, 'max_depth': max_depth}

rf = RandomForestClassifier(random_state=0)
rf_grid = GridSearchCV(estimator = rf, param_grid = grid, cv = ps, scoring='recall_macro')
rf_grid.fit(X, y)
  

Определение классификатора

 clf = RandomForestClassifier(n_estimators=10, max_depth=4, random_state=0)
clf.fit(X_train, y_train)
  

Отзыв был вычислен явно с использованием sklearn.metrics.recall_score

 y_pred_train = clf.predict(X_train)
y_pred_devel = clf.predict(X_devel)

uar_train = recall_score(y_train, y_pred_train, average='macro')
uar_devel = recall_score(y_devel, y_pred_devel, average='macro')
  

Поиск по сетке

 uar train:  0.32189884516029466
uar devel:  0.3328299259976279
  

Случайный лес:

 uar train:  0.483040291148839
uar devel:  0.40706644557392435
  

В чем причина такого несоответствия?

Ответ №1:

Здесь есть несколько проблем:

  1. Ваши входные аргументы для recall_score изменены на противоположные. Фактический правильный порядок:

     recall_score(y_true, y_test)
      

    Но вы делаете:

     recall_score(y_pred_train, y_train, average='macro')
      

    Исправьте это на:

     recall_score(y_train, y_pred_train, average='macro')
      
  2. Вы делаете это rf_grid.fit(X, y) для поиска по сетке. Это означает, что после нахождения наилучших комбинаций параметров GridSearchCV будет соответствовать всем данным (целому X, игнорируя PredefinedSplit , потому что это используется только во время перекрестной проверки в поисках наилучших параметров). Таким образом, по сути, оценщик из GridSearchCV увидит все данные, поэтому оценки будут отличаться от того, что вы получаете при выполнении clf.fit(X_train, y_train)

Комментарии:

1. Спасибо за информацию. Что-то все еще неясное после изменения порядка аргументов ожидается, что отзыв после переподготовки для всего набора данных улучшится (поскольку классификатор теперь просматривает все данные), однако он остается более низким как для подмножеств train, так и для devel. Есть какие-либо подсказки, почему это так?

2. @OxanaVerkholyak Извините, я не могу больше ничего сказать, не видя образцов данных. Может быть много вещей: 1) Сбалансировано ли разделение вашего обучающего теста? 2) Ваши данные несбалансированы? 3) Сколько существует классов?. «recall_macro» не учитывает дисбаланс меток. Возможно, это может быть причиной. Как насчет других показателей, точности, матрицы путаницы и т.д. Пожалуйста, опубликуйте полный код вместе с некоторыми примерами данных, которые могут привести к такому результату.

Ответ №2:

Это потому, что в вашем GridSearchCV вы используете функцию подсчета очков as, recall-macro которая в основном возвращает усредненное значение, recall score которое macro является усредненным. Смотрите эту ссылку.

Однако, когда вы возвращаете оценку по умолчанию из своего, RandomForestClassifier она возвращает mean accuracy . Итак, вот почему оценки разные. Смотрите Эту ссылку для получения информации о том же. (Поскольку одно из них — это отзыв, а другое — точность).