【问题标题】:Scikit - changing the threshold to create multiple confusion matrixesScikit - 更改阈值以创建多个混淆矩阵
【发布时间】:2015-12-14 04:20:30
【问题描述】:

我正在构建一个分类器,该分类器会遍历贷款俱乐部数据,并选择最好的 X 笔贷款。我已经训练了一个随机森林,并创建了通常的 ROC 曲线、混淆矩阵等。

混淆矩阵将分类器的预测(森林中树木的多数预测)作为参数。但是,我希望以不同的阈值打印多个confusion matrices,以了解如果我选择 10% 最佳贷款、20% 最佳贷款等会发生什么。

我从阅读changing the threshold is often a bad idea 的其他问题中知道,但是有没有其他方法可以查看这些情况的混淆矩阵? (问题A)

如果我继续更改阈值,我是否应该假设最好的方法是将其设置为predict proba,然后手动设置阈值并将其传递给混淆矩阵? (问题 B)

【问题讨论】:

  • 是的,我认为唯一的方法是使用 predict_proba 并手动更改阈值(或编写一个函数以根据某些指标选择最佳阈值)。在其他情况下这可能是个坏主意,但在这种情况下绝对有意义。

标签: scikit-learn classification random-forest threshold confusion-matrix


【解决方案1】:

A. 在您的情况下,更改阈值是可以接受的,甚至可能是必要的。默认阈值为 50%,但从业务角度来看,即使 15% 的不还款概率也可能足以拒绝此类申请。

事实上,在信用评分中,在使用通用模型预测违约概率后,通常会为不同的产品条款或客户群设置不同的临界值(参见例如 Naeem Siddiqi 的“信用风险记分卡”第 9 章) .

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]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-16
    • 2016-05-12
    • 2020-02-04
    • 2013-08-25
    • 2021-03-02
    • 2017-10-28
    • 2020-09-17
    • 2021-09-29
    相关资源
    最近更新 更多