登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

Evaluate 怎样加载指标并处理批量预测

来源:17golang原创

时间:2026-11-14 21:02:19 261浏览 收藏

我第一次把模型预测接入 Evaluate 时,真正卡住的不是指标公式,而是“这一批结果到底什么时候交给指标对象”。如果数据很小,可以直接调用 compute();如果预测来自循环中的多个 batch,更稳妥的做法是先用 evaluate.load() 加载指标,再逐批调用 add_batch(),最后统一 compute()。

官方地址:https://huggingface.co/docs/evaluate/

把 Evaluate 想成一个带输入契约的指标容器:先确认它要接收哪些字段,再让每个预测批次和对应标签一起进入,所有批次完成后只计算一次。

先确认指标需要什么输入

Evaluate 的指标不是一个只接收任意两个列表的黑盒。加载后先看 features,可以确认字段名以及单个元素的形状。以分类准确率为例,最常见的字段就是 predictions 和 references。

evaluate.load 加载 accuracy 后由 features 描述 predictions 和 references 输入字段的结构说明图
图1:结构说明图,展示指标加载后如何查看 features 并准备输入;不是运行截图。
import evaluate

# 先加载指标,再查看它声明的输入字段;字段名要和后续调用保持一致。
accuracy = evaluate.load("accuracy")
print(accuracy.features)

# 这里的 features 通常会说明 predictions 和 references 的数据类型。

这一步很适合排除“参数名写错”的问题。模型输出可能叫 logits、labels 或别的名字,但传给指标时仍要转换成该指标认识的 predictions 与 references。Evaluate 接受列表、NumPy 数组和部分张量格式,但输入语义不会因此改变。

用 evaluate.load 加载指标对象

最小加载方式是 evaluate.load("accuracy")。返回的对象同时提供一次性计算与增量提交接口。若名称存在歧义,还可以显式传入 module_type,但普通分类指标通常不需要额外参数。

import evaluate

# accuracy 是指标标识;返回对象后面会负责接收预测值和参考值。
metric = evaluate.load("accuracy")

# 小数据可以直接把完整数组交给 compute;关键字参数避免顺序传错。
result = metric.compute(
    predictions=[1, 0, 0, 1],
    references=[1, 1, 0, 1],
)
print(result)

结果是一个字典,而不是裸浮点数。官方示例展示的形式是 {'accuracy': 0.5},真实值取决于你的预测和标签。保留字典结构有一个好处:后续换成返回多个字段的指标时,调用方不必重新设计结果处理。

预测按批次到达时,用 add_batch 累积

实际推理经常是“拿一批输入、跑一批模型、得到一批预测”。这时没有必要为了调用一次 compute(),再把全部预测和标签复制到一个超大的列表里。每次得到一个 batch,就同时提交预测值和参考值。

import evaluate

metric = evaluate.load("accuracy")

# 每个元组代表一个已经完成推理的批次;两边必须一一对应。
batch_results = [
    ([0, 1], [0, 0]),
    ([1, 0], [1, 0]),
]

for references, predictions in batch_results:
    # 只提交当前批次,Evaluate 会把数据放入指标对象的累计输入中。
    metric.add_batch(
        references=references,
        predictions=predictions,
    )

# 所有批次都提交后再计算,避免漏掉最后一个 batch。
result = metric.compute()
print(result)
batch A 和 batch B 通过 add_batch 进入 metric stack 最后由 compute 返回结果字典的结构说明图
图2:结构说明图,展示多个预测批次进入指标对象并由 compute 收口;不是运行截图。

这里最容易出现的错误是把参数方向写反,或者让一个 batch 的预测数量与参考值数量不一致。工程上可以在提交前做轻量的长度检查;检查失败时尽早报错,比等到最终指标阶段才发现样本错位更容易定位。

def add_checked_batch(metric, predictions, references):
    # 先检查当前批次的样本数,防止预测与标签错位后继续累计。
    if len(predictions) != len(references):
        raise ValueError("predictions 和 references 的长度必须一致")

    # 通过关键字传参,让字段含义清楚,也便于后续替换输入容器。
    metric.add_batch(
        predictions=predictions,
        references=references,
    )

compute 要放在所有批次之后

compute() 有两种常见用法:直接接收完整的 predictions 和 references,或者不带数据、读取前面通过 add()/add_batch() 累积的内容。不要在每个 batch 后都调用一次并把中间分数当成全量最终分数,除非你的业务明确需要观察阶段性结果。

如果循环没有产生任何 batch,直接计算可能无法表达“本轮没有样本”的业务含义;可以在业务层记录样本数,并在没有数据时返回自己的空结果。Evaluate 指标还可能要求额外字段,所以遇到缺少参数时,应回到 metric.features 和对应指标说明,而不是盲目添加同名参数。

一次性计算和批量计算怎么选

场景推荐写法关注点
数据已经在内存中且规模小metric.compute(predictions=..., references=...)调用短,适合脚本和小样本示例
预测在循环中分批产生多次 add_batch(),最后一次 compute()每批字段对应,最后不要漏算
换了一个指标或模块先查看 features,再传对应字段不要假设所有模块都只需要两列

我会保留的排查顺序

出现结果为空、参数错误或分数异常时,我会按这个顺序看:第一,确认 evaluate.load() 加载的是预期模块;第二,打印 features 对照字段名;第三,检查每个 batch 的预测和参考值长度;第四,确认所有 batch 都调用了 add_batch();第五,最后才检查指标本身的计算语义。这个顺序的好处是先排输入契约,再排数据流,通常比从公式开始猜更快。

相关问题

可以每个 batch 都调用 compute 吗?

可以,但每次得到的通常只是当前累计状态下的结果,不等于把所有 batch 都处理完后的最终结果。批量推理场景一般在循环结束后统一调用。

add_batch 的 predictions 和 references 必须同长度吗?

应当保持同一批次逐样本对应。长度不一致时不要继续累计,先定位数据切分或模型输出的对齐问题。

什么时候直接传给 compute 更简单?

当完整预测和标签已经可靠地放在内存中,而且数据量不大时,直接传给 compute() 最清楚;一旦预测是流式或分批产生,再改用 add_batch()。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>