Datasets documentation

Stream

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Stream

Streaming dataset memungkinkan Anda bekerja dengan dataset tanpa mengunduhnya. Data akan di-stream saat Anda mengiterasi dataset. Ini sangat membantu ketika:

  • Anda tidak ingin menunggu dataset yang sangat besar untuk diunduh.
  • Ukuran dataset melebihi jumlah ruang disk yang tersedia di komputer Anda.
  • Anda ingin dengan cepat mengeksplorasi hanya beberapa sampel dari dataset.

Sebagai contoh, bagian bahasa Inggris dari dataset HuggingFaceFW/fineweb berukuran 45 terabita, tetapi Anda dapat menggunakannya secara instan dengan streaming. Alirkan dataset dengan mengatur streaming=True di load_dataset() seperti yang ditunjukkan di bawah ini:

>>> from datasets import load_dataset
>>> dataset = load_dataset('HuggingFaceFW/fineweb', split='train', streaming=True)
>>> print(next(iter(dataset)))
{'text': 'How AP reported in all formats from tornado-stricken regionsMarch 8, 2012\nWhen the first serious bout of tornadoes of 2012 blew through middle America in the middle of the night, they touched down in places hours from any AP bureau...', ...,
 'language_score': 0.9721424579620361, 'token_count': 717}

Streaming dataset juga memungkinkan Anda bekerja dengan dataset yang terdiri dari file lokal tanpa perlu melakukan konversi apa pun. Dalam kasus ini, data di-stream dari file lokal saat Anda mengiterasi dataset. Ini sangat membantu ketika:

  • Anda tidak ingin menunggu dataset lokal yang sangat besar untuk dikonversi ke Arrow.
  • Ukuran file yang dikonversi akan melebihi kapasitas ruang disk yang tersedia di komputer Anda.
  • Anda ingin dengan cepat mengeksplorasi hanya beberapa sampel dari dataset.
  • Anda ingin memuat hanya kolom tertentu atau memfilter dataset Parquet secara efisien.

Sebagai contoh, Anda dapat melakukan streaming dataset lokal berisi ratusan file JSONL terkompresi seperti oscar-corpus/OSCAR-2201 untuk langsung menggunakannya:

