【TorchMetrics精通系列①】核心设计哲学 + Accuracy 超详解

文章目录

  • 1、指标评估整体介绍
  • [2、 `torchmetrics` 文本分类指标 - 通用](#2、 torchmetrics 文本分类指标 - 通用)
  • [3、`torchmetrics` 文本分类指标 - 多分类](#3、torchmetrics 文本分类指标 - 多分类)
  • [4、准确率、精确率、召回率、F1分数 及其 类](#4、准确率、精确率、召回率、F1分数 及其 类)
  • [5、`torchmetrics` - Accuracy 详解(准确率)](#5、torchmetrics - Accuracy 详解(准确率))
  • [6、`torchmetrics` 模块式 metric - 常用 属性、方法](#6、torchmetrics 模块式 metric - 常用 属性、方法)

torchmetrics 堪称模型评估界的"绝世秘籍",招式精妙且威力无穷。若想真正参透其中玄机、融会贯通,列位看官莫急,且听我细细拆解。

这是 torchmetrics 系列文章的第一篇。

1、指标评估整体介绍

【 metric n.度量标准 】 【 metrics n.指标 】 【 matrix n.矩阵 】

📚 TorchMetrics 是什么?

TorchMetrics 最初是 PyTorch Lightning 的一部分,后来独立出来。它是一个专为 PyTorch 设计的模型评估指标库,旨在解决机器学习中指标实现不一致的问题,提供标准化、可重复的参考实现。

它不仅是 sklearn.metrics 在 PyTorch 生态中的优秀替代品,更提供了强大的分布式训练支持。其核心使命是提供标准化、可扩展、易于复现的评估方式。

主要特点:

  • 标准化接口 :提供统一的 update()compute() 接口,增加了不同项目和实验间的可复现性(Reproducibility)。
  • 自动累积与同步:自动处理跨 batch 的指标累积和多设备间的同步,非常适合大规模评估。
  • 设备兼容与优化 :指标和数据会自动放置在相同设备(CPU/GPU)上,得益于原生PyTorch实现,其计算速度通常快于 sklearn
  • 减少样板代码:封装了状态管理、设备同步等复杂逻辑,让代码更简洁。
  • 指标丰富且可扩展:内置超过100种评估指标,覆盖广泛领域,同时也易于创建自定义指标。

🚀 安装与首个示例

安装非常简单,推荐使用 pipconda

bash 复制代码
# pip 安装
pip install torchmetrics

# conda 安装
conda install -c conda-forge torchmetrics

注意 :本文章的代码基于 TorchMetrics v1.0 及以上版本 。早期版本在指标初始化时可不强制传入 task 等参数,而新版本为保障行为明确,通常要求显式指定任务类型。建议使用最新版,并养成显式传参的习惯。

安装后,可以用下面几个示例快速体验。它们演示了计算、累积和分布式三种核心用法。

  1. 函数式接口(快速计算)

适合单次、无状态的计算,用法类似 sklearn.metrics

python 复制代码
import torch
import torchmetrics

# 模拟分类问题的预测分数和真实标签
preds = torch.randn(10, 5).softmax(dim=-1)   # 5类概率
target = torch.randint(5, (10,))             # 真实类别索引

# 直接调用函数计算准确率(需指明任务类型及类别数)
acc = torchmetrics.functional.accuracy(
    preds, target, task='multiclass', num_classes=5
)
print(acc)
  1. 模块化接口(状态管理)

这是 TorchMetrics 的核心用法。内部维护状态,能自动管理跨 batch 的累计,非常适合训练循环。

在 TorchMetrics 库中,torchmetrics.Metric所有内置指标(如 Accuracy, Precision, F1Score 等)以及用户自定义指标的抽象基类(Abstract Base Class)

python 复制代码
import torch
import torchmetrics

# 初始化一个指标对象,显式指定 task 和 num_classes
metric = torchmetrics.Accuracy(task='multiclass', num_classes=5)

n_batches = 10
for i in range(n_batches):
    preds = torch.randn(10, 5).softmax(dim=-1)
    target = torch.randint(5, (10,))
    # 每次调用,指标对象内部会积累统计量(如正确数、总数)
    # 这里直接调用对象(等价于 metric.update(preds, target) 然后返回当前累积结果)
    acc = metric(preds, target)
    print(f"Accuracy on batch {i}: {acc:.4f}")

# 在所有 batch 计算完毕后,调用 .compute() 得到全局结果
total_acc = metric.compute()
print(f"Accuracy on all data: {total_acc:.4f}")

# 重置状态,为下一个 epoch 或评估周期做准备
metric.reset()
  1. 在 PyTorch Lightning 中使用(自动日志记录)

与 PyTorch Lightning 深度集成,能自动完成指标的状态重置和日志记录,代码极为简洁。

python 复制代码
import torch
import torchmetrics
import pytorch_lightning as pl

class MyModel(pl.LightningModule):
   def __init__(self, num_classes=10):
      super().__init__()
      # 同样需要指定任务参数,假设为10类分类问题
      self.accuracy = torchmetrics.Accuracy(task='multiclass', num_classes=num_classes)

   def training_step(self, batch, batch_idx):
      x, y = batch
      preds = self(x)               # 假设输出 logits,shape (batch, num_classes)
      loss = torch.nn.functional.cross_entropy(preds, y)
      preds_probs = preds.softmax(dim=-1)  # 指标通常期望概率或 logits
      self.accuracy(preds_probs, y)
      # on_epoch=True 会自动累积并记录整个 epoch 的指标
      self.log('train_acc', self.accuracy, on_step=False, on_epoch=True)
      return loss

   def on_train_epoch_end(self):
      # Lightning 会在 epoch 结束时自动调用 metric.reset(),无需手动操作
      pass

⚙️ 核心设计:两个主要接口与工作流程

TorchMetrics 提供了两种主要的使用方式,以适应不同场景。

  • 函数式接口 (Functional Interface)torchmetrics.functional 下的函数,无状态,直接输入张量进行计算,并立即返回结果。适合快速实验、单次评估。
  • 模块式接口 (Module Interface) :继承自 torch.nn.Module 的类,有状态。优势包括:
    • 跨 batch 累积统计量,最后通过 compute() 一次性算出全局结果;
    • 设备移动时自动同步内部状态;
    • 可直接作为模型的一部分,或配合 MetricCollection 一起使用。
      调用 metric(preds, target) 会内部执行 update() 并返回当前的累积结果(如果调用时不需要立即显示,也可以手动调用 metric.update(preds, target) 先累积)。
  • 典型工作流程 :
    1. 实例化与设备移动 : 创建指标对象(如 metric = torchmetrics.Accuracy(task='multiclass', num_classes=10).cuda()),与模型移动到同一设备。
    2. 迭代更新 : 在每个 batch 中调用 metric(preds, target)metric.update(preds, target) 累积状态。
    3. 结果计算 : epoch 结束时调用 metric.compute() 获取累计后的最终指标。
    4. 状态重置 : 调用 metric.reset() 清理内部状态,为下一轮评估做准备。

🗂️ 指标全景:分类纵览

TorchMetrics 提供了覆盖各种深度学习任务的超过100种指标。以下是按任务分类的部分常用指标:

任务类别 常用指标
分类 Accuracy, Precision, Recall, F1Score, FBetaScore, AUROC, AveragePrecision, ConfusionMatrix, MatthewsCorrCoef
回归 MeanSquaredError (MSE), MeanAbsoluteError (MAE), R2Score, MeanSquaredLogError (MSLE), PearsonCorrCoef, SpearmanCorrCoef
图像 PeakSignalNoiseRatio (PSNR), StructuralSimilarityIndexMeasure (SSIM), FrechetInceptionDistance (FID), LearnedPerceptualImagePatchSimilarity (LPIPS)
文本 BLEUScore, ROUGEScore, Perplexity, WER, BERTScore (需安装 bert-score 包)
音频 SignalNoiseRatio (SNR), SignalDistortionRatio (SDR), PerceptualEvaluationOfSpeechQuality (PESQ)
检索 RetrievalMAP, RetrievalMRR, RetrievalNormalizedDCG, RetrievalPrecision, RetrievalRecall
目标检测 MeanAveragePrecision (mAP)
**其他/包装器 ** MetricCollection, ClasswiseWrapper, MultioutputWrapper, Bootstrapper等实用工具

分类指标详解

  • Accuracy:计算所有样本中正确分类的比例。
  • PrecisionRecall :分别衡量模型预测正类的准确性(精确率)和模型找出所有正类的能力(召回率)。对于多分类,可通过 average 参数选择 macro, micro, weighted 等平均方式。
  • F1Score / FBetaScore :Precision和Recall的调和(或加权调和)平均值,FBetaScore 通过 beta 参数可以更偏重Precision或Recall。
  • AUROC / ROCROC计算曲线数据(假阳性率与真阳性率),AUROC计算其下方面积,衡量模型在不同阈值下的综合排序能力。输入通常是正类的概率或 logits(不是整数标签)。
  • ConfusionMatrix:提供模型在每个类别上表现的详细视图。
  • 输入格式提醒 :分类指标通常期望预测为 概率、logits 或类别索引 ,具体取决于任务设置。例如 multiclass 任务下,preds 可以是概率矩阵([N, C])或类别索引([N]);binary 任务下 preds 一般是概率向量([N])或类别索引。建议统一将概率传入,以避免歧义。

回归指标详解

  • MeanSquaredError (MSE):预测值与真实值之差平方的期望值,对大误差敏感。
  • MeanAbsoluteError (MAE):预测值与真实值之差绝对值的期望值,对异常值更鲁棒。
  • R2Score (R²) :衡量模型解释目标变量方差的程度,越接近1效果越好。输入要求 predstarget 形状一致。

🔧 自定义指标

你可以通过继承 torchmetrics.Metric 类来创建自定义指标。主要步骤包括:

  1. __init__ 方法中调用 self.add_state(...) 注册内部状态(如正确数、总数)。
  2. 实现 update(self, preds, target) 方法,从每个 batch 的数据中更新状态。
  3. 实现 compute(self) 方法,基于累积的状态计算并返回最终指标。

这是一个简单的自定义准确率示例:

python 复制代码
import torch
from torchmetrics import Metric

class MyAccuracy(Metric):
    def __init__(self):
        super().__init__()
        # dist_reduce_fx='sum' 表示在分布式评估时,该状态会在不同进程间求和
        self.add_state("correct", default=torch.tensor(0), dist_reduce_fx="sum")
        self.add_state("total", default=torch.tensor(0), dist_reduce_fx="sum")

    def update(self, preds: torch.Tensor, target: torch.Tensor):
        # 假设 preds 和 target 都是类别索引且 shape 为 (batch_size,)
        assert preds.shape == target.shape
        self.correct += torch.sum(preds == target)
        self.total += target.numel()

    def compute(self):
        return self.correct.float() / self.total

✨ 高级特性:MetricCollection

当需要同时计算多个指标时,可以使用 MetricCollection 将它们组合在一起。它能高效地处理参数的传递和结果的整合。

python 复制代码
import torch
from torchmetrics import MetricCollection, Accuracy, Precision, Recall, F1Score

# 将所有需要的指标放入一个 MetricCollection,并显式指定任务参数
# 这里假设是二分类任务,输入是概率或类别索引
metrics = MetricCollection({
    'acc': Accuracy(task='binary'),
    'precision': Precision(task='binary'),
    'recall': Recall(task='binary'),
    'f1': F1Score(task='binary')
})

# 模拟一个batch的二分类数据
preds = torch.rand(100)          # 正类的概率 [0,1]
target = torch.randint(0, 2, (100,))

# 一次性计算所有指标
result = metrics(preds, target)
print(result)  # 例如 {'acc': 0.52, 'precision': 0.48, 'recall': 0.51, 'f1': 0.49}

🔬 TorchMetrics vs. Scikit-learn Metrics

  • 设计哲学与框架依赖sklearn.metrics 设计简洁,输入通常是 NumPy 数组或 Python 列表;TorchMetrics 原生支持 PyTorch 张量,与训练流程无缝集成。
  • 计算性能 :原生 PyTorch 实现使其能直接在 GPU 上计算,避免 CPU-GPU 数据传输。有基准测试表明其计算速度比 sklearn 更快。
  • 分布式训练支持TorchMetrics 专为此设计,能跨多卡、多机自动同步和归并指标,而 sklearn.metrics 在分布式计算中需要手动实现,容易导致错误。
  • 数值精度:由于底层实现和浮点数精度,两者可能存在微小差异(通常在 1e-7 量级),但这对模型的相对比较和选择没有实质影响。
  • 使用体验 :在 PyTorch 中,TorchMetrics 免去了将张量转为 NumPy 的步骤,且支持累积计算,代码更简洁且不易出错。

💡 最佳实践与注意事项

  1. 正确管理状态 :遵循实例化 → 累积 → 计算 → 重置的工作流。在 PyTorch Lightning 中,如果你使用 self.log 并传入了一个 Metric 对象,Lightning 会在每个 epoch 结束时自动调用 metric.reset() ;但在自定义 PyTorch 训练循环中,务必在每个 epoch 开始前或结束后手动调用 metric.reset(),否则指标会跨 epoch 累积,导致结果错误。
  2. 生命周期管理 :指标对象旨在维护内部状态,不应在每个 batch 上重新初始化。通常在模型 __init__ 或外层循环前创建一次,反复使用。
  3. 正确指定任务参数 :使用分类指标时,必须根据实际情况明确指定 task 参数。例如:
    • 多分类(互斥类别)使用 task='multiclass' 并设置 num_classes
    • 二分类使用 task='binary'
    • 多标签分类使用 task='multilabel' 并设置 num_labels
    • 还需要按需设置 average(如 'macro', 'micro', 'weighted')等参数。参数缺失或错误会直接导致计算异常。
  4. 数值比较的容错 :进行精确比较时,建议设置一个误差范围(如 1e-6),而不是直接进行相等比较,以避免浮点误差带来的误判。
  5. 选择合适的接口:根据场景选择接口。简单评估可使用函数式接口;复杂的训练和验证循环中,建议使用模块化接口;使用PyTorch Lightning时,模块化接口可获得最佳体验。

💎 总结

TorchMetrics 是 PyTorch 生态中一个成熟、高效且可靠的模型评估工具。它通过标准化的接口、出色的设备兼容性和对分布式训练的完美支持,解决了 PyTorch 模型评估中的多个痛点,能帮助开发者编写更健壮、可复现的代码,专注于模型研发。

2、 torchmetrics 文本分类指标 - 通用

针对文本分类任务,选择指标的关键在于你的数据分布是否均衡 以及任务的容错率。简单来说,不能只看准确率(Accuracy),以下是你必须关注的核心指标组合:

  1. 基础"三剑客" (必选)

无论什么文本分类任务,这三个指标通常是一起看的,用来综合评估模型表现:

  • 精确率 (Precision)"查得准不准?"
    • 含义:模型预测为"正类"的样本中,有多少是真的?
    • 场景 :比如垃圾邮件检测。你非常不希望把正常邮件误判为垃圾邮件(误杀),这时候就要看 Precision。
  • 召回率 (Recall)"查得全不全?"
    • 含义:所有真实的"正类"样本中,有多少被模型找出来了?
    • 场景 :比如疾病诊断违规内容识别。你绝对不能漏掉任何一个真正的病人或违规贴,宁可错杀不可放过,这时候 Recall 最重要。
  • F1-Score"综合得分"
    • 含义:精确率和召回率的调和平均数。
    • 作用 :当 Precision 和 Recall 互相打架(一个高一个低)时,F1 能给你一个平衡的参考。这是最常用于汇报的指标之一。
  1. 多分类专用指标 (进阶)

如果文本分类不止两类(比如新闻分类:体育、财经、娱乐...),你需要关注聚合方式:

  • Macro-F1 :把所有类别的 F1 算出来取平均值。
    • 特点平等对待每个类别。如果你关心"娱乐"这种小类别的效果是否和"体育"大类别一样好,看这个。
  • Micro-F1 :先统计全局的 TP/FP/FN,再算 F1。
    • 特点受大类影响大。如果数据集里 90% 都是体育新闻,Micro-F1 基本就反映了模型在体育新闻上的表现。
  1. 特殊场景指标
  • 混淆矩阵 (Confusion Matrix)
    • 这不是一个单一数值,而是一张表。当你发现模型效果不好时,用它来抓虫。比如你会发现模型经常把"正面情绪"误判为"中性情绪",但在其他类别上很准。
  • AUC-ROC
    • 如果你的数据极度不平衡(比如 99% 是正常评论,1% 是恶意攻击),单纯看 Accuracy 会骗人(全猜正常也有 99% 准确率)。这时候 AUC 能更客观地反映模型的排序能力。

📌 总结建议

  • 如果是均衡数据(各类文章数量差不多) :重点关注 AccuracyMacro-F1
  • 如果不均衡(有的类很少) :忽略 Accuracy,死磕 Macro-F1Recall
  • 如果需要向老板汇报 :直接报 F1-ScoreTop-1 Accuracy

3、torchmetrics 文本分类指标 - 多分类

针对你的任务------单样本属于10个互斥标签中的一个 (这在机器学习中称为多分类任务),评估指标的选择非常有讲究。

简单来说,你不能只看准确率(Accuracy),因为它容易掩盖模型在"少数类"上的无能。以下是为你整理的核心指标组合:

  1. 必看的综合指标:Macro-F1 Score

这是多分类任务中最"硬核"的指标。

  • 为什么选它?
    • 如果你有10个标签,其中"标签A"有900条数据,"标签B"只有10条。如果模型把所有样本都预测为"标签A",它的准确率(Accuracy)高达90%,看起来很美,但实际上它完全学不会识别"标签B"。
    • Macro-F1 会先计算每个标签的 F1 分数,然后取平均值。这意味着小类别的表现和大类别一样重要。如果 Macro-F1 很高,说明模型对这10个类别都有不错的识别能力,没有"偏科"。
  1. 基础参考指标:Accuracy (Top-1 Accuracy)
  • 含义: 100篇文章里,有多少篇是完全猜对的。
  • 适用场景: 当你的10个标签的数据量比较均衡(比如每个标签都有1000条左右)时,这个指标最直观,老板和业务方最容易听懂。
  1. 诊断工具:混淆矩阵

这不仅仅是一个数字,而是一张 10x10 的热力图。

  • 作用: 帮你发现模型到底"傻"在哪里。
  • 怎么看?
    • 看对角线:越亮越好(代表预测正确)。
    • 看非对角线:如果你发现"体育"类的文章经常被预测成"汽车",说明这两个类别的特征太像了,模型分不清楚,你需要针对性地增加这两类的训练数据或优化特征。
  1. 进阶指标(视情况而定)
  • Weighted-F1:如果你觉得大类别(样本多的类)确实应该占主导地位,可以使用加权平均 F1,它会根据每个类别的样本数量进行加权。
  • Top-k Accuracy:如果你的应用场景允许推荐多个结果(比如给用户推荐3个可能的标签),可以看 Top-3 Accuracy,即正确答案只要在前3个预测里就算对。

📌 总结建议

在你的实验报告或监控面板中,建议按以下优先级展示:

  1. Macro-F1(核心指标,反映真实水平)
  2. Accuracy(直观指标,反映整体效果)
  3. 混淆矩阵(用于分析具体哪两个类别容易搞混)

4、准确率、精确率、召回率、F1分数 及其 类

  1. 准确率(Accuracy)

直白解释:

所有预测中,猜对的比例(不管是正类还是负类,猜对了就算)。

公式:

准确率 = (猜对的个数) / (总样本数)

对应 torchmetrics 类:

torchmetrics.classification.Accuracy


  1. 精确率(Precision)

直白解释:

模型说"这是正类"的那些样本里,到底有多少真的是正类。

换句话说:模型有没有乱报正类(冤枉好人)。

公式:

精确率 = (正确报出的正类数) / (所有报为正类的数量)

对应 torchmetrics 类:

torchmetrics.classification.Precision


  1. 召回率(Recall)

直白解释:

在所有真正的正类样本中,模型成功找出了多少。

换句话说:模型有没有漏掉正类(放过坏人)。

公式:

召回率 = (正确报出的正类数) / (所有真正的正类数量)

对应 torchmetrics 类:

torchmetrics.classification.Recall


  1. F1 分数

直白解释:

精确率和召回率的"综合得分"。

当你既不想乱报(高精确率),又不想漏报(高召回率),就用 F1 来平衡两者。

公式:

F1 = 2 × (精确率 × 召回率) / (精确率 + 召回率)

对应 torchmetrics 类:

torchmetrics.classification.F1Score


一句话总结(记忆用)

  • 准确率 :总的猜对比例 → Accuracy
  • 精确率 :报为正类的里头,有多少是对的 → Precision
  • 召回率 :真正的正类里头,找到了多少 → Recall
  • F1 分数 :精确率和召回率的"折中分" → F1Score

5、torchmetrics - Accuracy 详解(准确率)

📘 TorchMetrics Accuracy 深度拆解

什么是 Accuracy?

torchmetrics (v1.0+) 中,Accuracy 是一个通用的入口类。它通过 task 参数来自动适配二分类、多分类或多标签模式。这种设计比旧版本的独立类(如 Accuracy(num_classes=10))更加统一和规范。

注意 :你也可以直接使用 from torchmetrics.classification import MulticlassAccuracy,效果是一样的,但通用版 Accuracy 写起来更灵活。

两种使用模式

在使用之前,你需要知道它有两种形态:

  • 模块式 (Module Style)推荐用于训练/验证循环
    • 特点:有状态(Stateful)。可以累积多个 Batch 的数据,最后算总账(Epoch 级别)。
    • 用法 :实例化对象 -> 循环调用 update() -> 结束调用 compute()
  • 函数式 (Functional Style)推荐用于即时计算或无状态场景
    • 特点:无状态(Stateless)。给什么数据算什么结果,不记录历史。
    • 用法 :直接调用 torchmetrics.functional.accuracy(...)

完整函数签名与参数详解

这是 torchmetrics.Accuracy 类的初始化签名。请注意,虽然它是同一个类,但很多参数的有效性取决于 task 的选择。

python 复制代码
from torchmetrics import Accuracy

metric = Accuracy(
    # --- 必填参数 ---
    task: Literal["binary", "multiclass", "multilabel"], # [必填] 任务类型
    
    # --- 核心可选参数 ---
    threshold: float = 0.5,                              # [可选] 阈值,默认0.5
    num_classes: Optional[int] = None,                   # [可选] 类别数 (multiclass/multilabel必填)
    num_labels: Optional[int] = None,                    # [可选] 标签数 (multilabel专用)
    average: Optional[Literal["micro", "macro", "weighted", "none"]] = "micro", # [可选] 平均方式
    multidim_average: Literal["global", "samplewise"] = "global", # [可选] 多维平均方式
    top_k: Optional[int] = 1,                            # [可选] Top-k,默认1
    
    # --- 高级可选参数 ---
    ignore_index: Optional[int] = None,                  # [可选] 忽略的标签索引
    validate_args: bool = True                           # [可选] 是否检查参数合法性
)

🔍 参数深度解析

参数名 默认值 详解与注意事项
task 最关键的参数 。 • "binary": 二分类。 • "multiclass": 多分类(互斥,如文本分类)。 • "multilabel": 多标签(非互斥)。
num_classes None Multiclass/Multilabel 任务必填 。 • 告诉库一共有多少个类别,用于内部张量分配。
average "micro" Micro : 全局统计 TP/FP/FN 后计算。受大样本类别主导。 • Macro : 先算每个类的指标再平均。平等对待每个类别 。 • Weighted : 按样本量加权平均。 • None(可能是小写 none): 返回每个类别的指标数组,不聚合。(就能看到每个类别的指标分别是多少)
top_k 1 • 仅用于 Multiclass 。 • 默认为 1,即 Top-1 Accuracy。 • 若设为 3,只要正确标签在预测概率最高的前3个里,就算对。
ignore_index None • 用于忽略特定的目标值(例如 Padding 的索引 -100),这些位置不参与准确率计算。

输入与输出规范

📥 torchmetrics 输入 (preds, target) 核心规范

无论是模块式 (acc_metric.update(...)) 还是函数式 (accuracy(...)),输入的数据类型首选且最推荐 torch.Tensor(张量)

(注:虽然传入 Numpy 数组或 Python 列表通常不会报错,库会在内部自动转为张量,但为了保证 GPU 设备一致性和计算效率,强烈建议直接传入张量)

具体形状、类型和任务对应关系如下:

  1. preds (模型预测值)
  • Multiclass (多分类)
    • 情况 A(最常见) :传入模型输出的原始分数(Logits)或概率(Probabilities)。
      • 类型torch.Tensor(通常是 FloatTensor 浮点型)
      • 形状(N, C) ------ N是样本数,C是类别总数。
      • 说明 :库内部会自动对 C 这个维度做 argmax 找出概率最大的类别。
    • 情况 B :传入已经预测好的类别索引。
      • 类型torch.Tensor(必须是 LongTensor 整型)
      • 形状(N,) ------ 一维张量。
  • Binary (二分类)
    • 类型torch.TensorFloatTensorLongTensor
    • 形状(N,)(N, 1)
    • 说明 :如果是浮点数(0~1),库会根据 threshold(默认0.5)将其转为 0 或 1。
  • Multilabel (多标签分类)
    • 类型torch.TensorFloatTensorLongTensor
    • 形状(N, C) ------ N是样本数,C是标签总数。
    • 说明 :每个样本可以同时属于多个标签(如 [1, 0, 1] 表示属于第0类和第2类)。
  • Semantic Segmentation (语义分割 - 补充)
    • Multiclass
      • 类型torch.TensorFloatTensor
      • 形状(N, C, H, W) ------ N是样本数,C是类别数,H/W是图像高宽。
    • Binary
      • 类型torch.TensorFloatTensorLongTensor
      • 形状(N, H, W)
  1. target (真实标签)
  • Multiclass (多分类)
    • 类型torch.Tensor必须是 LongTensor 整型
    • 形状(N,) ------ 一维张量。
    • 内容 :值为类别的索引,范围在 0C-1 之间。
  • Binary (二分类)
    • 类型torch.TensorLongTensorFloatTensor
    • 形状(N,)(N, 1)
    • 内容 :值为 01
  • Multilabel (多标签分类)
    • 类型torch.TensorLongTensorFloatTensor
    • 形状(N, C) ------ 与多分类的 preds 形状一致。
    • 内容 :值为 01(One-hot 形式,1 表示该样本拥有此标签)。
  • Semantic Segmentation (语义分割 - 补充)
    • 类型torch.Tensor必须是 LongTensor 整型
    • 形状(N, H, W)
    • 内容:每个像素点对应的类别索引(0 到 C-1)。

输出:

输出的是一个张量

💡 核心总结

  • 数据类型 :全程用 PyTorch 张量 (torch.Tensor)
  • 形状铁律predstarget第一个维度(Batch Size / N)必须完全相同
  • 多分类特例preds(N, C) 的浮点张量,而 target(N,) 的整型张量。
  • 分割任务特例preds 多一个类别维度 (N, C, H, W),而 target 是直接的空间类别图 (N, H, W)

常用操作代码示例

场景一:模块式 (标准做法)

适用于训练循环,能够跨 Batch 累积计算。

在 TorchMetrics 库中,torchmetrics.Metric所有内置指标(如 Accuracy, Precision, F1Score 等)以及用户自定义指标的抽象基类(Abstract Base Class)

python 复制代码
import torch
from torchmetrics import Accuracy

# 1. 实例化 (Multiclass 任务)
acc_metric = Accuracy(task="multiclass", num_classes=10, average='macro')
print(type(acc_metric))    # MulticlassAccuracy

# 2. 模拟两个 Batch 的数据
preds_batch1 = torch.randn(20, 10)  # 20个样本,10个类别的概率
target_batch1 = torch.randint(0, 10, (20,))

preds_batch2 = torch.randn(20, 10)
target_batch2 = torch.randint(0, 10, (20,))

# 3. 更新状态 (Update)
# 此时不会计算最终结果,只是把中间变量累加起来
acc_metric.update(preds_batch1, target_batch1)
acc_metric.update(preds_batch2, target_batch2)

# 4. 计算最终结果 (Compute)
# 此时才进行除法运算,得出这40个样本的平均准确率
final_acc = acc_metric.compute()
print(f"Total Accuracy: {final_acc}")

# 5. 重置 (Reset)
# 下一个 Epoch 开始前必须调用
acc_metric.reset()

场景二:训练中的 Forward 用法

在训练循环中,我们通常希望每跑一个 batch 就打印一次当前的准确率,同时又要累积状态。这时可以直接调用对象本身(相当于调用了 forward)。

python 复制代码
# 假设在 training_step 中
outputs = model(data)
loss = criterion(outputs, target)

# 这一步既执行了 update,又返回了当前 batch 的 compute 结果
batch_acc = acc_metric(outputs, target) 

self.log('train_loss', loss)
self.log('train_acc', batch_acc) # 用于实时查看训练进度

场景三:函数式 (快速计算)

适用于只需要计算当前这一批数据的准确率,不需要累积。

python 复制代码
import torch
import torchmetrics

preds = torch.randn(10, 5).softmax(dim=-1) # 10个样本,5个类别
target = torch.randint(0, 5, (10,))

# 直接调用 functional 接口
# 注意:这里需要指定所有必要参数,因为它没有记忆
acc = torchmetrics.functional.accuracy(
    preds, 
    target, 
    task="multiclass", 
    num_classes=5
)

print(f"Batch Accuracy: {acc}")

场景四:Top-K 准确率

当你想知道模型"猜对前三名的概率"时:

python 复制代码
# 初始化时指定 top_k=3
top3_acc = Accuracy(task="multiclass", num_classes=10, top_k=3)

# 输入必须是概率分布或Logits (N, C),不能是索引
preds = torch.randn(32, 10) 
target = torch.randint(0, 10, (32,))

res = top3_acc(preds, target) # 直接调用 forward 也可以

💡 总结

对于文本分类任务,最常用的配置就是:

Accuracy(task="multiclass", num_classes=10, average='macro')

记住 "模块式 + Update/Compute" 的模式,以及在训练循环中使用 metric(preds, target) 的技巧,这是在 PyTorch Lightning 或标准训练循环中最稳健的用法。

6、torchmetrics 模块式 metric - 常用 属性、方法

🛠️ TorchMetrics 模块式指标对象:属性与方法全解析

模块式创建的指标对象继承自 torchmetrics.Metric,而 Metric 本身又继承自 torch.nn.Module。这意味着它既是一个有状态的评估工具 ,也是一个标准的 PyTorch 模块 。它的核心设计哲学是 "累积-计算-重置"三阶段分离,专为跨 batch 的大规模评估和分布式训练而优化。


🧱 一、基础设置与属性(入门必读)

在调用任何方法之前,务必将指标对象的"物理位置"和内部状态搞清楚。这是新手最容易踩坑的地方。

属性 / 方法 类型 说明
.to(device) / .cuda() 方法 【极其重要】 将指标及其所有内部状态张量移动到指定设备(GPU/CPU)。指标不会自动跟随模型或数据移动,必须在初始化后显式调用。
.device torch.device 查看指标当前所在的设备,用于调试设备不匹配问题。
metric_state Dict[str, Tensor] 返回当前所有内部状态(通过 add_state 注册的变量)的字典。键为状态名,值为当前累积的张量。
.correct / .total Tensor 直接通过属性名访问具体的内部状态变量,方便手动检查和调试。

关于 dtypeMetric 类本身没有统一的 dtype 属性。如需查看状态张量的数据类型,可通过 metric.metric_state['correct'].dtype 等方式查看。

示例

python 复制代码
import torch
import torchmetrics

# 初始化并立即移动到 GPU
metric = torchmetrics.Accuracy(task='multiclass', num_classes=10).to('cuda')

print(metric.device)            # cuda:0
print(metric.metric_state)      # {'correct': tensor(0, device='cuda:0'), 'total': tensor(0, device='cuda:0')}
print(metric.correct)           # tensor(0, device='cuda:0')

⚙️ 二、核心生命周期方法(日常训练/验证必用)

这是你写训练循环时每天都要接触的四个核心方法。它们遵循 "累积 → 计算 → 重置 → 累积" 的循环。

其中输入的 preds、target 都必须为张量

方法 签名 功能 返回值
update update(preds, target) 累积状态。接收当前 batch 的数据,计算中间统计量(如正确数、总数),并累加到内部变量中。只做累加,不做除法。 None
compute compute() 计算最终结果。基于所有累积的状态,一次性计算出最终的指标值(可以是标量、向量或字典)。不重置状态,可多次调用得到相同结果。 TensorDict
reset reset() 重置状态。将所有内部累积变量恢复到初始值(通常为 0)。 None
forward forward(preds, target) 更新 + 计算 。等价于先执行 self.update(preds, target),然后返回 self.compute()。可通过 metric(preds, target) 直接调用。 TensorDict

调用方式的选择逻辑

场景 推荐方法 原因
训练日志(想立刻看到当前 batch 的效果) metric(preds, target)(即 forward 一次调用完成累积和显示,方便记录到 TensorBoard。
验证循环内(只累积不显示,追求速度) metric.update(preds, target) 只做加法,不做除法和复杂运算,速度最快。
验证循环结束后(需要整个数据集的最终得分) metric.compute() 一次性基于所有累积数据计算全局指标。
Epoch 开始前/结束后(新周期必须清空旧数据) metric.reset() 如果忘记调用,指标会跨 epoch 累积,结果完全错误。

完整典型循环

python 复制代码
metric = torchmetrics.Accuracy(task='multiclass', num_classes=10).to('cuda')

# -- 验证阶段 --
for batch in val_dataloader:
    preds, target = batch
    metric.update(preds, target)         # 只累积,不返回

final_score = metric.compute()           # 获取整个验证集的准确率
print(f"Validation Accuracy: {final_score:.3f}")
metric.reset()                           # 清空状态,准备下一轮

🔧 三、自定义指标专用方法(开发者必看)

当你需要创建自己的指标类时,以下方法是核心。

方法 说明
add_state(name, default, dist_reduce_fx, persistent=True) __init__ 中调用,注册一个持久化状态变量。default 指定初始值,dist_reduce_fx 指定分布式聚合方式(如 "sum""mean")。
set_dtype(obj) 将所有状态的 dtype 统一转换为特定类型。一般在 __init__ 结尾调用。

dist_reduce_fx 常用取值

取值 含义
"sum" 多卡时将所有设备的该状态值求和 (适用于 correcttotal 等计数变量)。
"mean" 多卡时将所有设备的该状态值取平均(适用于某些比率型中间值)。
"cat" 将所有设备的张量拼接起来。
None 不做任何分布式归约,仅在单卡上维护状态。

自定义指标示例

python 复制代码
from torchmetrics import Metric
import torch

class MyAccuracy(Metric):
    def __init__(self):
        super().__init__()
        self.add_state("correct", default=torch.tensor(0), dist_reduce_fx="sum")
        self.add_state("total", default=torch.tensor(0), dist_reduce_fx="sum")

    def update(self, preds, target):
        self.correct += torch.sum(preds == target)
        self.total += target.numel()

    def compute(self):
        return self.correct.float() / self.total

📦 四、模块化管理属性(继承自 nn.Module

这些属性/方法继承自 torch.nn.Module,让指标对象可以像模型一样被管理。

方法 / 属性 说明
named_children() 查看指标包含的子模块(如 MetricCollection 中的子指标)。
parameters() 一般的 Metric 内部没有可学习参数,但某些特殊指标(如 FID)可能包含可训练的统计量。
train(mode) / eval() 切换训练/评估模式。如果自定义指标中嵌入了 BatchNormDropout 等层,模式切换会影响其行为。
to(device) 移动指标到指定设备,所有内部状态张量会自动跟随。
state_dict() 保存指标内部状态,可用于 checkpoint 恢复。
load_state_dict() 加载保存的内部状态,保证评估的连续性。
persistent(mode=True/False) 控制指标状态是否会被 model.state_dict() 保存。设为 False 时,保存模型权重时该指标的累积数据会被忽略(通常这正是我们想要的,因为重启训练时指标本就该清零)。
.clone() 创建指标的深拷贝,包括当前的内部状态。

📊 五、可视化与调试

方法 / 属性 说明
plot(val=None, ...) 部分指标(如 ConfusionMatrixROC 等)提供内置绘图方法,可直接可视化结果。

🧩 六、与 MetricCollection 协同

当多个指标被包装在 MetricCollection 中时,以上核心方法(forwardupdatecomputereset)仍然适用,但行为略有变化:

  • metric_collection(preds, target):返回一个字典,包含所有子指标的即时累积值。
  • metric_collection.compute():返回一个字典,包含所有子指标的最终累积值。
  • metric_collection.reset():同时清空所有子指标的状态。
  • 每个子指标仍可通过键名单独访问:metric_collection['acc'].correct
python 复制代码
from torchmetrics import MetricCollection, Accuracy, F1Score

metrics = MetricCollection({
    'acc': Accuracy(task='multiclass', num_classes=10),
    'f1': F1Score(task='multiclass', num_classes=10)
}).to('cuda')

result = metrics(preds, target)
print(result)  # {'acc': tensor(0.52, device='cuda:0'), 'f1': tensor(0.48, device='cuda:0')}

💡 七、完整生命周期总结表

阶段 推荐操作 目的
初始化并确定设备 metric = Metric(...).to(device) 必须显式指定设备,防止张量位置不匹配
训练单步(日志) val = metric(preds, target) 累积并获取当前 batch 的值,用于 TensorBoard 打印
验证循环内(最优性能) metric.update(preds, target) 默默累积,不做除法,速度最快
验证循环结束 final = metric.compute() 基于全部累积数据计算最终得分
Epoch 结束/新周期开始 metric.reset() 清空内存,防止数据跨 epoch 污染
调试/检查状态 metric.metric_statemetric.correct 查看当前累积了多少正确样本、总样本等
保存 checkpoint torch.save(metric.state_dict(), ...) 持久化当前评估进度
恢复 checkpoint metric.load_state_dict(torch.load(...)) 恢复之前的评估状态

以上就是 torchmetrics 模块式指标对象的完整属性与方法指南,覆盖了从入门、日常使用到自定义开发的全场景。这份知识能帮你避免绝大多数设备不匹配、状态污染等常见问题。

相关推荐
湘美书院--湘美谈教育7 小时前
湘美谈教育湘美书院成功学系列:标准即是文明,AI时代的走向
大数据·人工智能·深度学习·机器学习·生活
AI科技星9 小时前
光速螺旋时空曲率挠率拓扑统一场论——四大力全域闭环求导、精算验证与第一性原理完备证明
线性代数·算法·决策树·机器学习·常温超导·ai科技星
迷途呀9 小时前
conda使用指南
python·深度学习·机器学习·pycharm·conda
Risk Actuary11 小时前
手动示例解释机器学习中 GBDT 算法原理
人工智能·算法·机器学习
血色橄榄枝18 小时前
基于用户注册信息的关键词检测挑战赛「Datawhale AI 夏令营」
人工智能·算法·机器学习
QN1幻化引擎1 天前
Dalin L — 我造了一门支持中文编程的语言,完整移植到 Rust 了
人工智能·算法·机器学习
Axis tech1 天前
Manus基于手关节角度和指尖数据的Revo 3灵巧手遥操作
科技·机器学习
KaMeidebaby1 天前
卡梅德生物技术快报|如何制备单克隆抗体:小众禽类靶点单抗制备实操流程:双载体抗原交叉筛选完整工艺记录
人工智能·python·深度学习·算法·机器学习
z小猫不吃鱼1 天前
模型剪枝经典论文精读:DepGraph: Towards Any Structural Pruning
算法·机器学习·剪枝