Evaluate 文档
快速入门
并获得增强的文档体验
开始使用
快速入门
🤗 Evaluate 提供了广泛的评估工具。它涵盖了文本、计算机视觉、音频等多种模态,以及评估模型或数据集的工具。这些工具分为三类。
评估类型
典型的机器学习流程中有不同的方面可以进行评估,对于每个方面,🤗 Evaluate 都提供了一个工具:
- 指标(Metric):指标用于评估模型的性能,通常涉及模型的预测以及一些真实标签。你可以在 evaluate-metric 找到所有集成的指标。
- 比较(Comparison):比较用于对比两个模型。例如,可以通过将它们的预测与真实标签进行比较并计算它们的一致性来完成。你可以在 evaluate-comparison 找到所有集成的比较方法。
- 测量(Measurement):数据集与在其上训练的模型同等重要。通过测量,可以研究数据集的属性。你可以在 evaluate-measurement 找到所有集成的测量方法。
这些评估模块中的每一个都以 Space 的形式存在于 Hugging Face Hub 上。它们带有交互式小部件和文档卡片,记录了其用途和局限性。例如 accuracy

每个指标、比较和测量都是一个独立的 Python 模块,但使用它们中的任何一个,都有一个统一的入口:evaluate.load()!
加载
任何指标、比较或测量都通过 `evaluate.load` 函数加载。
>>> import evaluate
>>> accuracy = evaluate.load("accuracy")
如果你想确保加载了正确的评估类型(特别是在有名称冲突的情况下),可以显式地传递类型。
>>> word_length = evaluate.load("word_length", module_type="measurement")
社区模块
除了 🤗 Evaluate 中实现的模块外,你还可以通过指定指标实现仓库的 ID 来加载任何社区模块。
>>> element_count = evaluate.load("lvwerra/element_count", module_type="measurement")
有关上传自定义指标的信息,请参阅创建和共享指南。
列出可用模块
使用 list_evaluation_modules(),你可以查看 Hub 上有哪些可用的模块。你还可以筛选特定模块,并根据需要跳过社区指标。你还可以看到其他信息,例如点赞数。
>>> evaluate.list_evaluation_modules(
... module_type="comparison",
... include_community=False,
... with_details=True)
[{'name': 'mcnemar', 'type': 'comparison', 'community': False, 'likes': 1},
{'name': 'exact_match', 'type': 'comparison', 'community': False, 'likes': 0}]
模块属性
所有评估模块都带有一系列有用的属性,这些属性有助于使用存储在 EvaluationModuleInfo 对象中的模块。
属性 | 描述 |
---|---|
description | 评估模块的简短描述。 |
引用 | 可用的 BibTex 引用字符串。 |
features | 定义输入格式的 `Features` 对象。 |
inputs_description | 这相当于模块的文档字符串(docstring)。 |
homepage | 模块的主页。 |
许可证 | 模块的许可证。 |
codebase_urls | 指向模块背后代码的链接。 |
reference_urls | 其他参考 URL。 |
让我们看几个例子。首先,我们看看准确率(accuracy)指标的 `description` 属性。
>>> accuracy = evaluate.load("accuracy")
>>> accuracy.description
Accuracy is the proportion of correct predictions among the total number of cases processed. It can be computed with:
Accuracy = (TP + TN) / (TP + TN + FP + FN)
Where:
TP: True positive
TN: True negative
FP: False positive
FN: False negative
你可以看到它描述了该指标在理论上是如何工作的。如果你在你的工作中使用这个指标,特别是在学术出版物中,你需要正确地引用它。为此,你可以查看 `citation` 属性。
>>> accuracy.citation
@article{scikit-learn,
title={Scikit-learn: Machine Learning in {P}ython},
author={Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V.
and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P.
and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and
Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.},
journal={Journal of Machine Learning Research},
volume={12},
pages={2825--2830},
year={2011}
}
在我们能将指标或其他评估模块应用于一个用例之前,我们需要知道该指标的输入格式是什么。
>>> accuracy.features
{
'predictions': Value(dtype='int32', id=None),
'references': Value(dtype='int32', id=None)
}
请注意,features 总是描述单个输入元素的类型。通常我们会添加元素列表,所以你总可以想象在 `features` 中的类型周围有一个列表。Evaluate 接受各种输入格式(Python 列表、NumPy 数组、PyTorch 张量等),并将其转换为适合存储和计算的格式。
计算
现在我们知道评估模块是如何工作的以及应该输入什么了,我们想实际使用它!当涉及到计算实际分数时,主要有两种方法:
- 一次性计算
- 增量计算
在增量方法中,必要的输入通过 EvaluationModule.add() 或 EvaluationModule.add_batch() 添加到模块中,最终的分数通过 EvaluationModule.compute() 计算。或者,可以将所有输入一次性传递给 `compute()`。让我们看看这两种方法。
如何计算
计算评估模块分数的最简单方法是直接用必要的输入调用 `compute()`。只需将 `features` 中看到的输入作为参数传递给 `compute()` 方法即可。
>>> accuracy.compute(references=[0,1,0,1], predictions=[1,0,0,1])
{'accuracy': 0.5}
评估模块以字典形式返回结果。然而,在某些情况下,你是迭代地或以分布式方式构建预测的,这时 `add()` 或 `add_batch()` 就很有用。
计算单个指标或一批指标
在许多评估流程中,你是迭代地构建预测的,例如在 for 循环中。在这种情况下,你可以将预测存储在一个列表中,最后将它们传递给 `compute()`。使用 `add()` 和 `add_batch()` 可以避免单独存储预测的步骤。如果你一次只创建一个预测,可以使用 `add()`。
>>> for ref, pred in zip([0,1,0,1], [1,0,0,1]):
>>> accuracy.add(references=ref, predictions=pred)
>>> accuracy.compute()
{'accuracy': 0.5}
一旦收集了所有预测,你就可以调用 `compute()` 来根据所有存储的值计算分数。当以批次获取预测和参考时,你可以使用 `add_batch()`,它会添加一个元素列表以供后续处理。其余部分与 `add()` 类似。
>>> for refs, preds in zip([[0,1],[0,1]], [[1,0],[0,1]]):
>>> accuracy.add_batch(references=refs, predictions=preds)
>>> accuracy.compute()
{'accuracy': 0.5}
当需要分批从模型中获取预测时,这尤其有用。
>>> for model_inputs, gold_standards in evaluation_dataset:
>>> predictions = model(model_inputs)
>>> metric.add_batch(references=gold_standards, predictions=predictions)
>>> metric.compute()
分布式评估
在分布式环境中计算指标可能很棘手。指标评估在不同的 Python 进程或节点上,对数据集的不同子集执行。通常,当一个指标分数是可加的(`f(AuB) = f(A) + f(B)`)时,你可以使用分布式 reduce 操作来收集数据集每个子集的分数。但是当一个指标是不可加的(`f(AuB) ≠ f(A) + f(B)`)时,事情就没那么简单了。例如,你不能将每个数据子集的 F1 分数相加作为你的**最终指标**。
克服这个问题的一个常用方法是退回到单进程评估。指标在单个 GPU 上进行评估,这变得效率低下。
🤗 Evaluate 通过只在第一个节点上计算最终指标来解决这个问题。预测和参考值在每个节点上分别计算并提供给指标。这些数据暂时存储在一个 Apache Arrow 表中,避免了占用 GPU 或 CPU 内存。当你准备好 `compute()` 最终指标时,第一个节点能够访问存储在所有其他节点上的预测和参考值。一旦收集了所有的预测和参考值,`compute()` 将执行最终的指标评估。
这个解决方案允许 🤗 Evaluate 执行分布式预测,这对于分布式环境下的评估速度很重要。同时,你也可以使用复杂的非可加性指标,而不会浪费宝贵的 GPU 或 CPU 内存。
组合多个评估
通常,人们不仅希望评估单个指标,还希望评估一系列不同的指标,以捕捉模型的不同方面。例如,对于分类任务,除了准确率之外,计算 F1 分数、召回率和精确率通常是个好主意,以便更全面地了解模型性能。当然,你可以加载一堆指标并按顺序调用它们。然而,一个更方便的方法是使用 combine() 函数将它们捆绑在一起。
>>> clf_metrics = evaluate.combine(["accuracy", "f1", "precision", "recall"])
`combine` 函数既接受指标名称列表,也接受实例化的模块。然后 `compute` 调用会计算每个指标。
>>> clf_metrics.compute(predictions=[0, 1, 0], references=[0, 1, 1])
{
'accuracy': 0.667,
'f1': 0.667,
'precision': 1.0,
'recall': 0.5
}
保存并推送到 Hub
保存和共享评估结果是重要的一步。我们提供 evaluate.save() 函数来轻松保存指标结果。你可以传递一个特定的文件名或一个目录。在后一种情况下,结果会保存在一个自动创建文件名的文件中。除了目录或文件名,该函数还接受任何键值对作为输入,并将它们存储在一个 JSON 文件中。
>>> result = accuracy.compute(references=[0,1,0,1], predictions=[1,0,0,1])
>>> hyperparams = {"model": "bert-base-uncased"}
>>> evaluate.save("./results/", experiment="run 42", **result, **hyperparams)
PosixPath('results/result-2022_05_30-22_09_11.json')
JSON 文件的内容如下所示:
{
"experiment": "run 42",
"accuracy": 0.5,
"model": "bert-base-uncased",
"_timestamp": "2022-05-30T22:09:11.959469",
"_git_commit_hash": "123456789abcdefghijkl",
"_evaluate_version": "0.1.0",
"_python_version": "3.9.12 (main, Mar 26 2022, 15:51:15) \n[Clang 13.1.6 (clang-1316.0.21.2)]",
"_interpreter_path": "/Users/leandro/git/evaluate/env/bin/python"
}
除了指定的字段外,它还包含有用的系统信息,以便复现结果。
除了在本地存储结果,你还应该在 Hub 上的模型仓库中报告它们。使用 evaluate.push_to_hub() 函数,你可以轻松地将评估结果报告到模型的仓库中。
evaluate.push_to_hub(
model_id="huggingface/gpt2-wikitext2", # model repository on hub
metric_value=0.5, # metric value
metric_type="bleu", # metric name, e.g. accuracy.name
metric_name="BLEU", # pretty name which is displayed
dataset_type="wikitext", # dataset name on the hub
dataset_name="WikiText", # pretty name
dataset_split="test", # dataset split used
task_type="text-generation", # task id, see https://github.com/huggingface/evaluate/blob/main/src/evaluate/config.py#L154-L192
task_name="Text Generation" # pretty name for task
)
Evaluator
evaluate.evaluator() 提供了自动评估功能,只需要一个模型、数据集和指标,这与 `EvaluationModule` 中的指标不同,后者需要模型的预测结果。因此,它更容易在给定数据集和指标的情况下评估模型,因为推理过程在内部处理。为了实现这一点,它使用了 `transformers` 的 pipeline 抽象。不过,你也可以使用自己的框架,只要它遵循 `pipeline` 接口即可。
要使用 `evaluator` 进行评估,我们先加载一个 `transformers` pipeline(但你也可以传递任何框架的自定义推理类,只要它遵循 pipeline 调用 API),该 pipeline 使用一个在 IMDb 上训练过的模型,以及 IMDb 测试集和准确率指标。
from transformers import pipeline
from datasets import load_dataset
from evaluate import evaluator
import evaluate
pipe = pipeline("text-classification", model="lvwerra/distilbert-imdb", device=0)
data = load_dataset("imdb", split="test").shuffle().select(range(1000))
metric = evaluate.load("accuracy")
然后,你可以创建一个文本分类的 evaluator,并将这三个对象传递给 `compute()` 方法。通过标签映射,`evaluate` 提供了一种方法,可以将 pipeline 的输出与数据集中的标签列对齐。
>>> task_evaluator = evaluator("text-classification")
>>> results = task_evaluator.compute(model_or_pipeline=pipe, data=data, metric=metric,
... label_mapping={"NEGATIVE": 0, "POSITIVE": 1},)
>>> print(results)
{'accuracy': 0.934}
仅仅计算指标值通常不足以判断一个模型是否显著优于另一个模型。通过*自助法 (bootstrapping)*,`evaluate` 计算置信区间和标准误差,这有助于估计分数的稳定性。
>>> results = eval.compute(model_or_pipeline=pipe, data=data, metric=metric,
... label_mapping={"NEGATIVE": 0, "POSITIVE": 1},
... strategy="bootstrap", n_resamples=200)
>>> print(results)
{'accuracy':
{
'confidence_interval': (0.906, 0.9406749892841922),
'standard_error': 0.00865213251082787,
'score': 0.923
}
}
evaluator 期望数据输入中包含 `"text"` 和 `"label"` 列。如果你的数据集不同,你可以通过 `input_column="text"` 和 `label_column="label"` 关键字来提供列名。目前仅支持 `"text-classification"`,未来将添加更多任务。
可视化
在比较多个模型时,仅仅通过看分数很难发现它们性能上的差异。而且通常没有一个单一的最佳模型,而是在例如延迟和准确率之间存在权衡,因为较大的模型可能有更好的性能,但速度也更慢。我们正在逐步添加不同的可视化方法,如图表,以便更容易地为特定用例选择最佳模型。
例如,如果你有一个包含多个模型结果的列表(以字典形式),你可以将它们输入到 `radar_plot()` 函数中。
import evaluate
from evaluate.visualization import radar_plot
>>> data = [
{"accuracy": 0.99, "precision": 0.8, "f1": 0.95, "latency_in_seconds": 33.6},
{"accuracy": 0.98, "precision": 0.87, "f1": 0.91, "latency_in_seconds": 11.2},
{"accuracy": 0.98, "precision": 0.78, "f1": 0.88, "latency_in_seconds": 87.6},
{"accuracy": 0.88, "precision": 0.78, "f1": 0.81, "latency_in_seconds": 101.6}
]
>>> model_names = ["Model 1", "Model 2", "Model 3", "Model 4"]
>>> plot = radar_plot(data=data, model_names=model_names)
>>> plot.show()
这可以让你直观地比较这 4 个模型,并根据一个或多个指标选择最适合你的模型。

