Scikit - 更改阈值以创建多个混淆矩阵
Scikit - changing the threshold to create multiple confusion matrixes
我正在构建一个分类器,它通过贷款俱乐部数据,并选择最好的 X 贷款。我训练了随机森林,并创建了常用的 ROC 曲线、混淆矩阵等
混淆矩阵将分类器的预测(森林中树木的多数预测)作为参数。但是,我希望在不同的阈值下打印多个 confusion matrices,以了解如果我选择 10% 的最佳贷款、20% 的最佳贷款等会发生什么
我通过阅读其他问题了解到 changing the threshold is often a bad idea,但是对于这些情况,是否还有其他方法可以查看混淆矩阵? (问题 A)
如果我继续更改阈值,我是否应该假设最好的方法是 predict proba 然后手动设置阈值,将其传递给混淆矩阵? (问题 B)
A. 在您的情况下,更改阈值是可以接受的,甚至可能是必要的。默认阈值为 50%,但从商业角度来看,即使 15% 的不还款概率也足以拒绝此类申请。
事实上,在信用评分中,在使用通用模型预测违约概率后,通常会为不同的产品条款或客户群设置不同的截止点(例如,参见 Naeem "Credit Risk Scorecards" 的第 9 章西迪奇).
B。有两种方便的方法可以将阈值设置为任意 alpha
而不是 50%:
- 确实,
predict_proba
并将其阈值手动设置为 alpha
,或使用包装器 class(参见下面的代码)。如果您想在不重新拟合模型的情况下尝试多个阈值,请使用此选项。
- 在拟合模型之前将
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]]
我正在构建一个分类器,它通过贷款俱乐部数据,并选择最好的 X 贷款。我训练了随机森林,并创建了常用的 ROC 曲线、混淆矩阵等
混淆矩阵将分类器的预测(森林中树木的多数预测)作为参数。但是,我希望在不同的阈值下打印多个 confusion matrices,以了解如果我选择 10% 的最佳贷款、20% 的最佳贷款等会发生什么
我通过阅读其他问题了解到 changing the threshold is often a bad idea,但是对于这些情况,是否还有其他方法可以查看混淆矩阵? (问题 A)
如果我继续更改阈值,我是否应该假设最好的方法是 predict proba 然后手动设置阈值,将其传递给混淆矩阵? (问题 B)
A. 在您的情况下,更改阈值是可以接受的,甚至可能是必要的。默认阈值为 50%,但从商业角度来看,即使 15% 的不还款概率也足以拒绝此类申请。
事实上,在信用评分中,在使用通用模型预测违约概率后,通常会为不同的产品条款或客户群设置不同的截止点(例如,参见 Naeem "Credit Risk Scorecards" 的第 9 章西迪奇).
B。有两种方便的方法可以将阈值设置为任意 alpha
而不是 50%:
- 确实,
predict_proba
并将其阈值手动设置为alpha
,或使用包装器 class(参见下面的代码)。如果您想在不重新拟合模型的情况下尝试多个阈值,请使用此选项。 - 在拟合模型之前将
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]]