【问题标题】:Scikit-learn confusion matrixScikit-learn 混淆矩阵
【发布时间】:2016-05-12 17:46:57
【问题描述】:

我不知道我是否正确设置了二进制分类问题。我标记了正类 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

【问题讨论】:

    标签: python machine-learning scikit-learn classification


    【解决方案1】:

    我认为我们最终决定称之为“积极”或“消极”是一个选择问题,而 sklearn 并不知道这一点。您可以以任何您想要的方式标记数据点(不仅仅是 0 和 1),因此“sklearn 将 0 用作‘正数’”(反之亦然)的声明根本不成立。
    如果您没有专门使用“标签”参数来指定行和列标签的顺序,那么 sklearn 将按字母数字对它们进行排序。所以你可以以任何你想要的方式输出你的混淆矩阵,你可以决定你所说的(在最简单的二进制情况下)“正/负”。 sklearn 不会为您做出这些决定。

    【讨论】:

      【解决方案2】:

      scikit learn 按升序对标签进行排序,因此 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 中至少出现一次的那些将按排序顺序使用

      因此,您可以通过为混淆矩阵调用提供标签来改变这种行为

      >>> y_test = [1, 0, 0]
      >>> y_pred = [1, 0, 0]
      >>> cm(y_test, y_pred)
      array([[2, 0],
             [0, 1]])
      >>> cm(y_test, 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]])
      
      • 真:0,预测:0(值:3,位置 [0, 0])
      • 真:5,预测:0(值:2,位置 [1, 0])
      • 真:0,预测:5(值:0,位置 [0, 1])
      • 真:5,预测:5(值:1,位置 [1, 1])

      【讨论】:

        【解决方案3】:

        wikipedia 为例。如果一个分类系统已经被训练来区分猫和非猫,一个混淆矩阵将总结测试算法的结果以供进一步检查。假设有 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)
        

        crosstab pandas 的另一种方式

        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
        

        【讨论】:

        • 天哪! sklearn 的混淆矩阵采用混淆矩阵(y_true,y_pred)。你有参数倒退!我也喜欢维基百科的混淆矩阵结构,但 labels=[1,0] 只给出一个(混淆)转置。
        【解决方案4】:

        简答 在二元分类中,使用参数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, labels=[0,1]).ravel()
        

        这会给你一个混淆表如下:

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

        对应于:

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

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

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

        这样一来,假设sklearn 将第一个标签(在labels=[0,1] 中作为否定类)考虑在内,所有内容都会相加。因此,这里的第一个标签0 代表否定类。

        【讨论】:

          【解决方案5】:

          支持答案:

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

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

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

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

          经验:

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

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

          【讨论】:

            猜你喜欢
            • 2018-05-22
            • 2014-06-11
            • 2020-07-16
            • 2020-05-30
            • 2013-08-25
            • 2017-03-03
            • 1970-01-01
            • 2022-10-20
            • 2018-01-15
            相关资源
            最近更新 更多