Hugging Face Datasets 怎样用 flatten_indices 恢复顺序访问性能
如果一个 Hugging Face Datasets 的 Dataset 在 shuffle()、select() 或某些筛选操作后访问变慢,常见原因不是列数据突然变大,而是对象多了一层 indices mapping。读取一行时,程序要先通过映射找到底层 Arrow 表中的真实行,原本可以连续读取的数据块也可能被打散。
解决办法是接收 flatten_indices() 返回的新对象:它会把当前逻辑顺序的数据重写到新的缓存中,移除间接索引,让后续访问回到连续数据路径。官方资料:https://huggingface.co/docs/datasets/process。
为什么 shuffle 之后访问会变慢
Dataset 由 Arrow 表支撑。没有索引映射时,按相邻行读取可以利用连续数据块;而 shuffle() 通常保存一张重新排列后的行号表。调用方看到的顺序是对的,但每次取值都要多一次映射,连续读取也更难保持。
因此,flatten_indices() 不是“把数据重新排序一次的装饰方法”,而是把当前逻辑顺序物化成一份新的连续数据。它会产生写入成本,换来后续训练或批量遍历更简单的读取路径。

最小写法:把返回值赋回 Dataset
所有这类处理方法都返回新的 Dataset,不会把原变量原地改好。因此关键写法是把 flatten_indices() 的返回值重新赋给变量:
from datasets import load_dataset
# 载入一个训练集分片,实际项目中可替换为自己的数据集名称
dataset = load_dataset("nyu-mll/glue", "mrpc", split="train")
# shuffle 产生逻辑上的新顺序,也可能引入 indices mapping
shuffled = dataset.shuffle(seed=42)
# 把当前顺序重写成连续数据;必须接收返回的新 Dataset
flattened = shuffled.flatten_indices()
# 后续训练或批量读取使用重写后的对象
for row in flattened.select(range(3)):
print(row["label"], row["sentence1"][:30])
这里的 flattened 保留的是 shuffled 对外可见的行顺序,但底层不再依赖那张索引映射。若写成 shuffled.flatten_indices() 却继续使用 shuffled,重写动作本身可能已经完成,后续读取却仍然走旧对象,这是最容易忽略的错误。
flatten_indices 的参数怎么选
默认调用适合先验证流程,但大数据集需要明确写入策略。官方 API 提供的参数可以按下面的职责理解:
| 参数 | 作用 | 使用建议 |
|---|---|---|
cache_file_name | 指定重写结果的缓存文件位置 | 磁盘路径可控、临时盘空间紧张或需要固定缓存位置时设置 |
writer_batch_size | 缓存写入器一次处理的行数 | 增大可能减少查找次数,但会占用更多临时内存 |
num_proc | 生成缓存时使用的最大进程数 | CPU 和磁盘允许时再提高;先确认数据源与存储能承受并发 |
keep_in_memory | 是否把结果保留在内存而不写缓存文件 | 只适合数据较小且内存预算明确的短流程 |

