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 分数的定义是
当我用 Python 编程并在上面的矩阵上运行它时targets,probs我得到了一个结果
>>> 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 分数适用于可以构造为真或假的二元和分类结果
该函数实际上所做的是选择一个(或获取一个作为参数传递)类并将该类视为类和所有其他类作为类.
例如,如果我们选择类 3(索引 2)作为类,因此所有其他类作为类,我们得到:
>>> # 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 分数?