我在使用决策树分类器测试一个带有两个标签’A’和’B’的数据集时,意外发现模型在相同测试数据上得到了不同的精确度结果。我想知道这是为什么。
这是我的操作步骤,我先训练模型,然后在以下数据集上进行测试:
1. 测试集,2. 测试集中仅标记为'A'的数据,3. 测试集中仅标记为'B'的数据。
以下是我得到的结果:
-
对于测试数据集
精确度 召回率 F1分数 支持度A 0.94 0.95 0.95 25258B 0.27 0.22 0.24 1963
-
对于测试数据集中仅标记为’A’的数据
精确度 召回率 F1分数 支持度A 1.00 0.95 0.98 25258B 0.00 0.00 0.00 0
-
对于测试数据集中仅标记为’B’的数据
精确度 召回率 F1分数 支持度A 0.00 0.00 0.00 0B 1.00 0.22 0.36 1963
训练数据集和模型是相同的,2和3次测试中的数据也与1中相同。为什么’A’和’B’的精确度差异如此之大?这个模型的真实精确度是多少?非常感谢。
回答:
你听起来很困惑,而且完全不清楚你为什么对从评估集中完全移除其中一个标签的指标感兴趣。
让我们用一些可复制的虚拟数据来探索这个问题:
from sklearn.metrics import classification_reportimport numpy as npy_true = np.array([0, 1, 0, 1, 1, 0, 0])y_pred = np.array([0, 0, 1, 1, 0, 0, 1])target_names = ['A', 'B']print(classification_report(y_true, y_pred, target_names=target_names))
结果:
精确度 召回率 F1分数 支持度 A 0.50 0.50 0.50 4 B 0.33 0.33 0.33 3avg / total 0.43 0.43 0.43 7
现在,让我们在y_true
中只保留类别A:
indA = np.where(y_true==0)print(indA)print(y_true[indA])print(y_pred[indA])
结果:
(array([0, 2, 5, 6], dtype=int64),)[0 0 0 0] [0 1 0 1]
现在,这是scikit-learn文档中对精确度的定义:
精确度是
tp / (tp + fp)
的比率,其中tp
是真阳性的数量,fp
是假阳性的数量。直观上,精确度是分类器不将负样本标记为正样本的能力。
对于类别A,真阳性(tp
)将是真实类别为A(在我们的例子中为0
),并且我们确实预测了A(0
)的情况;从上面的结果可以明显看出,tp=2
。
棘手的部分是假阳性(fp
):它们是我们预测为A(0
)的情况,而真实标签是B(1
)。但在这里显然我们不可能有这样的情况,因为我们已经(有意地)从y_true
中移除了所有的B(为什么我们要这样做?我不知道,这完全没有意义);因此,在这种(奇怪的)设置中,fp=0
。因此,我们的类别A的精确度将是tp / (tp+0) = tp/tp = 1
。
这与分类报告给出的结果完全相同:
print(classification_report(y_true[indA], y_pred[indA], target_names=target_names))# 结果: 精确度 召回率 F1分数 支持度 A 1.00 0.50 0.67 4 B 0.00 0.00 0.00 0avg / total 1.00 0.50 0.67 4
显然,B的情况也是相同的。
为什么在情况#1中(对于A和B)精确度不是1?数据是相同的
不,它们显然不是相同的——真实情况已经被改变了!
结论:在计算精确度等之前从y_true
中移除类别完全没有意义(即你在情况#2和情况#3中报告的结果没有任何实际用途);但是,由于你出于某些原因决定这样做,你报告的结果正是预期的。