A. В вашем случае изменение порога допустимо и возможно даже необходимо. Порог по умолчанию составляет 50%, но с деловой точки зрения даже 15% вероятности невыплаты может быть достаточно для отклонения такого приложения.
Фактически, при кредитном скоринге обычно устанавливают разные отсечки для разных условий продукта или сегментов клиентов, после прогнозирования вероятности дефолта с общей моделью (см., Например, главу 9 «Оценочных показателей кредитного риска» от Naeem Siddiqi).
B. Есть два удобных способа порогу в произвольной alpha
вместо 50%:
- Действительно,
predict_proba
и порог его к alpha
вручную, или с помощью класса-оболочки (см код ниже). Используйте это, если вы хотите попробовать несколько пороговых значений без установки модели.
- Сменить
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]]
Да, я думаю, что единственный способ сделать это используя optim_proba и изменяя порог вручную (или записывая функцию, чтобы выбрать лучший порог в соответствии с некоторой метрикой). Это может быть плохой идеей в других случаях, но определенно имеет смысл в этом случае. – amanbirs