交叉表和混淆矩阵在 Python 中导致不一致

Posted

技术标签:

【中文标题】交叉表和混淆矩阵在 Python 中导致不一致【英文标题】:Crosstab and confusion_matrix results disagreement in Python 【发布时间】:2020-03-30 05:20:07 【问题描述】:

我需要使用 Python 中的交叉表函数生成混淆矩阵(作为练习)。我一直在使用各种数据集进行此操作,效果很好,但这次我遇到了一个奇怪的问题。

数据集分为训练集和测试集(X_train, y_train, X_test, y_test)。测试集是构成响应变量的一系列 0 和 1。我对训练集进行了逻辑回归,并预测了测试集的值:

logit1 = sm.Logit(y_train, X_train).fit()
pred = logit1.predict(X_test)

然后,我使用 0.5 的截止值对响应的值进行分类,结果我有一系列与 y_test (2500) 长度相同的 0 和 1。这个系列叫做 res,现在我想用交叉表创建混淆表:

cross_table = pd.crosstab(y_test, res, rownames=['Actual'], colnames=['Predicted'], margins=True)

但这给了我下表,加起来不等于 2500:

Predicted  0.0  1.0  All
Actual                  
0.0        413   52  465
1.0        140   20  160
All        553   72  625

当我使用 sklearn 中的confusion_matrix 函数时,我得到了正确的总数 2500:

confusion_matrix(y_test, res)

array([[1817,  110],
       [ 369,  205]])

我的交叉表有什么问题???

包:

from pandas import Series, DataFrame
import pandas as pd
import statsmodels.api as sm
from sklearn.metrics import confusion_matrix

完整代码:

# indexes of train and test were provided in external files:
train = pd.read_csv('/Users//train.csv')
test = pd.read_csv('/Users//test.csv')

X_train = X.iloc[train.values[:,0],:]
X_test = X.iloc[test.values[:,0],:]

y_train = y[train.values[:,0]]
y_test = y[test.values[:,0]]

logit1 = sm.Logit(y_train, X_train).fit()
pred = logit1.predict(X_test)

res = []
for i in pred:
    if i >= 0.5:
        each = 1
    else:
        each = 0
    res.append(each)

res = Series(res)

cross_table = pd.crosstab(y_test, res, rownames=['Actual'], colnames=['Predicted'], margins=True)

d = confusion_matrix(y_test, res)

建议编辑:

cross_table = pd.crosstab(y_test, res, rownames=['Actual'], 
colnames=['Predicted'], margins=True,dropna=False)

Predicted   0.0  1.0   All
Actual                    
0.0         413   52  1927
1.0         140   20   574
All        2186  315  4377

【问题讨论】:

【参考方案1】:

虽然我仍然不知道为什么上述方法不起作用,但我想出了需要进行哪些更改才能使其起作用。包含预测的对象 res 需要保存为数组:

import numpy as np

res = np.array(res)
cross_table = pd.crosstab(y_test, res, rownames=['Actual'], colnames=['Predicted'], margins=True)

Predicted     0    1   All
Actual                    
0          1817  110  1927
1           369  205   574
All        2186  315  2501

与confusion_matrix的结果相同。

【讨论】:

【参考方案2】:

如果我这样做:

import numpy as np
import pandas as pd
data = np.array([1, 1, 0, 0, 0])
data2 = np.array([1, 0, 0, 0, 1])
y_test =  pd.Series(data) 
res = pd.Series(data2)

然后运行:pd.crosstab(y_test, res, rownames=['Actual'], colnames=['Predicted'], margins=True)

我明白了:

这是正确的。

还有:

from sklearn.metrics import ocnfusion_matrix
confusion_matrix(y_test, res)

给我正确的输出,所以错误在其他地方。

【讨论】:

以上是关于交叉表和混淆矩阵在 Python 中导致不一致的主要内容,如果未能解决你的问题,请参考以下文章

在 KFold 交叉验证的情况下如何显示平均分类报告和混淆矩阵

10折交叉验证的混淆矩阵

交叉验证中的准确性和混淆矩阵

Python - 混淆矩阵维度的差异

sklearn中留一法交叉验证的混淆矩阵

获取每个交叉验证折叠的混淆矩阵