Scikit-learn混淆矩阵

时间:2016-02-03 13:35:47

标签: python machine-learning scikit-learn classification

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

confusion_matrix(y_test, preds)
 [ [30  5]
    [2 42] ]

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

          prediction                        prediction
           0       1                          1       0
         -----   -----                      -----   -----
      0 | TN   |  FP        (OR)         1 |  TP  |  FP
actual   -----   -----             actual   -----   -----
      1 | FN   |  TP                     0 |  FN  |  TN

4 个答案:

答案 0 :(得分:18)

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

这是用docs

写的
  

标签:数组,形状= [n_classes],可选   索引矩阵的标签列表。这可用于重新排序或选择标签的子集。 如果没有,那么在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]])

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

>>> 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]])
  • true:0,预测:0(值:3,位置[0,0])
  • true:5,预测:0(值:2,位置[1,0])
  • true:0,预测:5(值:0,位置[0,1])
  • true:5,预测:5(值:1,位置[1,1])

答案 1 :(得分:1)

简短答案 在二进制分类中,当使用参数labels时,

confusion_matrix([0, 1, 0, 1], [1, 1, 1, 0], labels=[0,1]).ravel()

类标签01分别被视为NegativePositive。这是由于列表所隐含的顺序,而不是字母数字顺序。


验证: 考虑这样的不平衡类标签:(使用不平衡类使区分更加容易)

>>> y_true = [0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0]
>>> y_pred = [0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0]
>>> table = confusion_matrix(y_true, y_pred, labeels=[0,1]).reval()

这会给您一个混乱的表,如下所示:

>>> table
array([12,  1,  2,  1])

对应于:

              Actual
        |   1   |   0  |
     ___________________
pred  1 |  TP=1 | FP=1 |
      0 |  FN=2 | TN=12|

其中FN=2表示在2种情况下,模型预测样本为负(即0),但实际标签为正(即1),因此假负等于2。

TN=12类似,在12种情况下,模型可以正确预测负类(0),因此True Negative等于12。

这样,假设sklearn将第一个标签(在labels=[0,1]中视为否定类,则所有内容加起来。因此,这里,第一个标签0代表否定类。

答案 2 :(得分:1)

wikipedia为例。如果已经训练了分类系统来区分猫和非猫,那么混淆矩阵将汇总测试算法的结果以进行进一步检查。假设有27种动物(8只猫和19只非猫)的样本,得出的混淆矩阵如下表所示:

enter image description here

使用sklearn

如果要维护Wikipedia混淆矩阵的结构,请首先输入预测值,然后输入实际类。

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)

使用交叉表熊猫的另一种方式

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

我希望它能为您服务

答案 3 :(得分:0)

支持答案:

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

[真否定假阳性]   [假阴性真阳性]

如果您误解了值,例如说TN的TP,则您的精度和AUC_ROC或多或少会匹配,但是您的精度,召回率,灵敏度和f1得分会受到打击最终将获得完全不同的指标。这将导致您对模型的性能做出错误的判断。

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

体验:

我正在预测欺诈(二进制监督分类),其中欺诈用1表示,非欺诈用0表示。我的模型是在放大的,完美平衡的数据集上进行训练的,因此在实时测试中,当我的结果达到顺序时,混淆矩阵的值似乎并不可疑 [TP FP]   [FN TN]

后来,当我不得不对新的不平衡测试集执行过期测试时,我意识到上述混淆矩阵的顺序是错误,与sklearn的文档页面上提到的顺序不同,后者将顺序称为 tn,fp,fn,tp 。插入新订单使我意识到错误,以及对模型性能的判断有何不同。