如何计算两个以上类别的 Brier 分数

机器算法验证 分类 scikit-学习 模型评估 计分规则
2022-02-06 13:43:44

tl;博士

如何正确计算两个以上班级的 Brier 分数?我用不同的方法得到了令人困惑的结果。详情如下。


正如在对这个问题的评论中向我建议的那样,我想评估我用 Brier 分数训练的一组分类器的质量。这些分类器是多类分类器,并且类是不平衡的。Brier 分数应该能够处理这些情况。但是,我对如何应用 Brier 分数测试不太有信心。假设我有 10 个数据点和 5 个类:

一个热向量表示给定数据项中存在哪个类:

targets = array([[0, 0, 0, 0, 1],
                 [0, 0, 0, 0, 1],
                 [0, 0, 0, 0, 1],
                 [0, 1, 0, 0, 0],
                 [0, 0, 0, 0, 1],
                 [0, 0, 1, 0, 0],
                 [1, 0, 0, 0, 0],
                 [0, 1, 0, 0, 0],
                 [1, 0, 0, 0, 0],
                 [1, 0, 0, 0, 0]])

概率向量代表我的分类器的输出,为每个类分配一个概率

probs = array([[0.14, 0.38, 0.4 , 0.04, 0.05],
               [0.55, 0.05, 0.34, 0.04, 0.01],
               [0.3 , 0.35, 0.18, 0.09, 0.08],
               [0.23, 0.22, 0.04, 0.05, 0.46],
               [0.  , 0.15, 0.47, 0.28, 0.09],
               [0.23, 0.13, 0.34, 0.27, 0.03],
               [0.32, 0.06, 0.59, 0.02, 0.01],
               [0.01, 0.19, 0.01, 0.03, 0.75],
               [0.27, 0.38, 0.03, 0.12, 0.2 ],
               [0.17, 0.45, 0.11, 0.25, 0.01]])

这些矩阵是共同索引的,probs[i, j]类别的概率也是如此targets[i, j]

现在,根据维基百科,多个类别的 Brier 分数的定义是

1Nt=1Ni=1R(ftioti)2

当我用 Python 编程并在上面的矩阵上运行它时targetsprobs我得到了一个结果1.0069

>>> def brier_multi(targets, probs):
...     return np.mean(np.sum((probs - targets)**2, axis=1))
... 
>>> brier_multi(targets, probs)
1.0068899999999998

但我不确定我是否正确解释了定义。

对于 Python,sklearn 库提供sklearn.metrics.brier_score_loss. 虽然文档指出

Brier 分数适用于可以构造为真或假的二元和分类结果

该函数实际上所做的是选择一个(或获取一个作为参数传递)n>2类并将该类视为类1和所有其他类作为类0.

例如,如果我们选择类 3(索引 2)作为1类,因此所有其他类作为类0,我们得到:

>>> # get true classes by argmax over binary arrays
... true_classes = np.argmax(targets, axis=1)
>>> 
>>> brier_score_loss(true_classes, probs[:,2], pos_label=2)
0.13272999999999996

或者:

>>> brier_score_loss(targets[:,2], probs[:,2])
0.13272999999999996

这确实是Brier score 的二进制版本,可以通过手动定义和运行它来显示:

>>> def brier_bin_(targets, probs):
...     return np.mean((targets - probs) ** 2)
>>> brier_bin(targets[:,2], probs[:,2])
0.13272999999999996

如您所见,这与使用 sklearn 的结果相同brier_score_loss

维基百科关于二进制版本的状态:

此公式主要用于二元事件(例如“下雨”或“不下雨”)。上述等式是仅适用于二元事件的正确评分规则;

所以......现在我很困惑,有以下问题:

1)如果 sklearn 将多类 Brier 分数计算为 One vs. All 二元分数,这是计算多类 Brier 分数的唯一且正确的方法吗?

这导致我

2)如果是这样,我的brier_multi代码一定是基于一个误解。我对多类 Brier 分数的定义有什么误解?

3)也许我完全走错了路。在这种情况下,请向我解释,我如何正确计算 Brier 分数?

1个回答

维基百科对多个类别的 Brier 分数版本是正确的。比较Brier (1950) 的原始出版物或任何数量的学术出版物,例如Czado 等人。(2009 年)(等式(6),尽管您需要做一些简单的算术并去掉一个常数 1 才能得出 Brier 的公式)。

  1. 如果 sklearn 计算二进制“一对多”的 Brier 分数并对焦点类的所有选择进行平均,那么它当然可以这样做。然而,这根本不是 Brier 分数。如此传递它是误导和错误的。

  2. 误解完全在于sklearn。

  3. 只需使用 your brier_multi,它是完全正确的。