SklearnパッケージのLogisticRegressionを使用していますが、分類について簡単な質問があります。分類器のROC曲線を作成しましたが、トレーニングデータの最適なしきい値は約0.25であることがわかりました。予測を作成するときのデフォルトのしきい値は0.5であると想定しています。このデフォルト設定を変更して、10分割の相互検証を行うときにモデルの精度を確認するにはどうすればよいですか?基本的に、モデルでは、0.5ではなく0.25を超えるすべてのユーザーに対して「1」を予測する必要があります。すべてのドキュメントを調べてきましたが、どこにも行けないようです。
よろしくお願いします。
これは組み込みの機能ではありません。 LogisticRegressionクラスを独自のクラスでラップし、カスタムpredict()
メソッド内で使用するthreshold
属性を追加することで、これを「追加」できます。
ただし、いくつかの注意点があります。
LogisticRegression.decision_function()
は、選択された分離超平面までの符号付き距離を返します。 predict_proba()
を表示している場合は、しきい値0.5の超平面距離のlogit()
を表示しています。しかし、それは計算するのにより高価です。class_weight
の使用を検討してください。これにより、分類器は、重要なクラスからさらに離れた超平面を選択する必要があります。実用的な答えを出したいと思います
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, recall_score, roc_auc_score, precision_score
X, y = make_classification(
n_classes=2, class_sep=1.5, weights=[0.9, 0.1],
n_features=20, n_samples=1000, random_state=10
)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
clf = LogisticRegression(class_weight="balanced")
clf.fit(X_train, y_train)
THRESHOLD = 0.25
preds = np.where(clf.predict_proba(X_test)[:,1] > THRESHOLD, 1, 0)
pd.DataFrame(data=[accuracy_score(y_test, preds), recall_score(y_test, preds),
precision_score(y_test, preds), roc_auc_score(y_test, preds)],
index=["accuracy", "recall", "precision", "roc_auc_score"])
THRESHOLD
を0.25
に変更すると、recall
とprecision
のスコアが減少していることがわかります。ただし、class_weight
引数を削除すると、accuracy
は増加しますが、recall
スコアは低下します。 @accepted回答を参照してください
def find_best_threshold(threshould, fpr, tpr):
t = threshould[np.argmax(tpr*(1-fpr))]
# (tpr*(1-fpr)) will be maximum if your fpr is very low and tpr is very high
print("the maximum value of tpr*(1-fpr)", max(tpr*(1-fpr)), "for threshold", np.round(t,3))
return t
この関数は、最高の真陽性率と長所率を見つけたい場合に使用できます
特殊なケース:1次元ロジスティック回帰
サンプルX
が1
とラベル付けされている領域と0
がラベル付けされている領域を区切る値は、次の式を使用して計算されます。
from scipy.special import logit
thresh = 0.1
val = (logit(thresh)-clf.intercept_)/clf.coef_[0]
したがって、予測はより直接的に計算できます
preds = np.where(X>val, 1, 0)
完全を期すために、scikitの確率計算に基づいて予測をエレガントに生成する別の方法を紹介します binarizeを使用 :
import numpy as np
from sklearn.preprocessing import binarize
THRESHOLD = 0.25
# This probabilities would come from logistic_regression.predict_proba()
y_logistic_prob = np.random.uniform(size=10)
predictions = binarize(y_logistic_prob.reshape(-1, 1), THRESHOLD).ravel()
さらに、私は アンドレウスが行う考慮事項 、特に2と3に同意します。それらに注意してください。