关于torchmetrics中F1 Score的mdmc_reduce参数使用及相关问题咨询
12类多分类任务中TorchMetrics F1 Score的mdmc_reduce参数及独热编码问题
问题背景
在12类单标签多分类任务中,使用TorchMetrics计算F1 Score时遇到mdmc_reduce参数的必填提示,相关代码及数据如下:
import torch from torchmetrics import F1 # 模型输出概率 y_pred = torch.tensor([[0.0793, 0.1140, 0.1216, 0.0727, 0.0671, 0.0810, 0.0646, 0.0759, 0.1108, 0.0600, 0.0578, 0.0952], [0.0830, 0.1252, 0.0985, 0.0736, 0.0722, 0.0839, 0.0734, 0.0721, 0.1242, 0.0516, 0.0636, 0.0788], [0.0779, 0.1169, 0.1129, 0.0715, 0.0713, 0.0930, 0.0693, 0.0786, 0.1065, 0.0591, 0.0577, 0.0856]]) # 真实标签(独热编码格式) y_true = torch.tensor([[0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) # 转换预测为独热编码 predictions = torch.argmax(y_pred, dim=1) one_hot_predictions = torch.nn.functional.one_hot(predictions, num_classes=12) # 尝试计算F1(报错需指定mdmc_reduce) f1_micro = F1(average='micro') f1_macro = F1(num_classes=12, average='macro') print(f"F1 Micro: {f1_micro(one_hot_predictions, y_true)}") print(f"F1 Macro: {f1_macro(one_hot_predictions, y_true)}")
问题解答
1. mdmc_reduce参数的区别与选择
mdmc_reduce是TorchMetrics针对多维多类别输入(比如独热编码格式的标签/预测)设计的参数,两个选项的核心区别:
mdmc_reduce='global':将所有样本的所有类别预测与真实标签合并,统一计算全局混淆矩阵后得到F1值。这是单标签多分类任务的正确选择——因为每个样本只有一个正类别,全局统计能准确反映模型整体性能。mdmc_reduce='samplewise':对每个样本单独计算F1值,再取所有样本的平均值。这仅适用于多标签任务(每个样本可能有多个正类别),你的单标签场景完全不需要用这个选项。
你的场景直接选mdmc_reduce='global'即可。
2. 是否需要将y_pred转换为独热编码?
不需要,且不推荐。
TorchMetrics的F1指标支持直接传入类别索引格式的预测和真实标签:
- 预测:用
torch.argmax(y_pred, dim=1)得到的一维张量(每个元素对应样本的预测类别索引) - 真实标签:可以将原独热编码用
torch.argmax(y_true, dim=1)转成一维类别索引张量
这种方式不需要设置mdmc_reduce,逻辑更清晰,计算也更高效。
修正后的代码示例
方式1:用类别索引(推荐)
import torch from torchmetrics import F1 y_pred = torch.tensor([[0.0793, 0.1140, 0.1216, 0.0727, 0.0671, 0.0810, 0.0646, 0.0759, 0.1108, 0.0600, 0.0578, 0.0952], [0.0830, 0.1252, 0.0985, 0.0736, 0.0722, 0.0839, 0.0734, 0.0721, 0.1242, 0.0516, 0.0636, 0.0788], [0.0779, 0.1169, 0.1129, 0.0715, 0.0713, 0.0930, 0.0693, 0.0786, 0.1065, 0.0591, 0.0577, 0.0856]]) y_true = torch.tensor([[0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) # 转换为类别索引 predictions = torch.argmax(y_pred, dim=1) true_labels = torch.argmax(y_true, dim=1) # 计算F1 f1_micro = F1(average='micro', num_classes=12) f1_macro = F1(average='macro', num_classes=12) print(f"F1 Micro: {f1_micro(predictions, true_labels)}") print(f"F1 Macro: {f1_macro(predictions, true_labels)}")
方式2:用独热编码(需指定mdmc_reduce)
import torch from torchmetrics import F1 y_pred = torch.tensor([[0.0793, 0.1140, 0.1216, 0.0727, 0.0671, 0.0810, 0.0646, 0.0759, 0.1108, 0.0600, 0.0578, 0.0952], [0.0830, 0.1252, 0.0985, 0.0736, 0.0722, 0.0839, 0.0734, 0.0721, 0.1242, 0.0516, 0.0636, 0.0788], [0.0779, 0.1169, 0.1129, 0.0715, 0.0713, 0.0930, 0.0693, 0.0786, 0.1065, 0.0591, 0.0577, 0.0856]]) y_true = torch.tensor([[0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) # 转换为独热编码 predictions = torch.argmax(y_pred, dim=1) one_hot_predictions = torch.nn.functional.one_hot(predictions, num_classes=12) # 计算F1,指定mdmc_reduce='global' f1_micro = F1(average='micro', mdmc_reduce='global') f1_macro = F1(average='macro', num_classes=12, mdmc_reduce='global') print(f"F1 Micro: {f1_micro(one_hot_predictions, y_true)}") print(f"F1 Macro: {f1_macro(one_hot_predictions, y_true)}")
内容的提问来源于stack exchange,提问作者Josalo9
相关产品推荐
相关产品推荐

