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

Hugging Face 数据集流式读取怎样减少本地磁盘

来源:17golang原创

时间:2026-10-14 11:22:20 278浏览 收藏

Hugging Face 数据集流式读取可以减少“先下载完整数据,再转换为本地数据集”的磁盘需求。关键写法是 load_dataset(..., streaming=True),并逐条或小批消费返回的 IterableDataset,避免随后又把全量转换成列表、DataFrame 或文件。它不是零磁盘、零网络,也不自动节省模型和训练输出的空间。

官方地址:https://huggingface.co/docs/datasets/stream。本文只讨论 Datasets 的读取路径,代码为原创说明示例,没有执行、下载数据或测量磁盘占用。

先限制消费范围,再考虑大数据集

如果只是看字段、做小样本预处理或顺序训练,可以先流式读取少量记录。下面以读者自行提供、已有访问权限的 JSONL 数据文件为输入,不绑定可能变化的数据集名称,也不打印原始文本。data_files 可以是经确认支持访问的远程地址,或自己的本地文件;本地文件已经占用的空间不会被 streaming 消除。

import os
from datasets import load_dataset

# 数据地址由读者提供;缺少配置时明确报错,不使用虚构仓库
source = os.environ.get("DEMO_JSONL_SOURCE")
if not source:
    raise RuntimeError("请先配置 DEMO_JSONL_SOURCE")
stream = load_dataset(
    "json", data_files={"train": source},
    split="train", streaming=True,
)
# 仅消费最多三条,不将全量流转成列表,也不输出敏感内容
for position, sample in enumerate(stream.take(3), start=1):
    print(position, sorted(sample.keys()))

文件必须是适合该加载器的 JSONL,记录字段也要满足后续处理要求。网络错误可能在开始迭代时才出现,因此创建对象成功不等于数据已经读取成功。地址、配置、split 和权限都属于读取任务的输入。

流式对象应当被视为数据源的迭代入口,不是已经在内存中的全部记录。只读三条可以限制样本数量,但网络预取、压缩块和存储格式可能导致读取多于三条对应的字节,不能直接推导为精确的字节限额。

数据文件、加载器与有限消费之间的静态依赖说明
图一:读取配置和有限消费的静态关系图,不是下载进度或运行结果。

流式与本地数据集,适合的负载不同

常规 Dataset 支持按索引访问,通常使用本地 Arrow 数据和内存映射,并不是把全部数据一次塞进 RAM。IterableDataset 更适合顺序消费;不能把它当作同样支持任意行号随机访问的表。为了查很靠后的记录而跳过前面的样本,仍可能产生大量读取工作。

负载更合适的起点主要代价
只探索少量样本流式加有限 take依赖源可访问,仍有网络与解码开销
顺序处理一次大数据流式与小批转换吞吐受读取和处理共同约束
频繁按任意行取样本地 Dataset需为下载和转换保留磁盘
多轮离线复用固定本地数据版本提前准备数据及空间预算

先常规加载再调用 to_iterable_dataset,可以得到迭代形式,但不能撤销之前的下载和 Arrow 准备。它解决消费形式的问题,不等同于一开始使用远程 streaming。

为缓冲与转换设定边界

shuffle 的 buffer_size 控制缓冲中的样本数量,不是字节上限。一个大文本样本可能远大于另一个,多进程、多 worker 还会放大内存压力。有限缓冲的打乱也不是全量精确随机排列,不能把统计要求悄悄替换掉。

下面只保留短文本预览,按需转换而不保存全量。选择 shuffle 时放在 take 之前;预览文本仅用于说明处理,正式任务应遵循数据使用规则。

# 示例要求记录含字符串 text;字段不符合时先检查数据模式
def preview(sample):
    text = sample.get("text")
    if not isinstance(text, str):
        raise ValueError("示例要求 text 为字符串")
    return {"preview": text[:80]}

# map 的转换随消费发生;参数不是磁盘配额
prepared = stream.map(preview)
# 有限缓冲打乱不等于完整数据集的精确洗牌
small = prepared.shuffle(seed=73, buffer_size=256).take(5)
for sample in small:
    # 只展示长度,避免把原始内容写入日志
    print(len(sample["preview"]))

如果后面调用 list(prepared),前面的流式读取不会阻止全量内存积累;如果逐条写到本地文件,磁盘仍会随着输出增长。降低读取缓存和控制输出保存是两个独立决策。训练检查点、日志、tokenizer 或模型权重也不属于此处 streaming 参数的控制范围。

打乱缓冲、预处理、缓存与输出的资源职责说明
图二:内存预算和磁盘预算分别对应不同对象的静态说明图。

记录缓存位置,不把搬目录当成减少数据量

Hugging Face Hub 缓存与 Datasets 的 Arrow、索引缓存是不同位置。HF_DATASETS_CACHE 主要控制 Datasets 自身缓存,不控制所有 Hub 下载;HF_HUB_CACHE 控制 Hub 文件缓存;HF_HOME 可以作为总体缓存根目录。环境变量应在导入相关库之前由启动环境设置。

改变缓存位置只是把空间压力转移到另一个磁盘,不会自动清除旧文件或缩小已有缓存。streaming 也不会自动清理此前常规下载产生的内容。先识别文件归属,再遵循项目缓存维护策略,不能直接递归删除公共缓存目录;其他任务可能仍在使用它。

预算至少分为数据源本地文件、库缓存、输出文件三栏;内存再记录打乱缓冲、小批样本与 worker 数量。多模态解码、访问实现或程序自己的临时文件还可能带来额外成本,所以“开启流式”不能代替整条任务的空间约束。

按可靠性选择读取方案,并留出恢复余地

在网络可靠且顺序消费的任务中,远程流式可以减少开始前的完整落盘;网络不稳定、要求离线或重复很多轮的任务,本地准备通常更值得考虑。这个选择是按负载约束作出的建议,不是对所有环境的速度排名。

长任务要记录固定的数据版本、分片范围、转换规则和已经提交的处理进度。异常后重新读取可能重复前面的记录,不能把盲目 skip 当成永远稳定的断点恢复;数据源变化或打乱顺序变化都会影响位置含义。支持的状态恢复能力依实际库版本和数据源确认,业务输出仍需幂等或去重设计。

开始大规模运行前,读者可在自己的环境先消费小范围,记录实际读取、缓存目录增量和内存峰值,再逐步增加消费量。本文没有进行这些检查,也不提供伪造结果。结论是:流式减少全量预下载及转换的需求,有限消费避免重新物化,输出与缓存预算决定最终的磁盘占用。

相关问题

streaming 是否完全不使用磁盘?不能保证。已有源文件、元数据、其他库缓存和程序输出仍可能占空间。

Dataset 一定把数据全放进内存吗?不是,本地 Arrow 与内存映射使它具有不同于普通 Python 全量列表的访问方式。

只改缓存目录能解决磁盘不足吗?只能调整位置,还需评估数据量、旧缓存和输出文件。

参考:https://huggingface.co/docs/datasets/about_mapstyle_vs_iterable;加载说明:https://huggingface.co/docs/datasets/loading;缓存管理:https://huggingface.co/docs/datasets/cache。

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