>>> from datasets import load_dataset
>>> data_files = {'train': 'path/to/OSCAR-2201/compressed/en_meta/*.jsonl.gz'}
>>> dataset = load_dataset('json', data_files=data_files, split='train', streaming=True)
>>> print(next(iter(dataset)))
{'id': 0, 'text': 'Founded in 2015, Golden Bees is a leading programmatic recruitment platform dedicated to employers, HR agencies and job boards. The company has developed unique HR-custom technologies and predictive algorithms to identify and attract the best candidates for a job opportunity.', ...

Parquet adalah format kolom yang memungkinkan Anda untuk streaming dan memuat hanya subset kolom serta mengabaikan kolom yang tidak diinginkan. Parquet juga menyimpan metadata seperti statistik kolom (pada level file dan grup baris), yang memungkinkan filtering yang efisien. Gunakan argumen columns dan filters dari datasets.packaged_modules.parquet.ParquetConfig untuk streaming dataset Parquet, memilih kolom, dan menerapkan filter:

>>> from datasets import load_dataset
>>> dataset = load_dataset('HuggingFaceFW/fineweb', split='train', streaming=True, columns=["url", "date"])
>>> print(next(iter(dataset)))
{'url': 'http://%20jwashington@ap.org/Content/Press-Release/2012/How-AP-reported-in-all-formats-from-tornado-stricken-regions', 'date': '2013-05-18T05:48:54Z'}
>>> dataset = load_dataset('HuggingFaceFW/fineweb', split='train', streaming=True, filters=[("language_score", ">=", 0.99)])
>>> print(next(iter(dataset)))
{'text': 'Everyone wishes for something. And lots of people believe they know how to make their wishes come true with magical thinking.\nWhat is it? "Magical thinking is a belief in forms of causation, with no known physical basis," said Professor Emily Pronin of Princeton...', ...,
 'language_score': 0.9900368452072144, 'token_count': 716}

Memuat dataset dalam mode streaming membuat instance tipe dataset baru (bukan objek Dataset klasik), yang dikenal sebagai IterableDataset. Tipe dataset khusus ini memiliki seperangkat metode pemrosesannya sendiri yang ditunjukkan di bawah ini.

IterableDataset berguna untuk tugas iteratif seperti pelatihan model. Anda sebaiknya tidak menggunakan IterableDataset untuk tugas yang memerlukan akses acak ke contoh, karena Anda harus mengiterasinya seluruhnya menggunakan for loop. Untuk mendapatkan contoh terakhir dalam dataset iterable, Anda harus mengiterasi semua contoh sebelumnya. Anda dapat menemukan detail lebih lanjut di panduan Dataset vs. IterableDataset.

Indeks kolom

Kadang-kadang, lebih praktis untuk mengiterasi nilai dari kolom tertentu. Untungnya, IterableDataset mendukung indeks kolom:

>>> from datasets import load_dataset
>>> dataset = load_dataset("allenai/c4", "en", streaming=True, split="train")
>>> print(next(iter(dataset["text"])))
Beginners BBQ Class Taking Place in Missoula!...

Mengonversi dari Dataset

Jika Anda memiliki objek Dataset yang sudah ada, Anda dapat mengonversinya menjadi IterableDataset dengan fungsi to_iterable_dataset(). Ini sebenarnya lebih cepat daripada mengatur argumen streaming=True di load_dataset() karena data dialirkan dari file lokal.

>>> from datasets import load_dataset

# faster 🐇
>>> dataset = load_dataset("ethz/food101")
>>> iterable_dataset = dataset.to_iterable_dataset()

# slower 🐢
>>> iterable_dataset = load_dataset("ethz/food101", streaming=True)

Fungsi to_iterable_dataset() mendukung sharding saat IterableDataset diinstansiasi. Hal ini berguna saat bekerja dengan dataset besar, dan Anda ingin mengacak dataset atau mengaktifkan pemuatan paralel yang cepat dengan PyTorch DataLoader.

>>> import torch
>>> from datasets import load_dataset

>>> dataset = load_dataset("ethz/food101")
>>> iterable_dataset = dataset.to_iterable_dataset(num_shards=64) # shard the dataset
>>> iterable_dataset = iterable_dataset.shuffle(buffer_size=10_000)  # shuffles the shards order and use a shuffle buffer when you start iterating
dataloader = torch.utils.data.DataLoader(iterable_dataset, num_workers=4)  # assigns 64 / 4 = 16 shards from the shuffled list of shards to each worker when you start iterating

Acak

Seperti objek Dataset biasa, Anda juga dapat mengacak IterableDataset dengan IterableDataset.shuffle().

Argumen buffer_size mengontrol ukuran buffer untuk mengambil contoh secara acak. Misalkan dataset Anda memiliki satu juta contoh, dan Anda mengatur buffer_size menjadi sepuluh ribu. IterableDataset.shuffle() akan memilih contoh secara acak dari sepuluh ribu contoh pertama di dalam buffer. Contoh yang dipilih di dalam buffer akan diganti dengan contoh baru. Secara default, ukuran buffer adalah 1.000.

>>> from datasets import load_dataset
>>> dataset = load_dataset('HuggingFaceFW/fineweb', split='train', streaming=True)
>>> shuffled_dataset = dataset.shuffle(seed=42, buffer_size=10_000)

IterableDataset.shuffle() mengisi buffer menggunakan hingga max_buffer_input_shards shard pada satu waktu (default adalah 10), yang sangat meningkatkan kualitas pengacakan. Metode ini juga mengacak urutan shard jika dataset dipecah menjadi beberapa file.

Jika Anda melakukan streaming dataset Parquet dengan hanya satu atau beberapa file, gunakan reshard() sebelum shuffling. Ini berguna untuk mem-shard dataset berdasarkan row group alih-alih berdasarkan file, sehingga meningkatkan kualitas shuffling.

Reshuffle

Kadang-kadang Anda mungkin ingin mengacak ulang dataset setelah setiap epoch. Hal ini mengharuskan Anda untuk menetapkan seed yang berbeda untuk setiap epoch. Gunakan IterableDataset.set_epoch() di antara epoch untuk memberi tahu dataset epoch mana yang sedang berjalan.

Seed Anda secara efektif menjadi: initial seed + current epoch.

>>> for epoch in range(epochs):
...     shuffled_dataset.set_epoch(epoch)
...     for example in shuffled_dataset:
...         ...

Bagi dataset

Anda dapat membagi dataset Anda dengan salah satu dari dua cara berikut:

>>> dataset = load_dataset('HuggingFaceFW/fineweb', split='train', streaming=True)
>>> dataset_head = dataset.take(2)
>>> list(dataset_head)
[{'text': "How AP reported in all formats from tor...},
 {'text': 'Did you know you have two little yellow...}]
>>> train_dataset = shuffled_dataset.skip(1000)

take dan skip mencegah panggilan shuffle di kemudian hari karena keduanya mengunci urutan shard. Anda sebaiknya shuffle dataset Anda sebelum membaginya.

Shard

🤗 Datasets mendukung sharding untuk membagi dataset yang sangat besar menjadi sejumlah chunk yang telah ditentukan. Tentukan jumlah shard untuk membagi dataset dengan menentukan parameter num_shards di shard(). Anda juga perlu menyediakan shard yang ingin dikembalikan dengan parameter index.

Sebagai contoh, dataset amazon_polarity memiliki 4 shard (dalam hal ini, 4 file Parquet):

>>> from datasets import load_dataset
>>> dataset = load_dataset("fancyzhx/amazon_polarity", split="train", streaming=True)
>>> print(dataset)
IterableDataset({
    features: ['label', 'title', 'content'],
    num_shards: 4
})

Setelah dataset dipecah menjadi dua bagian, bagian pertama hanya akan memiliki 2 shard:

>>> dataset.shard(num_shards=2, index=0)
IterableDataset({
    features: ['label', 'title', 'content'],
    num_shards: 2
})

Untuk meningkatkan jumlah shard dari dataset, Anda dapat menggunakan IterableDataset.reshard():

>>> dataset.reshard()
IterableDataset({
    features: ['label', 'title', 'content'],
    num_shards: 3600
})

Mekanisme resharding bergantung pada format file dataset. Sebagai contoh, untuk Parquet, resharding dilakukan menggunakan row group alih-alih memiliki satu file per shard. Lihat cara kerjanya untuk setiap format dalam dokumentasi IterableDataset.reshard().

Jika dataset Anda memiliki dataset.num_shards==1 bahkan setelah resharding, Anda harus membaginya menggunakan IterableDataset.skip() dan IterableDataset.take() sebagai gantinya.

Concatenate

Dataset yang terpisah dapat digabungkan jika mereka memiliki tipe kolom yang sama. Gabungkan dataset dengan concatenate_datasets():

>>> from datasets import concatenate_datasets, load_dataset

>>> stories = load_dataset("ajibawa-2023/General-Stories-Collection", split="train", streaming=True)
>>> stories = stories.select_columns(["text"])  # only keep the 'text' column
IterableDataset({
    features: Unknown,
    num_shards: 10
})

>>> wiki = load_dataset("wikimedia/wikipedia", "20231101.en", split="train", streaming=True)
>>> wiki = wiki.select_columns(["text"])  # only keep the 'text' column
IterableDataset({
    features: ['text'],
    num_shards: 41
})

>>> bert_dataset = concatenate_datasets([stories, wiki])
IterableDataset({
    features: ['text'],
    num_shards: 51
})

Shard dari dataset yang digabungkan adalah shard dari dataset input.

Anda juga dapat menggabungkan dua dataset secara horizontal dengan mengatur axis=1 selama kedua dataset memiliki jumlah baris yang sama:

>>> from datasets import IterableDataset
>>> stories_ids = IterableDataset.from_dict({"ids": list(range(num_stories))})
>>> stories_with_ids = concatenate_datasets([stories, stories_ids], axis=1)

Dalam kasus ini, dataset yang digabungkan hanya memiliki 1 shard, untuk menghindari shard yang tidak sejajar dari dataset input.

Interleave

interleave_datasets() dapat menggabungkan IterableDataset dengan dataset lain jika mereka memiliki tipe kolom yang sama. Dataset gabungan mengembalikan contoh secara bergantian dari masing-masing dataset asli.

>>> from datasets import interleave_datasets
>>> es_dataset = load_dataset('allenai/c4', 'es', split='train', streaming=True)
IterableDataset({
    features: Unknown,
    num_shards: 2048
})
>>> fr_dataset = load_dataset('allenai/c4', 'fr', split='train', streaming=True)
IterableDataset({
    features: Unknown,
    num_shards: 2048
})

>>> multilingual_dataset = interleave_datasets([es_dataset, fr_dataset])
IterableDataset({
    features: ['text', 'timestamp', 'url'],
    num_shards: 2048
})
>>> list(multilingual_dataset.take(2))
[{'text': 'Comprar Zapatillas para niña en chancla con goma por...'},
 {'text': 'Le sacre de philippe ier, 23 mai 1059 - Compte Rendu...'}]

Definisikan probabilitas sampling dari masing-masing dataset asli untuk kontrol lebih lanjut tentang bagaimana masing-masing dataset diambil sampelnya dan digabungkan. Atur argumen probabilities dengan probabilitas sampling yang Anda inginkan:

>>> multilingual_dataset_with_oversampling = interleave_datasets([es_dataset, fr_dataset], probabilities=[0.8, 0.2], seed=42)
>>> list(multilingual_dataset_with_oversampling.take(2))
[{'text': 'Comprar Zapatillas para niña en chancla con goma por...'},
 {'text': 'Chevrolet Cavalier Usados en Bogota - Carros en Vent...'}]

Sekitar 80% dari dataset akhir terdiri dari es_dataset, dan 20% dari fr_dataset.

Anda juga dapat menentukan stopping_strategy. Strategi default, first_exhausted, adalah strategi subsampling, yaitu konstruksi dataset dihentikan begitu salah satu dataset kehabisan sampel. Anda dapat menentukan stopping_strategy=all_exhausted untuk menjalankan strategi oversampling. Dalam kasus ini, konstruksi dataset dihentikan begitu setiap sampel di setiap dataset telah ditambahkan setidaknya sekali. Secara praktis, ini berarti jika sebuah dataset kehabisan sampel, dataset tersebut akan kembali ke awal hingga kriteria berhenti tercapai. Perhatikan bahwa jika probabilitas sampling tidak ditentukan, dataset baru akan memiliki max_length_datasets*nb_dataset samples. Tersedia juga stopping_strategy=all_exhausted_without_replacement untuk memastikan setiap sampel dilihat tepat satu kali.

Untuk memastikan paralelisme yang tepat menggunakan sharding, shard dari dataset yang diinterleaved mengandung setidaknya 1 shard dari setiap dataset input. Oleh karena itu, tingkat sharding dari dataset yang diinterleaved adalah tingkat sharding minimum dari dataset input.

Misalnya, jika dataset input masing-masing memiliki 32, 48, dan 128 shard, maka dataset yang diinterleaved memiliki 32 = min(32, 48, 128) shard, dan setiap shard baru memiliki 1 shard dari dataset pertama, 1-2 shard dari dataset kedua, dan 4 shard dari dataset ketiga.

Ganti nama, hapus, dan cast

Metode berikut memungkinkan Anda memodifikasi kolom dari sebuah dataset. Metode-metode ini berguna untuk mengganti nama atau menghapus kolom serta mengubah kolom menjadi set fitur baru.

Ganti nama

Gunakan IterableDataset.rename_column() ketika Anda perlu mengganti nama kolom dalam dataset Anda. Fitur yang terkait dengan kolom asli sebenarnya dipindahkan ke bawah nama kolom baru, bukan sekadar mengganti kolom asli di tempatnya.

Berikan IterableDataset.rename_column() dengan nama kolom asli, dan nama kolom baru:

>>> from datasets import load_dataset
>>> dataset = load_dataset('allenai/c4', 'en', streaming=True, split='train')
>>> dataset = dataset.rename_column("text", "content")

Hapus

Saat Anda perlu menghapus satu atau beberapa kolom, berikan IterableDataset.remove_columns() nama kolom yang akan dihapus. Hapus lebih dari satu kolom dengan menyediakan daftar nama kolom:

>>> from datasets import load_dataset
>>> dataset = load_dataset('allenai/c4', 'en', streaming=True, split='train')
>>> dataset = dataset.remove_columns('timestamp')

Cast

IterableDataset.cast() mengubah tipe fitur dari satu atau beberapa kolom. Metode ini mengambil Features baru Anda sebagai argumennya. Kode sampel berikut menunjukkan cara mengubah tipe fitur ClassLabel dan Value:

>>> from datasets import load_dataset
>>> dataset = load_dataset('nyu-mll/glue', 'mrpc', split='train', streaming=True)
>>> dataset.features
{'sentence1': Value('string'),
'sentence2': Value('string'),
'label': ClassLabel(names=['not_equivalent', 'equivalent']),
'idx': Value('int32')}

>>> from datasets import ClassLabel, Value
>>> new_features = dataset.features.copy()
>>> new_features["label"] = ClassLabel(names=['negative', 'positive'])
>>> new_features["idx"] = Value('int64')
>>> dataset = dataset.cast(new_features)
>>> dataset.features
{'sentence1': Value('string'),
'sentence2': Value('string'),
'label': ClassLabel(names=['negative', 'positive']),
'idx': Value('int64')}

Casting hanya berfungsi jika tipe fitur asli dan tipe fitur baru kompatibel. Misalnya, Anda dapat melakukan casting pada kolom dengan tipe fitur Value('int32') menjadi Value('bool') jika kolom asli hanya berisi angka satu dan nol.

Gunakan IterableDataset.cast_column() untuk mengubah tipe fitur dari satu kolom saja. Sampaikan nama kolom dan tipe fitur barunya sebagai argumen:

>>> dataset.features
{'audio': Audio(sampling_rate=44100, mono=True)}

>>> dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
>>> dataset.features
{'audio': Audio(sampling_rate=16000, mono=True)}

Peta

Mirip dengan fungsi Dataset.map() untuk Dataset biasa, 🤗 Datasets menyediakan IterableDataset.map() untuk memproses IterableDataset. IterableDataset.map() menerapkan pemrosesan secara langsung saat contoh di-streaming.

Fungsi ini memungkinkan Anda menerapkan fungsi pemrosesan pada setiap contoh dalam dataset, baik secara independen maupun dalam batch. Fungsi ini bahkan dapat membuat baris dan kolom baru.

Contoh berikut menunjukkan cara melakukan tokenisasi pada IterableDataset. Fungsi tersebut harus menerima dan mengoutputkan dict:

>>> def add_prefix(example):
...     example['text'] = 'My text: ' + example['text']
...     return example

Selanjutnya, terapkan fungsi ini ke dataset dengan IterableDataset.map():

>>> from datasets import load_dataset
>>> dataset = load_dataset('allenai/c4', 'en', streaming=True, split='train')
>>> updated_dataset = dataset.map(add_prefix)
>>> list(updated_dataset.take(3))
[{'text': 'My text: Beginners BBQ Class Taking Place in Missoula!\nDo you want to get better at making...',
  'timestamp': '2019-04-25 12:57:54',
  'url': 'https://klyq.com/beginners-bbq-class-taking-place-in-missoula/'},
 {'text': 'My text: Discussion in \'Mac OS X Lion (10.7)\' started by axboi87, Jan 20, 2012.\nI\'ve go...',
  'timestamp': '2019-04-21 10:07:13',
  'url': 'https://forums.macrumors.com/threads/restore-from-larger-disk-to-smaller-disk.1311329/'},
 {'text': 'My text: Foil plaid lycra and spandex shortall with metallic slinky insets. Attached metall...',
  'timestamp': '2019-04-25 10:40:23',
  'url': 'https://awishcometrue.com/Catalogs/Clearance/Tweens/V1960-Find-A-Way'}]

Mari kita lihat contoh lain, namun kali ini Anda akan menghapus kolom dengan IterableDataset.map(). Saat Anda menghapus kolom, kolom tersebut baru dihapus setelah contoh diberikan ke fungsi yang dipetakan. Hal ini memungkinkan fungsi yang dipetakan untuk menggunakan isi kolom sebelum kolom tersebut dihapus.

Tentukan kolom yang akan dihapus dengan argumen remove_columns di IterableDataset.map():

>>> updated_dataset = dataset.map(add_prefix, remove_columns=["timestamp", "url"])
>>> list(updated_dataset.take(3))
[{'text': 'My text: Beginners BBQ Class Taking Place in Missoula!\nDo you want to get better at making...'},
 {'text': 'My text: Discussion in \'Mac OS X Lion (10.7)\' started by axboi87, Jan 20, 2012.\nI\'ve go...'},
 {'text': 'My text: Foil plaid lycra and spandex shortall with metallic slinky insets. Attached metall...'}]

Pemrosesan batch

IterableDataset.map() juga mendukung pengoperasian pada batch contoh. Operasikan pada batch dengan mengatur batched=True. Ukuran batch default adalah 1000, tetapi Anda dapat menyesuaikannya dengan argumen batch_size. Hal ini membuka peluang untuk banyak aplikasi menarik seperti tokenisasi, pemecahan kalimat panjang menjadi potongan yang lebih pendek, dan augmentasi data.

Tokenisasi

>>> from datasets import load_dataset
>>> from transformers import AutoTokenizer
>>> dataset = load_dataset("allenai/c4", "en", streaming=True, split="train")
>>> tokenizer = AutoTokenizer.from_pretrained('distilbert-base-uncased')
>>> def encode(examples):
...     return tokenizer(examples['text'], truncation=True, padding='max_length')
>>> dataset = dataset.map(encode, batched=True, remove_columns=["text", "timestamp", "url"])
>>> next(iter(dataset))
{'input_ids': [101, 4088, 16912, 22861, 4160, 2465, 2635, 2173, 1999, 3335, ..., 0, 0, 0],
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ..., 0, 0]}

Lihat contoh lain pemrosesan batch dalam dokumentasi batched map processing. Cara kerjanya sama untuk dataset iterable.

Filter

Anda dapat menyaring baris dalam dataset berdasarkan fungsi predikat menggunakan Dataset.filter(). Fungsi ini mengembalikan baris yang memenuhi kondisi tertentu:

>>> from datasets import load_dataset
>>> dataset = load_dataset('HuggingFaceFW/fineweb', streaming=True, split='train')
>>> start_with_ar = dataset.filter(lambda example: example['text'].startswith('San Francisco'))
>>> next(iter(start_with_ar))
{'text': 'San Francisco 49ers cornerback Shawntae Spencer will miss the rest of the sea...}

Dataset.filter() juga dapat memfilter berdasarkan indeks jika Anda mengatur with_indices=True:

>>> even_dataset = dataset.filter(lambda example, idx: idx % 2 == 0, with_indices=True)
>>> list(even_dataset.take(3))
[{'text': 'How AP reported in all formats from tornado-stricken regionsMarch 8, 2012 Whe...},
 {'text': 'Car Wash For Clara! Now is your chance to help! 2 year old Clara Woodward has...},
 {'text': 'Log In Please enter your ECode to log in. Forgotten your eCode? If you create...}]

Batch

Metode batch mengubah IterableDataset Anda menjadi iterable dari batch. Hal ini sangat berguna ketika Anda ingin bekerja dengan batch dalam loop pelatihan Anda atau ketika menggunakan framework yang mengharapkan input yang di-batch.

Ada juga opsi “Batch Processing” saat menggunakan fungsi map untuk menerapkan fungsi pada batch data, yang dibahas di bagian Map di atas. Metode batch yang dijelaskan di sini berbeda dan menyediakan cara yang lebih langsung untuk membuat batch dari dataset Anda.

Anda dapat menggunakan metode batch seperti ini:

from datasets import load_dataset

# Load a dataset in streaming mode
dataset = load_dataset("some_dataset", split="train", streaming=True)

# Create batches of 32 samples
batched_dataset = dataset.batch(batch_size=32)

# Iterate over the batched dataset
for batch in batched_dataset:
    print(batch)
    break

Pada contoh ini, batched_dataset masih merupakan IterableDataset, tetapi setiap item yang dihasilkan sekarang berupa batch berisi 32 sampel, bukan satu sampel tunggal. Pengelompokan batch ini dilakukan secara langsung saat Anda mengiterasi dataset, sehingga mempertahankan sifat hemat memori dari IterableDataset.

Metode batch juga menyediakan parameter drop_last_batch. Ketika diset ke True, parameter ini akan membuang batch terakhir jika ukurannya lebih kecil dari batch_size yang ditentukan. Hal ini dapat berguna dalam skenario di mana pemrosesan hilir Anda membutuhkan semua batch berukuran sama:

batched_dataset = dataset.batch(batch_size=32, drop_last_batch=True)

Stream dalam loop pelatihan

IterableDataset dapat diintegrasikan ke dalam loop pelatihan. Pertama, acak dataset:

Pytorch
Hide Pytorch content
>>> seed, buffer_size = 42, 10_000
>>> dataset = dataset.shuffle(seed, buffer_size=buffer_size)

Terakhir, buat loop pelatihan sederhana dan mulai pelatihan:

>>> import torch
>>> from torch.utils.data import DataLoader
>>> from transformers import AutoModelForMaskedLM, DataCollatorForLanguageModeling
>>> from tqdm import tqdm
>>> dataset = dataset.with_format("torch")
>>> dataloader = DataLoader(dataset, collate_fn=DataCollatorForLanguageModeling(tokenizer))
>>> device = 'cuda' if torch.cuda.is_available() else 'cpu' 
>>> model = AutoModelForMaskedLM.from_pretrained("distilbert-base-uncased")
>>> model.train().to(device)
>>> optimizer = torch.optim.AdamW(params=model.parameters(), lr=1e-5)
>>> for epoch in range(3):
...     dataset.set_epoch(epoch)
...     for i, batch in enumerate(tqdm(dataloader, total=5)):
...         if i == 5:
...             break
...         batch = {k: v.to(device) for k, v in batch.items()}
...         outputs = model(**batch)
...         loss = outputs[0]
...         loss.backward()
...         optimizer.step()
...         optimizer.zero_grad()
...         if i % 10 == 0:
...             print(f"loss: {loss}")

Simpan checkpoint dataset dan lanjutkan iterasi

Jika loop pelatihan Anda berhenti, Anda mungkin ingin memulai ulang pelatihan dari titik di mana ia berhenti. Untuk melakukannya, Anda dapat menyimpan checkpoint model dan optimizer Anda, serta data loader Anda.

Dataset iterable tidak menyediakan akses acak ke indeks contoh tertentu untuk melanjutkan dari sana, tetapi Anda dapat menggunakan IterableDataset.state_dict() dan IterableDataset.load_state_dict() untuk melanjutkan dari checkpoint, serupa dengan yang dapat Anda lakukan untuk model dan optimizer:

>>> iterable_dataset = Dataset.from_dict({"a": range(6)}).to_iterable_dataset(num_shards=3)
>>> for idx, example in enumerate(iterable_dataset):
...     print(example)
...     if idx == 2:
...         state_dict = iterable_dataset.state_dict()
...         print("checkpoint")
...         break
>>> iterable_dataset.load_state_dict(state_dict)
>>> print(f"restart from checkpoint")
>>> for example in iterable_dataset:
...     print(example)

Mengembalikan:

{'a': 0}
{'a': 1}
{'a': 2}
checkpoint
restart from checkpoint
{'a': 3}
{'a': 4}
{'a': 5}

Di balik layar, dataset iterable melacak shard saat ini yang sedang dibaca dan indeks contoh di shard saat ini, lalu menyimpan informasi ini di state_dict.

Untuk melanjutkan dari checkpoint, dataset melewati semua shard yang sebelumnya dibaca untuk memulai ulang dari shard saat ini. Kemudian, dataset membaca shard tersebut dan melewati contoh-contoh hingga mencapai contoh yang tepat dari checkpoint.

Oleh karena itu, memulai ulang dataset cukup cepat karena tidak akan membaca ulang shard yang sudah diiterasi. Namun, melanjutkan dataset umumnya tidak instan karena harus memulai ulang pembacaan dari awal shard saat ini dan melewati contoh-contoh hingga mencapai lokasi checkpoint.

Hal ini dapat digunakan dengan StatefulDataLoader dari torchdata:

>>> from torchdata.stateful_dataloader import StatefulDataLoader
>>> iterable_dataset = load_dataset("deepmind/code_contests", streaming=True, split="train")
>>> dataloader = StatefulDataLoader(iterable_dataset, batch_size=32, num_workers=4)
>>> # checkpoint
>>> state_dict = dataloader.state_dict()  # uses iterable_dataset.state_dict() under the hood
>>> # resume from checkpoint
>>> dataloader.load_state_dict(state_dict)  # uses iterable_dataset.load_state_dict() under the hood

Resuming mengembalikan proses tepat dari titik checkpoint yang disimpan, kecuali jika .shuffle() digunakan: contoh dari buffer shuffle akan hilang saat resuming dan buffer diisi ulang dengan data baru.

Simpan

Setelah dataset iterable Anda siap, Anda dapat menyimpannya sebagai Dataset Hugging Face dalam format Parquet dan menggunakannya kembali nanti dengan load_dataset().

Simpan dataset Anda dengan memberikan nama repositori dataset di Hugging Face yang ingin Anda tuju sebagai argumen untuk push_to_hub(). Ini akan mengiterasi dataset dan secara progresif mengunggah data ke Hugging Face:

dataset.push_to_hub("username/my_dataset")

Secara default, IterableDataset.push_to_hub() menulis dataset.num_shards file. Atur num_shards untuk memilih jumlah yang berbeda. Dengan jumlah shard output yang lebih banyak dari dataset.num_shards, setiap shard input disebar ke grup shard output-nya sendiri dengan menulis contoh-contohnya secara bergiliran (round-robin), dalam satu kali iterasi data. Jika jumlah contoh lebih sedikit dari shard yang diminta, shard yang tersisa akan berupa file Parquet kosong.

Jika dataset terdiri dari beberapa shard (dataset.num_shards > 1), Anda dapat menggunakan beberapa proses untuk mengunggahnya secara paralel. Hal ini sangat berguna jika Anda menerapkan langkah map() atau filter() karena langkah-langkah tersebut akan berjalan lebih cepat secara paralel:

dataset.push_to_hub("username/my_dataset", num_proc=8)

Gunakan fungsi load_dataset() untuk memuat ulang dataset:

from datasets import load_dataset
reloaded_dataset = load_dataset("username/my_dataset")

Ekspor

🤗 Datasets mendukung ekspor sehingga Anda dapat bekerja dengan dataset Anda di aplikasi lain. Tabel berikut menunjukkan format file yang saat ini didukung untuk diekspor:

Jenis fileMetode ekspor
CSVIterableDataset.to_csv()
JSONIterableDataset.to_json()
ParquetIterableDataset.to_parquet()
SQLIterableDataset.to_sql()
Objek Python di memoriIterableDataset.to_pandas(), IterableDataset.to_polars() or IterableDataset.to_dict()

Sebagai contoh, ekspor dataset Anda ke file CSV seperti ini:

>>> dataset.to_csv("path/of/my/dataset.csv")

Jika Anda memiliki dataset besar, Anda dapat menyimpan satu file per shard, misalnya

>>> num_shards = dataset.num_shards
>>> for index in range(num_shards):
...     shard = dataset.shard(index, num_shards)
...     shard.to_parquet(f"path/of/my/dataset/data-{index:05d}.parquet")
Update on GitHub