- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 PyTorch 中本地实现宏 F1 分数(F 度量),而不是使用已经广泛使用的 sklearn.metrics.f1_score以便直接在 GPU 上计算测量值。
据我了解,为了计算宏观 F1 分数,我需要计算所有标签的 F1 分数以及灵敏度和精度,然后取所有这些的平均值。
我目前的实现是这样的:
def confusion_matrix(y_pred: torch.Tensor, y_true: torch.Tensor, n_classes: int):
conf_matrix = torch.zeros([n_classes, n_classes], dtype=torch.int)
y_pred = torch.argmax(y_pred, 1)
for t, p in zip(y_true.view(-1), y_pred.view(-1)):
conf_matrix[t.long(), p.long()] += 1
return conf_matrix
def forward(self, y_pred: torch.Tensor, y_true: torch.Tensor) -> torch.Tensor:
conf_matrix = confusion_matrix(y_pred, y_true, self.classes)
TP = conf_matrix.diag()
f1_scores = torch.zeros(self.classes, dtype=torch.float)
for c in range(self.classes):
idx = torch.ones(self.classes, dtype=torch.long)
idx[c] = 0
FP = conf_matrix[c, idx].sum()
FN = conf_matrix[idx, c].sum()
sensitivity = TP[c] / (TP[c] + FN + self.epsilon)
precision = TP[c] / (TP[c] + FP + self.epsilon)
f1_scores[c] += 2.0 * ((precision * sensitivity) / (precision + sensitivity + self.epsilon))
return f1_scores.mean()
self.classes
是标签的数量,self.epsilon
是一个非常小的值,设置为 10-e12
可以防止 DivisionByZeroError
.
训练时,我计算每个批处理的度量值,并将所有度量值的平均值作为最终分数。
问题是,当我将自定义 F1 分数与 sklearn 的宏观 F1 分数进行比较时,它们很少相等。
# example 1
eval_cce 0.5203, eval_f1 0.8068, eval_acc 81.5455, eval_f1_sci 0.8023,
test_cce 0.4784, test_f1 0.7975, test_acc 82.6732, test_f1_sci 0.8097
# example 2
eval_cce 0.3304, eval_f1 0.8211, eval_acc 87.4955, eval_f1_sci 0.8626,
test_cce 0.3734, test_f1 0.8183, test_acc 85.4996, test_f1_sci 0.8424
# example 3
eval_cce 0.4792, eval_f1 0.7982, eval_acc 81.8482, eval_f1_sci 0.8001,
test_cce 0.4722, test_f1 0.7905, test_acc 82.6533, test_f1_sci 0.8139
虽然我尝试浏览互联网,但大多数案例都涉及二进制分类。我还没有找到一个例子来尝试做我想做的事情。
我的尝试有什么明显的问题吗?
我还没有弄清楚我的错误。由于时间限制,我决定只使用 sklearn 提供的 F1 宏分数。虽然它不能直接与 GPU 张量一起使用,但它对于我的情况来说已经足够快了。
但是,如果有人能解决这个问题,那就太棒了,这样任何其他可能偶然发现这个问题的人都可以解决他们的问题。
最佳答案
我前段时间用Pytorch写了自己的实现:
from typing import Tuple
import torch
class F1Score:
"""
Class for f1 calculation in Pytorch.
"""
def __init__(self, average: str = 'weighted'):
"""
Init.
Args:
average: averaging method
"""
self.average = average
if average not in [None, 'micro', 'macro', 'weighted']:
raise ValueError('Wrong value of average parameter')
@staticmethod
def calc_f1_micro(predictions: torch.Tensor, labels: torch.Tensor) -> torch.Tensor:
"""
Calculate f1 micro.
Args:
predictions: tensor with predictions
labels: tensor with original labels
Returns:
f1 score
"""
true_positive = torch.eq(labels, predictions).sum().float()
f1_score = torch.div(true_positive, len(labels))
return f1_score
@staticmethod
def calc_f1_count_for_label(predictions: torch.Tensor,
labels: torch.Tensor, label_id: int) -> Tuple[torch.Tensor, torch.Tensor]:
"""
Calculate f1 and true count for the label
Args:
predictions: tensor with predictions
labels: tensor with original labels
label_id: id of current label
Returns:
f1 score and true count for label
"""
# label count
true_count = torch.eq(labels, label_id).sum()
# true positives: labels equal to prediction and to label_id
true_positive = torch.logical_and(torch.eq(labels, predictions),
torch.eq(labels, label_id)).sum().float()
# precision for label
precision = torch.div(true_positive, torch.eq(predictions, label_id).sum().float())
# replace nan values with 0
precision = torch.where(torch.isnan(precision),
torch.zeros_like(precision).type_as(true_positive),
precision)
# recall for label
recall = torch.div(true_positive, true_count)
# f1
f1 = 2 * precision * recall / (precision + recall)
# replace nan values with 0
f1 = torch.where(torch.isnan(f1), torch.zeros_like(f1).type_as(true_positive), f1)
return f1, true_count
def __call__(self, predictions: torch.Tensor, labels: torch.Tensor) -> torch.Tensor:
"""
Calculate f1 score based on averaging method defined in init.
Args:
predictions: tensor with predictions
labels: tensor with original labels
Returns:
f1 score
"""
# simpler calculation for micro
if self.average == 'micro':
return self.calc_f1_micro(predictions, labels)
f1_score = 0
for label_id in range(1, len(labels.unique()) + 1):
f1, true_count = self.calc_f1_count_for_label(predictions, labels, label_id)
if self.average == 'weighted':
f1_score += f1 * true_count
elif self.average == 'macro':
f1_score += f1
if self.average == 'weighted':
f1_score = torch.div(f1_score, len(labels))
elif self.average == 'macro':
f1_score = torch.div(f1_score, len(labels.unique()))
return f1_score
您可以通过以下方式进行测试:
from sklearn.metrics import f1_score
import numpy as np
errors = 0
for _ in range(10):
labels = torch.randint(1, 10, (4096, 100)).flatten()
predictions = torch.randint(1, 10, (4096, 100)).flatten()
labels1 = labels.numpy()
predictions1 = predictions.numpy()
for av in ['micro', 'macro', 'weighted']:
f1_metric = F1Score(av)
my_pred = f1_metric(predictions, labels)
f1_pred = f1_score(labels1, predictions1, average=av)
if not np.isclose(my_pred.item(), f1_pred.item()):
print('!' * 50)
print(f1_pred, my_pred, av)
errors += 1
if errors == 0:
print('No errors!')
关于python - 在 PyTorch 中本地测量多类分类的 F1 分数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62265351/
直接从 Python 代码运行 pylint 时,我似乎无法获得任何返回值。从命令行运行它会生成一个漂亮的报告,在底部有一个总结分数。 我已经尝试将“Run”的返回值放入一个变量中,并获取它的“rep
我是 Python 新手,正在尝试学习单词检测。我有一个带有单词的数据框 sharina['transcript'] Out[25]: 0 thank you for calling my
http://jsfiddle.net/q8P7Y/ 我在最后显示最终分数时遇到问题,有很多方法可以做到这一点,但我不确定什么是最好的。 正如你所看到的,下一个按钮只是 div 的显示/隐藏,而不是页
我使用滑动 slider 并有计数器分数。它计数很好,但我需要计数 =(所有幻灯片 - 1)。例如,如果我有 20 张幻灯片,我想显示总数 19。有什么办法可以做到这一点吗?我使用他们网站上的常规 j
我使用滑动 slider 并有计数器分数。它计数很好,但我需要计数 =(所有幻灯片 - 1)。例如,如果我有 20 张幻灯片,我想显示总数 19。有什么办法可以做到这一点吗?我使用他们网站上的常规 j
我试图在按下按钮时添加分数,分数显示在 JTextField 中,但是当按下按钮时,分数会添加,它显示为 0。我有一个存储分数的整数字段 private int score=0; yesButton
我可以在选项(单选按钮)随机播放之前计算分数/分数,如下面的代码所示。在Collection.shuffle()之前,选项是固定的,因为 CorrectChoice将始终分配给c2单选按钮。那么我可以
我在这里的代码只能得到87%的代码,因为“带有非正参数的加法参数什么也没做。我该如何解决呢?我尝试了更多的方法,但是我什至无法解决此错误在同学的帮助下 说明是: 对于此分配,您将创建一个存储分数的类。
昨天,我尝试以一种方式执行此操作...今天我尝试另一种方式,但仍然卡住了。我必须找到一种使用整数除法和取模来做到这一点的方法。这是我的代码,后面是错误消息。 public int evaluateFr
我这里有一些特殊字符: http://209.141.56.244/test/char.php 但是当我在这里通过 ajax 抓取这个文件时,它们显示为 back ?标记: http://209.14
我得到了一张图表 G与 n顶点,标记自 1至 n (2 a_1 -> a_2 -> ... a_k -> n A然后将占据 1 的所有“子节点”节点, a_1 , ... a_x (其中 x = ce
我有一个看起来像这样的 mongodb 集合: db.scores.insert({"name": "Bob", value: 96.3, timeStamp:'2010-9-27 9:32:00'}
我试图更好地了解 lucene 如何对我的搜索进行评分,以便我可以对我的搜索配置或文档内容进行必要的调整。 以下是分数明细的一部分。 产品: 0.34472802 = queryWeight,
在我网站上用户生成的帖子下,我有一个类似亚马逊的评级系统: Was this review helpful to you: Yes | No 如果有投票,我会在该行上方显示结果,如下所示:
对于我的项目,我需要找出哪些搜索结果被视为“良好”匹配。目前,分数因查询而异,因此需要以某种方式对它们进行标准化。标准化分数将允许选择高于给定阈值的结果。 我为 Lucene 找到了几个解决方案: h
我有一个由 57 个变量组成的数据文件。由于测量水平不均匀,我想将其中的大约 12 个转换为 z 分数。我查找了互联网资源和帮助文件。一个互联网资源建议我需要 Rbasic 包(不存在)。我使用了 s
我对 SOLR 核心运行查询并使用过滤器限制结果例如 fq: {!frange l=0.7 }query($q)。我知道 SOLR 分数不有绝对意义,但是0.7(只是一个例子)是计算出来的基于用户输入
我想找到不同的方法来解决我遇到的现实生活问题:想象一下进行一场比赛或一场游戏,在此期间用户收集积分。您必须构建一个查询来显示具有最佳“n”分数的用户列表。 我举一个例子来澄清。假设这是用户表,其中包含
我有很多 wiki 页面,我想训练一个分类器,看看是否可以通过一些特征(包括段落的位置和段落的 lucene 分数)来确定重点搜索的位置。我尝试将每个段落视为一个文档,这使我能够获得每个段落的 luc
我是 R 编程新手,在使用一些基本代码时遇到问题。 我有一个包含以下列的数据框:条件(因子)、用户(因子)和灵敏度(int)。对于每个用户有 20 个敏感项。我需要为每个用户创建一个具有标准化敏感度分
我是一名优秀的程序员,十分优秀!