我正在构建一个分类器,它遍历借贷俱乐部数据,并选择最佳的X笔贷款。我已经训练了一个随机森林,并创建了通常的ROC曲线,混淆矩阵等。
混淆矩阵以分类器的预测作为参数(森林中大多数树的预测)。但是,我希望在不同阈值处打印多个混淆矩阵,以了解如果我选择10%最佳贷款,20%最佳贷款等会发生什么。
我从阅读其他问题中知道,改变阈值通常是一个坏主意,但是有没有其他方法可以看到这些情况下的混淆矩阵?(问题)
如果我继续改变阈值,我是否应该假设这样做的最佳方法是预测概率,然后手动设置阈值,将其传递给混淆矩阵?(问题2)
在您的情况下,更改阈值是可以接受的,甚至可能是必要的。默认阈值为50%,但从业务角度来看,即使15%的不还款概率也足以拒绝这样的申请。
事实上,在信用评分中,在使用通用模型预测违约概率之后,通常会为不同的产品条款或客户细分设置不同的截止值(例如,参见Naeem Siddiqi的"信用风险记分卡"第9章)。
有两种方便的方法可以将阈值设置为任意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]]