Hub documentation

대규모 데이터셋 처리

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

대규모 데이터셋 처리

모든 Job에는 hardware flavor에 의해 설정된 고정된 양의 로컬 디스크가 제공됩니다(Ephemeral Storage 열, hf jobs hardware에도 표시됨). 해당 디스크에 전체 데이터셋을 적재하지 않아도 데이터셋과 Storage Buckets를 Hub에서 직접 읽을 수 있습니다. 스트리밍, 쿼리, 마운트 방식으로 접근할 수 있으므로, 단일 Job이 디스크 용량보다 훨씬 큰 데이터를 처리할 수 있습니다. 이 페이지에서는 각 옵션과 사용 시점을 다룹니다.

어떤 접근 방식인가요?

  • 디스크에 맞음 → load_dataset(...)을 그대로 사용할 수 있습니다(또는 최대 1 TB의 임시 디스크를 지원하는 더 큰 버전을 선택할 수 있습니다).
  • 행을 반복하며 처리하거나 학습하는 경우 → stream으로 처리하세요.
  • 필터링 또는 컬럼 제거된 스캔 → Polars 또는 DuckDB를 사용하여 hf:// 에서 직접 쿼리합니다.
  • 로컬 파일 경로를 기대하는 도구 → 저장소를 mount하고 지연하여 읽습니다.
  • 결과 저장 → Job이 종료된 후에도 유지되도록 Storage Bucket에 기록합니다.

데이터셋 스트리밍

Streaming은 코드가 예제를 소비하는 동안 Hub에서 예제를 스트리밍으로 읽습니다. 다운로드나 로컬 복사본이 필요 없으며, 수 TB 규모의 데이터셋까지 확장할 수 있습니다. 최근 릴리스에서 최대 100배 더 효율적으로 개선되어, 여러 워커에 걸쳐 학습할 때 로컬 SSD와 동등한 성능을 달성합니다:

from datasets import load_dataset

ds = load_dataset("HuggingFaceFW/fineweb-edu", "sample-10BT", split="train", streaming=True)
for example in ds.take(1000):
    ...  # streams in as you iterate, nothing hits disk

스트림 데이터셋은 지연 .filter(), .map(), .shuffle(buffer_size=...), .batch()를 지원하는 IterableDataset이며, 디스크보다 큰 데이터로 학습하기 위해 PyTorch DataLoader 또는 Trainer에 바로 전달할 수 있습니다. 전체 API는 Stream 가이드를, 단일 노드 또는 분산 환경의 끝에서 끝까지 학습 튜토리얼은 예제 & 튜토리얼을 참고하세요.

Streaming은 Spark를 사용하여 분산 환경에서도 작동합니다:

import pyspark_huggingface

df = spark.read.format("huggingface").option("config", "sample-10BT").load("HuggingFaceFW/fineweb-edu")

결과 Spark dataframe는 분산됩니다. 각 워커는 자신의 파일 하위 집합에서 스트리밍합니다. 행과 열을 읽고, 쓰고, 효율적으로 필터링하는 예제는 Spark 문서를 참조하세요.

hf://에서 읽고 필터링

많은 데이터 라이브러리가 hf:// 경로를 통해 Hub 데이터셋을 직접 읽습니다. Polars, DuckDB, pandas는 모두 Hub Parquet를 네이티브로 스캔하며, 필터와 컬럼 선택을 스캔 단계로 내리므로 단일 Job이 메모리나 디스크에 들어가지 않는 훨씬 더 많은 데이터를 처리할 수 있습니다. 이 쿼리는 기본 CPU flavor에서 약 28 GB의 Parquet를 약 4분 만에 요약합니다:

import polars as pl

agg = (
    pl.scan_parquet("hf://datasets/HuggingFaceFW/fineweb-edu/sample/10BT/*.parquet")
    .filter(pl.col("int_score") >= 4)
    .group_by("int_score")
    .agg(pl.len().alias("docs"), pl.col("token_count").sum().alias("tokens"))
    .sort("int_score")
    .collect()
)
print(agg)

이러한 스캔은 메모리보다 네트워크에 의존적이며, 엔진마다 원격 읽기를 병렬화하는 방식이 다르므로 라이브러리별 타이밍이 달라집니다. 두 가지 실용적인 시사점: 긴 스캔의 경우 --timeout을 기본값인 30분보다 높게 설정하고, 더 빠르게 처리하려면 작업을 여러 개의 Job으로 나누어 병렬로 실행하세요. 라이브러리별 예제는 Polars, DuckDB, pandas를 참고하고, hf://를 통해 buckets를 읽는 방법은 Python data tools를 참고하세요(이는 HfFileSystem를 통해 처리됩니다).

데이터셋, 모델 또는 버킷 마운트

-v / --volume를 사용하여 리포지토리 또는 버킷을 Job에 로컬 경로로 마운트합니다. 코드가 파일을 읽을 때 네트워크를 통해 지연 로드되므로 로컬 파일을 읽는 모든 도구가 그대로 작동합니다:

hf jobs uv run --flavor cpu-upgrade \
  -v hf://datasets/HuggingFaceFW/fineweb-edu:/mnt/data \
  process.py
# /// script
# dependencies = ["polars"]
# ///
# process.py — the mounted repo is just a directory of files
from pathlib import Path

import polars as pl

for path in Path("/mnt/data/sample/10BT").glob("*.parquet"):
    shard = pl.read_parquet(path)
    ...  # process one shard at a time, write results out

파일이 전체로 소비되는 경우(모델 가중치, 오디오 또는 이미지 파일, 아카이브 등)나 도구가 파일 경로만 허용하는 경우 마운팅이 자연스러운 선택입니다. 대규모 다중 파일 Parquet 스캔의 경우, 마운트를 통해 스캔하는 것보다 hf://를 직접 쿼리하는 것이 일반적으로 몇 배 더 빠릅니다.

Datasets와 models는 읽기 전용으로 마운트되며, buckets는 읽기/쓰기 가능하므로 결과를 저장하는 데 적합합니다. 전체 -v 문법은 Configuration을, 세부 사항은 bucket access patterns을 참고하세요.

마운트를 통해 읽은 파일은 Job의 임시 디스크에 캐시되므로, 지연 읽기(한 번에 하나의 파일씩 읽기) 방식으로 읽으면 사용량을 작게 유지할 수 있습니다. hf jobs uv run로 로컬 스크립트를 실행할 경우 스크립트 디렉터리가 /data에 마운트되므로, 데이터는 다른 위치(예: /mnt/data)에 마운트해야 합니다.

결과 저장

Ephemeral disk은 Job이 종료되면 유지되지 않으므로, 유지하려는 데이터는 읽기/쓰기 권한으로 마운트된 Storage Bucket에 작성하거나 Hub에 dataset으로 push하세요. DuckDB는 hf://를 통해 소스를 필터링하고, out-of-core 쿼리 하나로 매칭된 결과를 마운트된 버킷에 바로 작성할 수 있어, 결과가 메모리에 모두 들어맞을 필요가 없습니다:

hf jobs uv run --flavor cpu-upgrade --timeout 1h \
  -v hf://buckets/username/my-output:/mnt/out \
  filter.py
# /// script
# dependencies = ["duckdb"]
# ///
# filter.py — scan ~28 GB of Parquet, keep only the matching rows
import duckdb

duckdb.sql(
    """
    COPY (
        SELECT text, url, token_count
        FROM 'hf://datasets/HuggingFaceFW/fineweb-edu/sample/10BT/*.parquet'
        WHERE int_score >= 4 AND token_count >= 4000
    ) TO '/mnt/out/result.parquet' (FORMAT parquet)
    """
)

버킷 마운트 경로 아래에 작성된 파일은 Job이 종료된 후에도 유지됩니다. 대신 처리된 데이터셋을 게시하려면 Dataset.push_to_hub를 사용하세요.

실제 예제: Common Crawl을 다운로드하지 않고 쿼리하기

Common Crawl은 아카이브를 commoncrawl/commoncrawl 버킷에 미러링합니다 — 수백 TB 규모입니다. hf://에서 WET(평문) 샤드 하나를 스트리밍하여 파싱하고 DuckDB로 쿼리할 수 있습니다. gzip이 순차적으로 읽혀지고 조기 중단되므로 전송되는 데이터는 몇 MB에 불과합니다:

# /// script
# requires-python = ">=3.11"
# dependencies = ["huggingface_hub>=1.9", "fastwarc>=0.15", "duckdb>=1.0"]
# ///
import duckdb
from fastwarc.warc import ArchiveIterator, WarcRecordType
from huggingface_hub import hffs

WET = (
    "buckets/commoncrawl/commoncrawl/crawl-data/CC-MAIN-2026-17/"
    "segments/1775805908305.14/wet/"
    "CC-MAIN-20260410081153-20260410111153-00000.warc.wet.gz"
)

rows = []
with hffs.open(WET, "rb") as f:
    for rec in ArchiveIterator(f, record_types=WarcRecordType.conversion):
        lang = (rec.headers.get("WARC-Identified-Content-Language", "") or "und").split(",")[0]
        rows.append((rec.headers.get("WARC-Target-URI", ""), lang, len(rec.reader.read())))
        if len(rows) >= 5000:
            break

con = duckdb.connect()
con.execute("CREATE TABLE wet(url VARCHAR, lang VARCHAR, n_chars BIGINT)")
con.executemany("INSERT INTO wet VALUES (?,?,?)", rows)
con.sql("SELECT lang, count(*) AS docs FROM wet GROUP BY lang ORDER BY docs DESC LIMIT 10").show()

hf jobs uv run cc_wet.py로 실행하면 기본 CPU flavor에서 약 1분 만에 완료되며 다음과 같이 출력됩니다:

┌─────────┬───────┐
│  lang   │ docs  │
│ varchar │ int64 │
├─────────┼───────┤
│ eng     │  1974 │
│ zho     │   586 │
│ rus     │   434 │
│ jpn     │   244 │
│ …       │    …  │
└─────────┴───────┘

참고

Update on GitHub