如何利用外部标签文件构建含ClassLabel的Huggingface Dataset?
我发现几乎所有使用ClassLabel的Hugging Face Datasets示例都用硬编码标签列表的方式,比如ag_news的实现代码如下:
def _info(self): return datasets.DatasetInfo( description=_DESCRIPTION, features=datasets.Features( { "text": datasets.Value("string"), "label": datasets.features.ClassLabel(names=["World", "Sports", "Business", "Sci/Tech"]), } ), homepage="http://groups.di.unipi.it/~gulli/AG_corpus_of_news_articles.html", citation=_CITATION, task_templates=[TextClassification(text_column="text", label_column="label")], )
我现在要构建一个包含大量标签且标签带额外元数据的数据集,比如有个labels.json文件,内容如下:
{"name":"label_1", "category":"c1", "reference":123} {"name":"label_2", "category":"c1", "reference":456} {"name":"label_3", "category":"c2", "reference":789}
(后续会把这些额外元数据用于推理,和当前问题无关)
我想读取这个文件来构建DatasetInfo,特别是在数据集加载时生成names数组,但_info方法没传入download_manager,而这个工具是定位缓存中本地文件必需的,该怎么解决?
方法1:通过Builder实例传递缓存后的标签文件路径
Dataset Builder的实例支持存储自定义属性,可以在_download方法里用download_manager完成labels.json的下载或缓存,把本地路径存在Builder的属性中,之后在_info方法直接读取该路径:
class MyDataset(datasets.GeneratorBasedBuilder): def _download(self, config, split, download_manager): # 下载/缓存labels.json,返回本地路径 self.label_file_path = download_manager.download_and_extract("path/to/labels.json") # 处理其他数据集文件的下载逻辑... return {"label_file": self.label_file_path, ...} def _info(self): import json labels = [] with open(self.label_file_path, "r", encoding="utf-8") as f: for line in f: labels.append(json.loads(line.strip())) label_names = [label["name"] for label in labels] return datasets.DatasetInfo( description="自定义数据集描述", features=datasets.Features( { "text": datasets.Value("string"), "label": datasets.features.ClassLabel(names=label_names), } ), # 补充主页、引用等其他属性 )
如果是本地数据集,也可以用download_manager.local_file处理本地路径,确保路径在缓存体系中被正确识别。
方法2:直接通过配置的data_dir读取本地标签文件
如果labels.json和数据集文件在同一个目录下,可以在_info方法中通过self.config.data_dir获取数据集根目录,拼接路径直接读取:
import os import json def _info(self): label_file_path = os.path.join(self.config.data_dir, "labels.json") labels = [] with open(label_file_path, "r", encoding="utf-8") as f: for line in f: labels.append(json.loads(line.strip())) label_names = [label["name"] for label in labels] return datasets.DatasetInfo( # 构建相关内容 features=datasets.Features( { "text": datasets.Value("string"), "label": datasets.features.ClassLabel(names=label_names), } ), )
这种方法适合本地数据集场景,不需要依赖download_manager,直接通过配置的data_dir定位文件。
方法3:保留标签元数据到DatasetInfo的metadata字段
如果需要保留标签的额外元数据(比如category、reference),可以把这些信息存入DatasetInfo的metadata字段,方便后续推理使用:
def _info(self): import json # 用上述两种方法之一获取标签文件路径 labels = [] with open(self.label_file_path, "r", encoding="utf-8") as f: for line in f: labels.append(json.loads(line.strip())) label_names = [label["name"] for label in labels] # 整理标签元数据 label_metadata = { label["name"]: {"category": label["category"], "reference": label["reference"]} for label in labels } return datasets.DatasetInfo( # 其他属性 features=datasets.Features( { "text": datasets.Value("string"), "label": datasets.features.ClassLabel(names=label_names), } ), metadata={"label_metadata": label_metadata} )
后续可以通过dataset.info.metadata["label_metadata"]获取这些元数据。
内容的提问来源于stack exchange,提问作者David Waterworth

