Как передать параметры подгонки XGBoost при использовании OneVsRestClassifier?

Я хочу передать параметры подгонки xgboost через OneVsRestClassifierпригодный метод.

clf = OneVsRestClassifier( XGBClassifier(objective='binary:logistic', seed=0))
# Want to pass `eval_set` and 'eval_metric' to xgboost model.
clf.fit(X_train, y_train, estimator__eval_metric='aucpr', estimator__eval_set= eval_set_xgboost)

Ошибка: fit() получил неожиданный аргумент ключевого слова 'estimator__eval_metric'

Можете ли вы помочь мне, как я могу передать XGBoost подгонять параметры используя OneVsRestClassifier подходящий метод?

1 ответ

Решение

XGBoost по умолчанию обрабатывает мультиклассовую классификацию. Обратитесь к этому примеру для получения дополнительных объяснений.

С текущей структурой, вы не можете пройти fit_params за OneVsRestClassifier, Обратитесь к этой проблеме для более подробной информации.

Может быть, если вы можете поделиться своим намерением для упаковки с OneVsRestClassifierМы можем направить вас соответствующим образом.

Обновить:

Я не думаю, что упаковка с одним Vs классификатором отдыха уменьшит переоснащение.

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

Другие лучшие варианты снижения переоснащения описаны здесь

Ответ Чендлера Секаи полезен. Однако необходимо изменить одну строку:

weight_array = y * weight + 1
(иначе вы дадите 0 вес отрицательному классу...)

Недавно я столкнулся с этой проблемой, чтобы динамически передать pos_scale_weight, и ниже я обхожу решение. В настоящее время для класса XGBClassifier недоступен автоматический pos_scale_weight. И мы действительно хотим использовать sklearn OneVsRestClassifier с xgboost для задач классификации с несколькими метками или несколькими классами.

Типичный способ использования OneVsRestClassifier:

clf = OneVsRestClassifier(XGBClassifier(booster='gbtree', objective='binary:logistic'))
clf.fit(X=X_train, y = y_train)

OneVsRestClassifier делает следующее: когда вы вызываете clf.fit, он фактически вызывает метод fit из XGBClassifier для соответствия X_train и каждую цель из y_train для соответствия обучающим данным. В приведенном ниже примере метод clf.fit будет: XGBClassifier.fit(X_train, target1) -> XGBClassifier.fit(X_train, target2) -> XGBClassifier.fit(X_train, target3) -> объединить все три модели. Если вы установите для pos_scale_weight определенное число, тогда для каждой подгонки будет использоваться один и тот же масштаб. Если положительное соотношение по всем трем целям сильно различается. Он не соответствует цели, положительная скорость которой намного ниже, чем у других.

y_train.head()
| target1| target2 |target3|
|--------|---------|-------|
| 0      | 1       | 0     |
| 1      | 1       | 0     |

В моей задаче каждая метка, которую я прогнозирую, имеет совершенно разное соотношение положительных и отрицательных результатов (от 0,1% до 10%). Ниже приведен созданный мной метод. Предположим, у нас есть X_train в качестве обучающих функций, y_train - это матрица двоичных меток для каждого класса. Мы можем обойтись и создать новый класс, унаследовавший функцию подгонки, и передать weight_array для каждого массива y_train. OneVsRestClassifier будет передавать каждый y из y_train один за другим, поэтому weight_array будет рассчитываться отдельно. Это решение предназначено только для двоичной классификации ([0,1]) для нескольких меток. Мы хотим убедиться, что вес класса neg равен 1, вес класса pos должен быть (num of neg)/(num of pos).

class XGBClassifierNew(XGBClassifier):
      """
      the inherited class with same method name will override.
      if you start an XGBClassifierNew instance the fit method you called by default will be XGBClassifierNew.fit(). Check the link below for reference.
      https://stackru.com/questions/12764995/python-overriding-an-inherited-class-method
      """  
      def fit(self, X, y, **kwargs):
          pos_ratio = y.sum()/len(y)
          weight = len(y)/y.sum() - 1
          weight_array = y * (weight-1) + 1
          return super().fit(X=X, y=y, sample_weight = weight_array, **kwargs)

clf = OneVsRestClassifier(XGBClassifierNew())
clf.fit(X=X_train, y=y_train)

И причина, по которой weight_array является массивом, заключается в том, что sample_weight принимает вес для каждого экземпляра, а не для всего класса, например pos_scale_weight.

И этот метод одинаково обрабатывает вес всего класса (внутри каждой метки).

Другие вопросы по тегам