随机森林 - “完美”的混淆矩阵

Posted

技术标签:

【中文标题】随机森林 - “完美”的混淆矩阵【英文标题】:random forest - "perfect" confusion matrix 【发布时间】:2020-06-01 16:14:36 【问题描述】:

我有一个分类问题,我想确定不应该被邀请参加银行会议的潜在借款人。 在数据中,约。不应邀请 25% 的借款人。 我有大约 4500 个观察值和 86 个特征(很多假人)。

清理数据后,我这样做:

# Separate X_train and Y_train

X = ratings_prepared[:, :-1]
y= ratings_prepared[:,-1]

##################################################################################

# Separate test and train (stratified, 20% test)

import numpy as np
from sklearn.model_selection import StratifiedKFold

from sklearn.base import clone

skfolds = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

for train_index, test_index in skfolds.split(X,y):
    X_train = X[train_index]
    y_train = y[train_index]
    X_test = X[test_index]
    y_test = y[test_index]

然后,我继续训练模型。 SGD 分类器不能很好地工作:

def plot_roc_curve(fpr, tpr, label=None):
    plt.plot(fpr, tpr, linewidth=2, label =label)
    plt.plot([0,1], [0,1],'k--')
    plt.axis([0,1,0,1])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')

def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
    plt.plot(thresholds, precisions[:-1],"b--", label="Precision")
    plt.plot(thresholds, recalls[:-1], "g-", label="Recall")
    plt.xlabel("Threashold")
    plt.legend(loc="center left")
    plt.ylim([0,1])

############################# Train Models #############################

from sklearn.linear_model import SGDClassifier

sgd_clf =SGDClassifier(random_state=42)
sgd_clf.fit(X_train,y_train)
y_pred = sgd_clf.predict(X_train)

# f1 score

f1_score(y_train, y_pred)

# confusion matrix

tn, fp, fn, tp = confusion_matrix(y_train, y_pred).ravel()
(tn, fp, fn, tp)
from sklearn.metrics import plot_confusion_matrix
import matplotlib.pyplot as plt

disp = plot_confusion_matrix(sgd_clf, X_train, y_train,
                                 cmap=plt.cm.Blues,
                                 normalize='true')

# recall and precision

from sklearn.metrics import precision_score, recall_score
precision_score(y_train, y_pred)

# Precision Recall

from sklearn.metrics import precision_recall_curve

plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
plt.show()

# Plot ROC curve
y_scores = cross_val_predict(sgd_clf, X_train, y_train, cv=3, method="decision_function")
fpr, tpr, thresholds = roc_curve(y_train, y_scores)

plot_roc_curve(fpr, tpr)
plt.show()

# recall and precision

from sklearn.metrics import precision_score, recall_score
precision_score(y_train, y_pred)
### Precision score: 0.5084427767354597

然后我继续使用随机森林分类器,它应该会改进 SGD

from sklearn.ensemble import RandomForestClassifier

forest_clf = RandomForestClassifier(random_state=42)
y_probas_forest = cross_val_predict(forest_clf, X_train, y_train, cv=3, method='predict_proba')
y_scores_forest = y_probas_forest[:,1]
fpr_forest, tpr_forest, threshold_forest = roc_curve(y_train,y_scores_forest)

plt.plot(fpr, tpr, "b:", label="SGD")
plot_roc_curve(fpr_forest, tpr_forest, "Random Forest")
plt.legend(loc="lower right")
plt.show()

确实 ROC 曲线看起来更好:

但是混淆矩阵和精确度得分非常奇怪:

from sklearn.ensemble import RandomForestClassifier

forest_clf = RandomForestClassifier(random_state=42)
y_probas_forest = cross_val_predict(forest_clf, X_train, y_train, cv=3, method='predict_proba')
y_scores_forest = y_probas_forest[:,1]
fpr_forest, tpr_forest, threshold_forest = roc_curve(y_train,y_scores_forest)

forest_clf.fit(X_train,y_train)
y_pred = forest_clf.predict(X_train)


# f1 score

f1_score(y_train, y_pred)

# confusion matrix

from sklearn.metrics import plot_confusion_matrix
import matplotlib.pyplot as plt

disp = plot_confusion_matrix(forest_clf, X_train, y_train,
                                 cmap=plt.cm.Blues,
                                 normalize='true')

F 分数也是 1。我不明白这是怎么回事。我怀疑我犯了一个错误,但 SGD 分类器似乎工作正常的事实让我认为这与数据清理无关。

知道可能出了什么问题吗?

#

更新:

1) 绝对值的混淆矩阵:

2) 降低门槛:

【问题讨论】:

能否提供一些关于用于分类的特征的信息? 混淆矩阵的阈值是多少?是否有可能,您有某种自动阈值选择,它选择极低的 TPR 或极高的 FPR?很难读懂第二个 ROC,但 ROC 是否真的可以完美地拥抱那些极端点附近的墙?你能用绝对值而不是比率来显示混淆矩阵吗? 嗨 - 你可能是对的!这是一个自动阈值选择并使用极高的阈值:0.99。精度分数为 1,召回分数基本为零。如果我将阈值降低到 0.98,我会得到更平衡的结果。我不确定这在 TPR/FPR 方面意味着什么(我会说我几乎没有 FP)。我在上面添加了具有绝对值的混淆矩阵。 嗯...我预计预测的真假之间会有更大的差异。并不是说它一定是错的。我刚刚注意到您的模型中存在更大的问题。我没有看到任何测试数据!除非我忽略它,否则你完全有可能像疯了一样过度拟合。这就是为什么你看起来有一个完美的混淆矩阵。 【参考方案1】:

你有满分的原因是你没有根据测试数据做你的指标。

在第一段中,您正在对训练数据和测试数据进行 80/20 拆分,但随后所有指标 ROC、混淆矩阵等都是在原始训练数据而不是测试数据上完成的。

通过这样的设置,您的报告会显示您疯狂地过度拟合。

您应该做的是将经过训练的模型应用于您的测试数据并查看该模型的效果。

【讨论】:

谢谢!我理解我的错误以及为什么一切都很奇怪。我还是不太明白为什么 SGD 分类器没有同样的问题——仅仅是因为它是一个糟糕的预测器吗?

以上是关于随机森林 - “完美”的混淆矩阵的主要内容,如果未能解决你的问题,请参考以下文章

随机森林中的 class_weight 超参数改变了混淆矩阵中的样本数量

R语言使用party包中的cforest函数基于条件推理决策树(Conditional inference trees)构建随机森林使用varimp函数查看特征重要度使用table函数计算混淆矩阵

R语言使用randomForest包构建随机森林模型(Random forests)使用importance函数查看特征重要度使用table函数计算混淆矩阵评估分类模型性能包外错误估计OOB

R语言编写自定义函数计算分类模型评估指标:准确度特异度敏感度PPVNPV数据数据为模型预测后的混淆矩阵比较多个分类模型分类性能(逻辑回归决策树随机森林支持向量机)

H2O 上的混淆矩阵

10个交叉折叠的混淆矩阵 - 如何做到pandas dataframe df