在一系列任务上运行评估
在各种不同的任务上评估模型,以了解它们的下游性能可能很有用。EvaluationSuite 能够在一系列任务上评估模型。任务可以构建为 (evaluator, dataset, metric) 元组,并传递给存储在 Hugging Face Hub 上作为 Space 的 EvaluationSuite,或者本地作为 Python 脚本。有关当前支持的任务列表,请参阅 evaluator 文档。
`EvaluationSuite` 脚本可以如下定义,并支持用于数据预处理的 Python 代码。
import evaluate
from evaluate.evaluation_suite import SubTask
class Suite(evaluate.EvaluationSuite):
def __init__(self, name):
super().__init__(name)
self.suite = [
SubTask(
task_type="text-classification",
data="imdb",
split="test[:1]",
args_for_task={
"metric": "accuracy",
"input_column": "text",
"label_column": "label",
"label_mapping": {
"LABEL_0": 0.0,
"LABEL_1": 1.0
}
}
),
SubTask(
task_type="text-classification",
data="sst2",
split="test[:1]",
args_for_task={
"metric": "accuracy",
"input_column": "sentence",
"label_column": "label",
"label_mapping": {
"LABEL_0": 0.0,
"LABEL_1": 1.0
}
}
)
]
可以通过加载 `EvaluationSuite` 并使用模型或 pipeline 调用 `run()` 方法来运行评估。
>>> from evaluate import EvaluationSuite
>>> suite = EvaluationSuite.load('mathemakitten/sentiment-evaluation-suite')
>>> results = suite.run("huggingface/prunebert-base-uncased-6-finepruned-w-distil-mnli")
准确率 | 总耗时(秒) | 每秒样本数 | 延迟(秒) | 任务名称 |
---|---|---|---|---|
0.3 | 4.62804 | 2.16074 | 0.462804 | imdb |
0 | 0.686388 | 14.569 | 0.0686388 | sst2 |