精度类型

Type of precision

使用keras库获得以下精度:

model.compile(optimizer='sgd',
          loss='mse',
          metrics=[tf.keras.metrics.Precision()])

sklearn计算出的精度和keras计算出的精度是多少?

precision_score(y_true, y_pred, average=???)
  1. 微型
  2. 加权
  3. none

当您将 zero_division 设置为 1 时会发生什么?:

precision_score(y_true, y_pred, average=None, zero_division=1)

TLDR; 二进制 class 化默认为 binary 多 class class 默认为 micro ]化。其他平均类型,如 Nonemacro 也可以通过如下所述的微小修改来实现。


这应该可以让您清楚地了解 tf.keras.Precision()sklearn.metrics.precision_score() 之间的区别。让我们比较一下不同的场景。

场景一:二进制class化

对于二进制class化,你的y_true和y_pred分别是0,1和0-1。两者的实现都非常简单。

Sklearn documentation: Only report results for the class specified by pos_label. This is applicable only if targets (y_{true,pred}) are binary.

#Binary classification

from sklearn.metrics import precision_score
import tensorflow as tf

y_true = [0,1,1,1]
y_pred = [1,0,1,1]

print('sklearn precision: ',precision_score(y_true, y_pred, average='binary'))
#Only report results for the class specified by pos_label. 
#This is applicable only if targets (y_{true,pred}) are binary.

m = tf.keras.metrics.Precision()
m.update_state(y_true, y_pred)
print('tf.keras precision:',m.result().numpy())
sklearn precision:  0.6666666666666666
tf.keras precision: 0.6666667

场景二:多classclass化(全局精度)

这里您使用的是多个 class 标签,但您并不关心每个 class 的精度如何。您只需要一组全局 TP 和 FP 来计算总精度分数。在 sklearn 中,这是由参数 micro 设置的,而在 tf.keras 中,这是 Precision()

的默认设置

Sklearn documentation: Calculate metrics globally by counting the total true positives, false negatives and false positives.

#Multi-class classification (global precision)

#3 classes, 6 samples
y_true = [[1,0,0],[0,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,1]]
y_pred = [[1,0,0],[0,0,1],[0,1,0],[1,0,0],[1,0,0],[0,1,0]]

print('sklearn precision: ',precision_score(y_true, y_pred, average='micro'))
#Calculate metrics globally by counting the total true positives, false negatives and false positives.

m.reset_states()
m = tf.keras.metrics.Precision()
m.update_state(y_true, y_pred)
print('tf.keras precision:',m.result().numpy())
sklearn precision:  0.3333333333333333
tf.keras precision: 0.33333334

场景3:多classclass化(每个标签的二进制精度)

如果您想知道每个人的精度,您会对这种情况感兴趣 class。在 sklearn 中,这是通过将 average 参数设置为 None 来完成的,而在 tf.keras 中,您必须使用 class 分别为每个个体实例化对象 class_id.

Sklearn documentation: If None, the scores for each class are returned.

#Multi-class classification (binary precision for each label)

#3 classes, 6 samples
y_true = [[1,0,0],[0,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,1]]
y_pred = [[1,0,0],[0,0,1],[0,1,0],[1,0,0],[1,0,0],[0,1,0]]

print('sklearn precision: ',precision_score(y_true, y_pred, average=None))
#If None, the scores for each class are returned.

#For class 0
m0 = tf.keras.metrics.Precision(class_id=0)
m0.update_state(y_true, y_pred)

#For class 1
m1 = tf.keras.metrics.Precision(class_id=1)
m1.update_state(y_true, y_pred)

#For class 2
m2 = tf.keras.metrics.Precision(class_id=2)
m2.update_state(y_true, y_pred)

mm = [m0.result().numpy(), m1.result().numpy(), m2.result().numpy()]

print('tf.keras precision:',mm)
sklearn precision:  [0.66666667 0.         0.        ]
tf.keras precision: [0.6666667, 0.0, 0.0]

场景4:Multi-class classification(单个二进制分数的平均值)

计算出每个 class 的个体精确度后,您可能需要取平均分(或加权平均分)。在 sklearn 中,通过将参数 average 设置为 macro 来取单个分数的简单平均值。在 tf.keras 中,您可以通过对上述场景中计算的各个精度取平均值来获得相同的结果。

Sklearn documentation: Calculate metrics for each label, and find their unweighted mean.

#Multi-class classification (Average of individual binary scores)

#3 classes, 6 samples
y_true = [[1,0,0],[0,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,1]]
y_pred = [[1,0,0],[0,0,1],[0,1,0],[1,0,0],[1,0,0],[0,1,0]]

print('sklearn precision (Macro): ',precision_score(y_true, y_pred, average='macro'))
print('sklearn precision (Avg of None):' ,np.average(precision_score(y_true, y_pred, average=None)))

print(' ')

print('tf.keras precision:',np.average(mm)) #mm is list of individual precision scores
sklearn precision (Macro):  0.2222222222222222
sklearn precision (Avg of None):  0.2222222222222222
 
tf.keras precision: 0.22222222

注意: 请记住,使用 sklearn,您拥有直接预测标签的模型,而 precision_score 是一种独立方法。因此,它可以直接对预测和实际标签列表进行操作。但是,tf.keras.Precision() 是一个必须应用于二进制或多 class 密集输出的指标。它将无法直接使用标签。您必须为每个样本提供一个长度为 n 的数组,其中 n 是 classes/output 个密集节点的数量。

希望这能阐明两者在各种情况下的不同之处。请在 sklearn documentation and the tf.keras documentation.

中找到更多详细信息

你的第二个问题-

根据 sklearn 文档,

zero_division - “warn”, 0 or 1, default=”warn”
#Sets the value to return when there is a zero division. If set to “warn”, #this acts as 0, but warnings are also raised.

这是一个异常处理标志。在计算分数的过程中,如果遇到divide by zero,它会认为它等于0并警告。否则,如果明确设置为 1,则将其设置为 1。