Scikit-learn混淆矩阵

OAK*_*OAK 16 python classification machine-learning scikit-learn

我无法弄清楚我是否正确设置了二进制分类问题.我标记了正类1和负0.但是我的理解是默认情况下scikit-learn在其混淆矩阵中使用0类作为正类(因此我将其设置为反向).这对我来说很困惑.在scikit-learn的默认设置中,排名是正面还是负面?让我们假设混淆矩阵输出:

confusion_matrix(y_test, preds)
 [ [30  5]
    [2 42] ]
Run Code Online (Sandbox Code Playgroud)

它在混淆矩阵中会是什么样子?实际实例是scikit-learn中的行还是列?

          prediction                        prediction
           0       1                          1       0
         -----   -----                      -----   -----
      0 | TN   |  FP        (OR)         1 |  TP  |  FP
actual   -----   -----             actual   -----   -----
      1 | FN   |  TP                     0 |  FN  |  TN
Run Code Online (Sandbox Code Playgroud)

lej*_*lot 24

scikit学习按升序排序标签,因此0是第一列/行,1是第二列

>>> from sklearn.metrics import confusion_matrix as cm
>>> y_test = [1, 0, 0]
>>> y_pred = [1, 0, 0]
>>> cm(y_test, y_pred)
array([[2, 0],
       [0, 1]])
>>> y_pred = [4, 0, 0]
>>> y_test = [4, 0, 0]
>>> cm(y_test, y_pred)
array([[2, 0],
       [0, 1]])
>>> y_test = [-2, 0, 0]
>>> y_pred = [-2, 0, 0]
>>> cm(y_test, y_pred)
array([[1, 0],
       [0, 2]])
>>> 
Run Code Online (Sandbox Code Playgroud)

这是在文档中写的:

labels:array,shape = [n_classes],optional用于索引矩阵的标签列表.这可用于重新排序或选择标签的子集.如果没有给出,那么在y_true或y_pred中至少出现一次的那些按排序顺序使用.

因此,您可以通过向confusion_matrix调用提供标签来改变此行为

>>> y_test = [1, 0, 0]
>>> y_pred = [1, 0, 0]
>>> cm(y_pred, y_pred)
array([[2, 0],
       [0, 1]])
>>> cm(y_pred, y_pred, labels=[1, 0])
array([[1, 0],
       [0, 2]])
Run Code Online (Sandbox Code Playgroud)

实际/预测就像你的图像一样 - 预测在列中,实际值在行中

>>> y_test = [5, 5, 5, 0, 0, 0]
>>> y_pred = [5, 0, 0, 0, 0, 0]
>>> cm(y_test, y_pred)
array([[3, 0],
       [2, 1]])
Run Code Online (Sandbox Code Playgroud)
  • true:0,预测:0(值:3,位置[0,0])
  • true:5,预测:0(值:2,位置[1,0])
  • true:0,预测:5(值:0,位置[0,1])
  • true:5,预测:5(值:1,位置[1,1])


小智 7

支持答案:

使用sklearn.metrics绘制混淆矩阵值时,请注意值的顺序是

[真阴性假阳性][假阴性真阳性]

如果你对这些值的解释有误,比如 TN 的 TP,你的准确率和 AUC_ROC 或多或少会匹配,但你的准确率、召回率、灵敏度和 f1 分数会受到影响,你最终会得到完全不同的指标。这将导致您对模型的性能做出错误判断。

请务必清楚地确定模型中的 1 和 0 代表什么。这在很大程度上决定了混淆矩阵的结果。

经验:

我致力于预测欺诈(二元监督分类),其中欺诈用 1 表示,非欺诈用 0 表示。我的模型是在放大的、完美平衡的数据集上训练的,因此在及时测试期间,混淆矩阵的值当我的结果是 [TP FP] [FN TN]

后来,当我不得不对一个新的不平衡测试集进行超时测试时,我意识到上述混淆矩阵的顺序是错误的,并且与 sklearn 的文档页面上提到的顺序不同,该顺序将顺序称为tn, fp, fn, tp。插入新订单让我意识到这个错误以及它在我对模型性能的判断中造成的差异。


Raf*_*íaz 5

按照维基百科的例子。如果分类系统已经被训练来区分猫和非猫,混淆矩阵将总结测试算法的结果以供进一步检查。假设有 27 只动物的样本——8 只猫和 19 只非猫,产生的混淆矩阵可能如下表所示:

在此处输入图片说明

使用 sklearn

如果你想保持维基百科混淆矩阵的结构,首先是预测值,然后是实际类。

from sklearn.metrics import confusion_matrix
y_true = [0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,0]
y_pred = [0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,1,0,0,0]
confusion_matrix(y_pred, y_true, labels=[1,0])

Out[1]: 
array([[ 5,  2],
       [ 3, 17]], dtype=int64)
Run Code Online (Sandbox Code Playgroud)

交叉表熊猫的另一种方式

true = pd.Categorical(list(np.where(np.array(y_true) == 1, 'cat','non-cat')), categories = ['cat','non-cat'])
pred = pd.Categorical(list(np.where(np.array(y_pred) == 1, 'cat','non-cat')), categories = ['cat','non-cat'])

pd.crosstab(pred, true, 
            rownames=['pred'], 
            colnames=['Actual'], margins=False, margins_name="Total")

Out[2]: 
Actual   cat  non-cat
pred                 
cat        5        2
non-cat    3       17
Run Code Online (Sandbox Code Playgroud)

  • 主啊!sklearn的confusion_matrix采用confusion_matrix(y_true, y_pred)。你把参数弄反了!我也喜欢维基百科的混淆矩阵结构,但 labels=[1,0] 只给出(令人困惑的)转置。 (2认同)