Scikit - изменение порога для создания нескольких матриц путаницы

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

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

Из прочтения других вопросов я знаю, что изменение порога часто является плохой идеей, но есть ли другой способ увидеть матрицы путаницы для этих ситуаций? (вопрос А)

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


person sapo_cosmico    schedule 17.09.2015    source источник
comment
Да, я думаю, что единственный способ сделать это - использовать pred_proba и изменить порог вручную (или написать функцию для выбора лучшего порога в соответствии с какой-либо метрикой). В других случаях это может быть плохой идеей, но в данном случае определенно имеет смысл.   -  person amanbirs    schedule 21.11.2017


Ответы (1)


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

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

Б. Есть два удобных способа установить порог на произвольном 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]]
person David Dale    schedule 24.11.2017