不均衡なクラス(5%1)の分類問題に取り組んでいます。確率ではなく、クラスを予測したい。
バイナリ分類問題で、scikitのclassifier.predict()
はデフォルトで_0.5
_を使用していますか?そうでない場合、デフォルトの方法は何ですか?その場合、どのように変更しますか?
Scikitでは、一部の分類子には_class_weight='auto'
_オプションがありますが、すべてではありません。 _class_weight='auto'
_を使用すると、.predict()
は実際の人口比率をしきい値として使用しますか?
_class_weight
_をサポートしないMultinomialNB
のような分類子でこれを行う方法は何でしょうか? predict_proba()
を使用してから、自分でクラスを計算する以外。
scikitの
classifier.predict()
はデフォルトで0.5を使用していますか?
確率的分類器では、はい。他の人が説明したように、それは数学的な観点からの唯一の賢明なしきい値です。
class_weight
をサポートしないMultinomialNBのような分類器でこれを行う方法は何でしょうか?
class_prior
を設定できます。これは、クラスごとの事前確率P(y)yです。これにより、決定境界が事実上シフトします。例えば。
# minimal dataset
>>> X = [[1, 0], [1, 0], [0, 1]]
>>> y = [0, 0, 1]
# use empirical prior, learned from y
>>> MultinomialNB().fit(X,y).predict([1,1])
array([0])
# use custom prior to make 1 more likely
>>> MultinomialNB(class_prior=[.1, .9]).fit(X,y).predict([1,1])
array([1])
Scikit学習のしきい値は、バイナリ分類の場合は0.5であり、マルチクラス分類の確率が最も高いクラスになります。多くの問題では、しきい値を調整することではるかに良い結果が得られる場合があります。ただし、これは、ホールドアウトテストデータではなく、トレーニングデータの相互検証によって慎重に行う必要があります。テストデータのしきい値を調整すると、テストデータが過剰に適合します。
しきい値を調整するほとんどの方法は、 受信者動作特性(ROC) および YoudenのJ統計 に基づいていますが、遺伝的検索などの他の方法でも実行できますアルゴリズム。
これは医学でこれを行うことを説明しているピアレビュージャーナルの記事です:
http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2515362/
私が知る限り、Pythonでそれを行うためのパッケージはありませんが、Pythonでブルートフォース検索を使用して見つけるのは比較的単純ですが(非効率的です)。
これはそれを行うRコードです。
## load data
DD73OP <- read.table("/my_probabilites.txt", header=T, quote="\"")
library("pROC")
# No smoothing
roc_OP <- roc(DD73OP$tc, DD73OP$prob)
auc_OP <- auc(roc_OP)
auc_OP
Area under the curve: 0.8909
plot(roc_OP)
# Best threshold
# Method: Youden
#Youden's J statistic (Youden, 1950) is employed. The optimal cut-off is the threshold that maximizes the distance to the identity (diagonal) line. Can be shortened to "y".
#The optimality criterion is:
#max(sensitivities + specificities)
coords(roc_OP, "best", ret=c("threshold", "specificity", "sensitivity"), best.method="youden")
#threshold specificity sensitivity
#0.7276835 0.9092466 0.7559022
clf.predict_proba()
を使用してしきい値を設定できます
例えば:
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(random_state = 2)
clf.fit(X_train,y_train)
# y_pred = clf.predict(X_test) # default threshold is 0.5
y_pred = (clf.predict_proba(X_test)[:,1] >= 0.3).astype(bool) # set threshold as 0.3
あなたはここで概念を混乱させているようです。しきい値は「一般的な分類子」の概念ではありません-最も基本的なアプローチは調整可能なしきい値に基づいていますが、既存の方法のほとんどは、しきい値設定とは見なせない(または少なくともすべきでない)分類の複雑なルールを作成します。
最初に-scikitの分類子のデフォルトのしきい値に関する質問には答えられません。そのようなものがないからです。
第二に、クラスの重み付けはしきい値ではなく、不均衡なクラスを処理する分類機能に関するものであり、特定の分類に依存するものです。たとえば、SVMの場合、最適化問題のスラック変数に重み付けする方法です。または、必要に応じて、特定のクラスに関連付けられたラグランジュ乗数の値の上限を指定します。これを「自動」に設定することは、デフォルトのヒューリスティックを使用することを意味しますが、もう一度-単にしきい値に変換することはできません。
一方、Naive Bayesdirectlyは、トレーニングセットからクラスの確率を推定します。これは「クラス優先」と呼ばれ、「class_prior」変数を使用してコンストラクターで設定できます。
ドキュメント から:
クラスの事前確率。指定した場合、事前分布はデータに従って調整されません。
0.5は、何らかの方法で人口の割合とは関係ありません。その確率出力。 「しきい値」はありません。1つのクラスの確率が0.51である場合、最も可能性の高いクラスであるように見えます。常に使用するもの*であり、異なる「しきい値」を使用するパッケージがない場合は0.5。確率スコアが*正確かつ真に代表*である場合、常に最も可能性の高いクラスを選択する必要があります。そうしないと、精度が低下するだけです。仮定を行うさまざまなアルゴリズムを使用しているため、確率が正しいことはわかりませんが、モデルによって行われた仮定に反することになります。
are class_weightが何をするか混乱しています。クラスの重みを変更すると、あまり表現されていないクラスのデータポイントの重みが増加し(/過剰に表現されたクラスでは減少)、各クラスの「重み」が等しくなります。これは、常に最も一般的なクラスに投票する分類子を避けるための一般的なトリックです。このように、両方のクラスは学習アルゴリズムの観点から等しく共通です。
誰かがこのスレッドにアクセスして、すぐに使用できる機能を期待している場合(python 2.7)。この例では、カットオフは元のデータセットのイベントと非イベントの比率を反映するように設計されていますdf、whiley_prob.predict_probaメソッドの結果である可能性があります(階層化されたトレイン/テストの分割を想定)。
def predict_with_cutoff(colname, y_prob, df):
n_events = df[colname].values
event_rate = sum(n_events) / float(df.shape[0]) * 100
threshold = np.percentile(y_prob[:, 1], 100 - event_rate)
print "Cutoff/threshold at: " + str(threshold)
y_pred = [1 if x >= threshold else 0 for x in y_prob[:, 1]]
return y_pred
気軽に批判/修正してください。クラスバランシングが問題外であり、データセット自体のバランスが非常に悪いときに、まれに役立つことを願っています。