例如,希望把重写结果落到指定缓存文件,并使用较大的写入批量,可以这样写:
from pathlib import Path
# 目录应位于有足够空间且生命周期明确的缓存盘
cache_path = Path("./dataset-cache/mrpc-shuffled.arrow")
cache_path.parent.mkdir(parents=True, exist_ok=True)
# 指定缓存位置;num_proc 需要结合 CPU、磁盘吞吐和数据规模调整
flattened = shuffled.flatten_indices(
cache_file_name=str(cache_path),
writer_batch_size=1000,
num_proc=2,
)
# 后续把 flattened 传给训练器,而不是继续使用 shuffled
print(flattened.column_names)
writer_batch_size 不是“越大越快”的开关。它影响写入器的批量和临时内存,应该在真实机器的内存、磁盘和并发条件下调整;num_proc 也不是免费加速,多个进程可能让共享存储成为瓶颈。
什么时候不应该马上 flatten
flatten_indices() 会重写整个逻辑数据集,因此它适合“后面要反复读取”的场景,不适合每个小实验都调用一次。下面三种情况可以先不做:
- 只抽取很小的样本做一次性检查,直接使用当前对象更省事。
- 数据集即将再次筛选、打乱或拆分,过早重写会产生一次额外的磁盘写入。
- 训练流程接受流式遍历且不要求精确的全量随机访问,可以考虑
to_iterable_dataset()。
官方文档还给出另一条思路:先把数据转换为 IterableDataset,再使用带缓冲区的近似 shuffle。它避免了把所有随机顺序一次性物化,代价是访问模型从可按索引取行变成惰性迭代,不能把两种对象当成完全等价的替换。
常见误区与排查顺序
- 没有接收返回值:确认训练器、DataLoader 或后续
map()使用的是重写后的变量。 - 把重写当成原地操作:先把新对象命名为
flattened,等流程稳定后再覆盖旧变量,便于排查顺序问题。 - 忽略磁盘空间:重写期间要同时考虑原始数据、缓存文件和临时分片,不要只看数据集的逻辑大小。
- 只盯着 CPU:重写与读取速度还受磁盘连续写入、缓存目录和进程数影响,增加
num_proc前先看存储吞吐。 - 把近似 shuffle 当精确 shuffle:
IterableDataset.shuffle()使用缓冲区,是另一种随机化模型;如果任务依赖可复现的精确行顺序,要保留明确的 seed 与数据处理链。
结论与相关问题
一句话概括:如果 shuffle 或筛选后的 Dataset 要被反复顺序读取,就把 flatten_indices() 当成一次“用写入换读取”的整理步骤,并接收它返回的新对象;如果只是短暂实验或适合流式遍历,则先评估是否需要这次全量重写。
flatten_indices 会改变 shuffle 后的顺序吗?
它的目标是移除索引映射并按当前逻辑顺序重写数据,不是重新随机一次。文章示例中的顺序仍由前面的 shuffle(seed=42) 决定。
为什么指定了 cache_file_name 还要保留原始数据?
缓存文件是重写结果,原始数据仍可能被其他流程使用。是否清理原始数据要由你的缓存生命周期和可恢复需求决定,不能把缓存路径当作自动迁移或自动删除开关。
num_proc 应该设置成 CPU 核数吗?
不一定。它还受存储吞吐、数据格式和机器内存约束,建议从较小值开始观察整体重写耗时与资源占用。
Audacity 怎样用标签导出多段独立音频
- 上一篇
- Audacity 怎样用标签导出多段独立音频
- 下一篇
- Hugging Face Datasets 怎样按特征层级展开嵌套字段
-
- 科技周边 · 人工智能 | 35分钟前 |
- PEFT 怎样分别启用和停用模型中的 LoRA 层
- 483浏览 收藏
-
- 科技周边 · 人工智能 | 38分钟前 | LoRa PEFT merge_and_unload
- PEFT 怎样在合并适配器后恢复基础模型接口
- 185浏览 收藏
-
- 科技周边 · 人工智能 | 39分钟前 |
- Hugging Face Tokenizers 怎样为句对配置后处理模板
- 420浏览 收藏
-
- 科技周边 · 人工智能 | 43分钟前 |
- Hugging Face Tokenizers 怎样组合多个文本正规化器
- 415浏览 收藏
-
- 科技周边 · 人工智能 | 44分钟前 | ai · CrossEncoder Sentence Transformers 文档重排
- Sentence Transformers 怎样用 CrossEncoder 对候选文档重排
- 224浏览 收藏
-
- 科技周边 · 人工智能 | 44分钟前 | 人工智能 · 向量数据库 · 向量检索 Sentence Transformers 嵌入向量 二进制量化
- Sentence Transformers 怎样用二进制量化保存嵌入向量
- 150浏览 收藏
-
- 科技周边 · 人工智能 | 48分钟前 | 性能优化 · 人工智能 · ONNX Runtime InferenceSession SessionOptions 图优化
- ONNX Runtime 怎样为指定会话选择图优化等级
- 269浏览 收藏
-
- 科技周边 · 人工智能 | 49分钟前 |
- ONNX Runtime 怎样把优化后的模型另存为文件
- 372浏览 收藏
-
- 科技周边 · 人工智能 | 52分钟前 | python · 人工智能 · Optuna 超参数优化 MedianPruner 中间指标
- Optuna MedianPruner 怎样结合中间指标提前停止试验
- 298浏览 收藏
-
- 科技周边 · 人工智能 | 54分钟前 | 数据处理 · 人工智能 · 嵌套字段 Hugging Face Datasets flatten Features
- Hugging Face Datasets 怎样按特征层级展开嵌套字段
- 350浏览 收藏
-
- 科技周边 · 人工智能 | 15小时前 | API · 人工智能 · vLLM max_tokens 推理服务
- vLLM 怎样为在线服务设置请求最大 Token 数
- 326浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 775次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 771次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 856次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 821次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 652次使用
-
- go zero微服务实战性能优化极致秒杀
- 2022-12-27 207浏览
-
- Go pprof 排查慢接口:别只会看火焰图,先把问题问对
- 2026-06-01 101浏览
-
- Go JSON v2 实战:别急着替换 encoding/json,先搞懂这些变化
- 2026-06-01 437浏览
-
- Go 1.25 容器感知 GOMAXPROCS:K8s 里别再让 CPU limit 偷偷拖垮 P99
- 2026-06-01 473浏览
-
- Go map 新实现实战:Swiss Tables 变快了,但别急着改业务代码
- 2026-06-01 218浏览

