バイナリ分類のためのXGBoost:適切なしきい値の選択


8

私は非常に不均衡なバイナリラベル付きデータセットに取り組んでいます。この場合真のラベルの数はデータセット全体の7%にすぎません。ただし、機能の組み合わせによっては、サブセット内の機能の数が平均よりも多くなる場合があります。

たとえば、単一の特徴(色)を持つ次のデータセットがあるとします。

180個の赤いサンプル— 0

20個の赤いサンプル— 1個

緑のサンプル300個— 0

緑のサンプル100個— 1

簡単な決定木を作ることができます:

                      (color)

                red /       \ green

 P(1 | red) = 0.1              P(1 | green) = 0.25

データセット全体のP(1)= 0.2

このデータセットでXGBoostを実行すると、0.25以下の確率を予測できます。つまり、しきい値を0.5に決定した場合、

  • 0-P <0.5
  • 1-P> = 0.5

次に、常にゼロとしてラベル付けされたすべてのサンプルを取得します。私が問題を明確に説明したことを願っています。

ここで、初期データセットで次のプロットを取得しています(x軸のしきい値)。

ここに画像の説明を入力してください

しきい値= 0.1で最大のf1_scoreを持つ。今私は2つの質問があります:

  • そのような構造のデータセットにf1_scoreを使用する必要がありますか?
  • バイナリ分類にXGBoostを使用する場合、確率をラベルにマッピングするために0.5しきい値を使用することは常に合理的ですか?

更新。私はその話題が興味を引くと思います。以下は、XGBoostを使用して赤/緑の実験を再現するPythonコードです。それは実際に期待される確率を出力します:

from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
import numpy as np

X0_0 = np.zeros(180) # red - 0
Y0_0 = np.zeros(180)

X0_1 = np.zeros(20) # red - 1
Y0_1 = np.ones(20)

X1_0 = np.ones(300) # green - 0
Y1_0 = np.zeros(300)

X1_1 = np.ones(100) # green  - 1
Y1_1 = np.ones(100)

X = np.concatenate((X0_0, X0_1, X1_0, Y1_1))
Y = np.concatenate((Y0_0, Y0_1, Y1_0, Y1_1))

# reshaping into 2-dim array
X = X.reshape(-1, 1)

import xgboost as xgb

xgb_dmat = xgb.DMatrix(X_train, label=y_train)

param = {'max_depth': 1,
         'eta': 0.01,
         'objective': 'binary:logistic',
         'eval_metric': 'error',
         'nthread': 4}

model = xgb.train(param, xg_mat, 400)

X0_sample = np.array([[0]])
X1_sample = np.array([[1]])

print('P(1 | red), predicted: ' + str(model.predict(xgb.DMatrix(X0_sample))))
print('P(1 | green), predicted: ' + str(model.predict(xgb.DMatrix(X1_sample))))

出力:

P(1 | red), predicted: [ 0.1073855]
P(1 | green), predicted: [ 0.24398108]

回答:


5

最大化するものを決定する必要があります。

精度を最大化したい場合は、確率を0.5と比較して分類するのが適切です。f1メトリックを最大化する場合は適切ではありません。

精度を最大にしたい場合は、常にゼロを予測すること最適な分類子です。

pp

f1メトリックを最大化する場合、1つのアプローチは、分類子をトレーニングして確率を予測し、f1スコアを最大化するしきい値を選択することです。しきい値はおそらく0.5にはなりません。

別のオプションは、タイプIエラーとタイプIIエラーのコストを理解し、それに応じてクラスの重みを割り当てることです。


1
さらに2つのことを述べておきます。(a)F1スコアの代わりに、OPは加重精度を使用することもできます。または、AUC ROCなどのランキングメトリックを最大化することもできます(b)xgboostクラスの重みをサポートします。彼が最大化したい指標に満足していません。
Ricardo Cruz

@RicardoCruz、ありがとう-良い提案!(クラスの重みについては簡単に触れましたが、回答の最後の段落ですが、強調表示してよかったです。)
DW

ところで、よく使われるclass_weightsは逆周波数です:n_samples / (n_classes * np.bincount(y))。これにより、分類器がより人口の多いクラスにより大きな重みを与えるのを回避できます。
Ricardo Cruz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.