6

Я строю классификатор, который проходит через данные о кредитном клубе и выбирает лучшие кредиты X. Я обучил случайный лес и создал обычные кривые ROC, матрицы замешательства и т. Д.Scikit - изменение порога для создания нескольких матриц путаницы

Матрица замешательства принимает в качестве аргумента предсказания классификатора (большинство прогнозов деревьев в лесу). Тем не менее, я хочу напечатать несколько confusion matrices с разными порогами, чтобы узнать, что произойдет, если я выберу 10% лучших кредитов, 20% лучших кредитов и т. Д.

Я знаю, читая другие вопросы, что changing the threshold is often a bad idea, но есть ли какие-либо другой способ увидеть матрицы замешательства для этих ситуаций? (вопрос А)

Если я продолжу менять порог, я должен предположить, что это лучший способ сделать это до predict proba, а затем порог его вручную, передавая его в матрицу замешательства? (вопрос B)

+0

Да, я думаю, что единственный способ сделать это используя optim_proba и изменяя порог вручную (или записывая функцию, чтобы выбрать лучший порог в соответствии с некоторой метрикой). Это может быть плохой идеей в других случаях, но определенно имеет смысл в этом случае. – amanbirs

ответ

0

A. В вашем случае изменение порога допустимо и возможно даже необходимо. Порог по умолчанию составляет 50%, но с деловой точки зрения даже 15% вероятности невыплаты может быть достаточно для отклонения такого приложения.

Фактически, при кредитном скоринге обычно устанавливают разные отсечки для разных условий продукта или сегментов клиентов, после прогнозирования вероятности дефолта с общей моделью (см., Например, главу 9 «Оценочных показателей кредитного риска» от Naeem Siddiqi).

B. Есть два удобных способа порогу в произвольной alpha вместо 50%:

  1. Действительно, predict_proba и порог его к alpha вручную, или с помощью класса-оболочки (см код ниже). Используйте это, если вы хотите попробовать несколько пороговых значений без установки модели.
  2. Сменить class_weights на (alpha, 1-alpha) перед установкой модели.

А теперь пример кода для оболочки:

import numpy as np 
from sklearn.datasets import make_classification 
from sklearn.ensemble import RandomForestClassifier 
from sklearn.pipeline import make_pipeline 
from sklearn.model_selection import train_test_split 
from sklearn.metrics import confusion_matrix 
from sklearn.base import BaseEstimator, ClassifierMixin 
X, y = make_classification(random_state=1) 
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1) 

class CustomThreshold(BaseEstimator, ClassifierMixin): 
    """ Custom threshold wrapper for binary classification""" 
    def __init__(self, base, threshold=0.5): 
     self.base = base 
     self.threshold = threshold 
    def fit(self, *args, **kwargs): 
     self.base.fit(*args, **kwargs) 
     return self 
    def predict(self, X): 
     return (self.base.predict_proba(X)[:, 1] > self.threshold).astype(int) 

rf = RandomForestClassifier(random_state=1).fit(X_train, y_train) 
clf = [CustomThreshold(rf, threshold) for threshold in [0.3, 0.5, 0.7]] 

for model in clf: 
    print(confusion_matrix(y_test, model.predict(X_test))) 

assert((clf[1].predict(X_test) == clf[1].base.predict(X_test)).all()) 
assert(sum(clf[0].predict(X_test)) > sum(clf[0].base.predict(X_test))) 
assert(sum(clf[2].predict(X_test)) < sum(clf[2].base.predict(X_test))) 

Это выход 3 спутанность матрицы для различных порогов:

[[13 1] 
[ 2 9]] 
[[14 0] 
[ 3 8]] 
[[14 0] 
[ 4 7]]