Datasets documentation

بث

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v4.8.4).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

بث

يتيح لك بثّ مجموعة البيانات العمل معها دون الحاجة إلى تنزيلها. يتم بثّ البيانات أثناء تكرارك على عناصر مجموعة البيانات. وهذا مفيد بشكل خاص عندما:

  • لا تريد الانتظار حتى يتم تنزيل مجموعة بيانات ضخمة للغاية.
  • يتجاوز حجم مجموعة البيانات مساحة القرص المتاحة على جهازك.
  • تريد استكشاف عدد قليل من العينات في مجموعة بيانات بسرعة.

على سبيل المثال، حجم الجزء الإنجليزي من مجموعة بيانات HuggingFaceFW/fineweb يبلغ 45 تيرابايت، لكن يمكنك استخدامه فورًا عبر البث. قم ببث مجموعة البيانات عن طريق تعيين streaming=True في load_dataset() كما هو موضح أدناه:

>>> 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}

يتيح لك بثّ مجموعة البيانات أيضًا العمل مع مجموعة بيانات مكوّنة من ملفات محلية دون الحاجة إلى أي تحويل. في هذه الحالة، يتم بثّ البيانات من الملفات المحلية أثناء تكرار التكرار على مجموعة البيانات. وهذا مفيد بشكل خاص عندما:

  • لا تريد الانتظار حتى يتم تحويل مجموعة بيانات محلية ضخمة جداً إلى صيغة Arrow.
  • ستتجاوز مساحة الملفات المحوّلة حجم مساحة القرص المتاحة على جهازك.
  • تريد استكشاف عدد قليل من العينات في مجموعة بيانات بسرعة.
  • تريد تحميل أعمدة معينة فقط أو تصفية مجموعة بيانات Parquet بكفاءة.

على سبيل المثال، يمكنك بث مجموعة بيانات محلية تتكون من مئات ملفات JSONL المضغوطة مثل oscar-corpus/OSCAR-2201 لاستخدامها فورًا:

>>> 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 هو تنسيق أعمدة يتيح لك بثّ وتحميل مجموعة فرعية من الأعمدة فقط وتجاهل الأعمدة غير المرغوب فيها. كما يخزّن Parquet بيانات وصفية مثل إحصاءات الأعمدة (على مستوى الملف ومجموعة الصفوف)، مما يتيح تصفيةً فعّالة. استخدم حججي columns وfilters في datasets.packaged_modules.parquet.ParquetConfig لبثّ مجموعات بيانات Parquet واختيار الأعمدة وتطبيق عوامل التصفية:

>>> 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}

إنشاء مجموعة بيانات في وضع البث (streaming) ينشئ كائنًا من نوع مجموعة بيانات جديد (بدلًا من كائن Dataset الكلاسيكي)، يُعرف باسم IterableDataset. يتميز هذا النوع الخاص من مجموعات البيانات بمجموعة من طرق المعالجة الخاصة به، وهي موضحة أدناه.

يُعدّ IterableDataset مفيدًا للمهام التكرارية مثل تدريب نموذج. لا ينبغي استخدام IterableDataset للمهام التي تتطلب وصولاً عشوائيًا إلى الأمثلة، لأنك مضطر لتكرارها بالكامل باستخدام حلقة for. فالحصول على المثال الأخير في مجموعة بيانات قابلة للتكرار سيتطلب منك المرور على جميع الأمثلة السابقة. يمكنك العثور على مزيد من التفاصيل في دليل Dataset مقابل IterableDataset.

فهرسة الأعمدة

في بعض الأحيان يكون من المفيد التكرار على قيم عمود محدد. لحسن الحظ، يدعم IterableDataset فهرسة الأعمدة:

>>> 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!...

التحويل من Dataset

إذا كان لديك كائن Dataset موجود مسبقًا، يمكنك تحويله إلى IterableDataset باستخدام الدالة to_iterable_dataset(). وهذا في الواقع أسرع من تعيين معامل streaming=True في load_dataset() لأن البيانات تُبث من ملفات محلية.

>>> 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)

تدعم الدالة to_iterable_dataset() تقسيم البيانات (sharding) عند إنشاء IterableDataset. وهذا مفيد عند العمل مع مجموعات بيانات كبيرة، حيث ترغب في خلط البيانات أو تمكين التحميل المتوازي السريع باستخدام 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

خلط

كما هو الحال مع كائن Dataset العادي، يمكنك أيضًا خلط IterableDataset باستخدام IterableDataset.shuffle().

يتحكم الحجة buffer_size في حجم المخزن المؤقت الذي تُسحب منه الأمثلة عشوائياً. لنفترض أن مجموعة بياناتك تحتوي على مليون مثال، وقد قمت بتعيين buffer_size إلى عشرة آلاف. سيقوم IterableDataset.shuffle() باختيار أمثلة عشوائياً من أول عشرة آلاف مثال في المخزن المؤقت. تُستبدل الأمثلة المختارة في المخزن المؤقت بأمثلة جديدة. افتراضياً، يكون حجم المخزن المؤقت 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() باستخدام ما يصل إلى max_buffer_input_shards من الشرائح في كل مرة (الافتراضي هو 10)، مما يحسّن بشكل كبير من جودة الخلط. كما يقوم بخلط ترتيب الشرائح إذا كان مجموعة البيانات مقسمة إلى ملفات متعددة.

إذا كنت تبث مجموعة بيانات Parquet تحتوي على ملف واحد أو عدد قليل من الملفات، فاستخدم reshard() قبل الخلط. وهذا مفيد لتقسيم مجموعة البيانات حسب مجموعة الصفوف بدلاً من تقسيمها حسب الملف، مما يحسّن جودة الخلط.

إعادة الترتيب

قد ترغب أحيانًا في إعادة خلط مجموعة البيانات بعد كل حقبة. سيتطلب ذلك منك تعيين بذرة مختلفة لكل حقبة. استخدم IterableDataset.set_epoch() بين الحقب لإبلاغ مجموعة البيانات بالحقبة التي أنت عليها.

تصبح البذرة الخاصة بك بشكل فعال: initial seed + current epoch.

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

تقسيم مجموعة البيانات

يمكنك تقسيم مجموعة البيانات بطريقتين:

>>> 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...}]
  • يتجاهل IterableDataset.skip() أول n أمثلة في مجموعة البيانات ويعيد الأمثلة المتبقية:
>>> train_dataset = shuffled_dataset.skip(1000)

take وskip تمنعان الاستدعاءات المستقبلية لـshuffle لأنها تُثبّت ترتيب الشرائح. يجب عليك shuffle مجموعة البيانات قبل تقسيمها.

شريحة

🤗 يدعم Datasets التقسيم إلى شرائح (sharding) لتقسيم مجموعة بيانات كبيرة جدًا إلى عدد محدد مسبقًا من المقاطع. حدد معامل num_shards في shard() لتحديد عدد الشرائح التي سيتم تقسيم مجموعة البيانات إليها. كما ستحتاج إلى تحديد الشريحة التي تريد إرجاعها باستخدام معامل index.

على سبيل المثال، يحتوي مجموعة بيانات amazon_polarity على 4 أجزاء (في هذه الحالة، هي 4 ملفات 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
})

بعد تقسيم مجموعة البيانات إلى مقطعين، لن يحتوي المقطع الأول على سوى شريحتين:

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

لزيادة عدد أجزاء مجموعة البيانات، يمكنك استخدام IterableDataset.reshard():

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

يعتمد آلية إعادة التقسيم على صيغة ملف مجموعة البيانات. فعلى سبيل المثال، في حالة Parquet، يتم إعادة التقسيم باستخدام مجموعات الصفوف بدلاً من وجود ملف واحد لكل شريحة. راجع كيفية عملها لكل صيغة في توثيق IterableDataset.reshard().

إذا كان dataset.num_shards==1 حتى بعد إعادة التقسيم، فيجب عليك تقسيمه باستخدام IterableDataset.skip() و IterableDataset.take() بدلاً من ذلك.

دمج

يمكن دمج مجموعات البيانات المنفصلة إذا كانت تشترك في نفس أنواع الأعمدة. قم بدمج مجموعات البيانات باستخدام 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
})

شرائح مجموعة البيانات المدمجة هي شرائح مجموعات البيانات المدخلة.

يمكنك أيضًا دمج مجموعتي بيانات أفقيًا عن طريق تعيين axis=1 طالما أن المجموعتين تحتويان على نفس عدد الصفوف:

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

في هذه الحالة، يحتوي مجموعة البيانات المدمجة على شريحة واحدة فقط، لتجنب الانتهاء بشرائح غير محاذاة من مجموعات البيانات المدخلة.

تبادل

يمكن لـ interleave_datasets() دمج IterableDataset مع مجموعات بيانات أخرى إذا كانت أنواع الأعمدة متطابقة. تُرجع مجموعة البيانات المدمجة أمثلة متناوبة من كل مجموعة بيانات أصلية.

>>> 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...'}]

حدّد احتمالات العينة من كلٍّ من مجموعات البيانات الأصلية للحصول على مزيد من التحكم في كيفية أخذ العينات منها ودمجها. اضبط الحجة probabilities بالاحتمالات المرغوبة لأخذ العينات:

>>> 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...'}]

يتكوّن حوالي 80% من مجموعة البيانات النهائية من es_dataset، و20% من fr_dataset.

يمكنك أيضًا تحديد stopping_strategy. الاستراتيجية الافتراضية، first_exhausted، هي استراتيجية أخذ عينات فرعية، أي أن بناء مجموعة البيانات يتوقف بمجرد نفاد العينات من إحدى مجموعات البيانات. يمكنك تحديد stopping_strategy=all_exhausted لتنفيذ استراتيجية أخذ عينات زائدة. في هذه الحالة، يتوقف بناء مجموعة البيانات بمجرد إضافة كل عينة في كل مجموعة بيانات مرة واحدة على الأقل. عمليًا، يعني ذلك أنه إذا نفدت مجموعة بيانات، فستعود إلى بداية هذه المجموعة حتى يتم تحقيق معيار التوقف. لاحظ أنه إذا لم يتم تحديد احتمالات أخذ العينات، فستحتوي مجموعة البيانات الجديدة على max_length_datasets*nb_dataset samples. يوجد أيضًا stopping_strategy=all_exhausted_without_replacement للتأكد من أن كل عينة تُرى مرة واحدة بالضبط.

لضمان التوازي الصحيح باستخدام التقسيم، تحتوي شُعب مجموعة البيانات المتشابكة على شعبة واحدة على الأقل من كل مجموعة بيانات إدخال. وبالتالي، فإن مستوى التقسيم لمجموعة البيانات المتشابكة هو أدنى مستوى تقسيم بين مجموعات البيانات المدخلة.

على سبيل المثال، إذا كانت مجموعات البيانات المدخلة تحتوي على 32 و48 و128 شريحة على التوالي، فإن مجموعة البيانات المتداخلة تحتوي على 32 = min(32, 48, 128) شريحة، وتحتوي كل شريحة جديدة على شريحة واحدة من مجموعة البيانات الأولى، وشريحتين من مجموعة البيانات الثانية، وأربع شرائح من مجموعة البيانات الثالثة.

إعادة التسمية، الإزالة، والتحويل

تتيح لك الطرق التالية تعديل أعمدة مجموعة البيانات. وتُعدّ هذه الطرق مفيدة لإعادة تسمية الأعمدة أو حذفها، وتغيير الأعمدة إلى مجموعة جديدة من الميزات.

إعادة تسمية

استخدم IterableDataset.rename_column() عندما تحتاج إلى إعادة تسمية عمود في مجموعة البيانات الخاصة بك. يتم نقل الميزات المرتبطة بالعمود الأصلي فعليًا تحت اسم العمود الجديد، بدلاً من مجرد استبدال العمود الأصلي في مكانه.

قدّم IterableDataset.rename_column() باسم العمود الأصلي واسم العمود الجديد:

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

إزالة

عندما تحتاج إلى إزالة عمود واحد أو أكثر، قم بتزويد IterableDataset.remove_columns() باسم العمود المراد إزالته. لإزالة أكثر من عمود، قم بتوفير قائمة بأسماء الأعمدة:

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

إسناد

يُغيّر IterableDataset.cast() نوع الميزة لأحد الأعمدة أو أكثر. يتلقى هذا الدالة Features الجديدة الخاصة بك كحجة. يُظهر المثال التالي من الكود كيفية تغيير أنواع الميزات الخاصة بـ ClassLabel و 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')}

لا يعمل التحويل إلا إذا كان نوع الميزة الأصلي ونوع الميزة الجديد متوافقين. على سبيل المثال، يمكنك تحويل عمود بنوع ميزة Value('int32') إلى Value('bool') إذا كان العمود الأصلي يحتوي فقط على أرقام واحد وصفر.

استخدم IterableDataset.cast_column() لتغيير نوع الميزة لعمود واحد فقط. مرر اسم العمود ونوع ميزته الجديد كحججين:

>>> 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)}

خريطة

على غرار دالة Dataset.map() الخاصة بـ Dataset العادي، تتميز مكتبة 🤗 Datasets بدالة IterableDataset.map() لمعالجة IterableDataset. تطبّق IterableDataset.map() المعالجة على الفور أثناء بثّ الأمثلة.

يتيح لك تطبيق دالة معالجة على كل مثال في مجموعة البيانات، بشكل مستقل أو على شكل دفعات. ويمكن لهذه الدالة حتى إنشاء صفوف وأعمدة جديدة.

يوضح المثال التالي كيفية ترميز IterableDataset. يجب أن تستقبل الدالة dict وتُخرجه:

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

بعد ذلك، طبّق هذه الدالة على مجموعة البيانات باستخدام 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'}]

لنلقِ نظرة على مثال آخر، لكن هذه المرة ستقوم بإزالة الأعمدة باستخدام IterableDataset.map(). عند إزالة عمود، لا يتم إزالته إلا بعد أن يُقدَّم المثال إلى الدالة المُرسَلة. وهذا يتيح للدالة المُرسَلة استخدام محتوى الأعمدة قبل إزالتها.

حدد العمود الذي تريد إزالته باستخدام الحجة remove_columns في 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...'}]

المعالجة الدفعية

يدعم IterableDataset.map() أيضًا العمل مع دفعات من الأمثلة. للتعامل مع الدفعات، اضبط batched=True. حجم الدفعة الافتراضي هو 1000، لكن يمكنك ضبطه باستخدام الحجة batch_size. وهذا يفتح الباب أمام العديد من التطبيقات المثيرة للاهتمام مثل الترميز، وتقسيم الجمل الطويلة إلى مقاطع أقصر، وتوسيع البيانات.

التجزئة

>>> 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]}

راجع أمثلة أخرى لمعالجة الدفعات في وثائق معالجة الخريطة الدفعية. تعمل بنفس الطريقة مع مجموعات البيانات القابلة للتكرار.

تصفية

يمكنك تصفية الصفوف في مجموعة البيانات بناءً على دالة شرطية باستخدام Dataset.filter(). تُرجع هذه الدالة الصفوف التي تطابق شرطًا محددًا:

>>> 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() أيضًا التصفية حسب الفهارس إذا قمت بإعداد 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 مجموعة البيانات القابلة للتكرار IterableDataset إلى سلسلة قابلة للتكرار من الدفعات. وهذا مفيد بشكل خاص عندما تريد العمل مع الدفعات في حلقة التدريب الخاصة بك أو عند استخدام أطر عمل تتوقع مدخلات على شكل دفعات.

يوجد أيضاً خيار “معالجة الدُفعات” عند استخدام دالة map لتطبيق دالة على دفعات من البيانات، وهو ما تم تناوله في قسم Map أعلاه. الطريقة batch الموصوفة هنا مختلفة وتوفر طريقة أكثر مباشرة لإنشاء دفعات من مجموعة البيانات الخاصة بك.

يمكنك استخدام طريقة batch على النحو التالي:

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

في هذا المثال، لا يزال batched_dataset من نوع IterableDataset، لكن كل عنصر يُنتج الآن هو دفعة من 32 عينة بدلاً من عينة واحدة. يتم تنفيذ هذا التقسيم إلى دفعات على الفور أثناء التكرار على مجموعة البيانات، مما يحافظ على الطبيعة الموفرة للذاكرة الخاصة بـ IterableDataset.

توفر طريقة الدفعة (batch) أيضًا معاملًا باسم drop_last_batch. عند ضبطه على True، سيتم تجاهل آخر دفعة إذا كانت أصغر من حجم الدفعة المحدد batch_size. يمكن أن يكون ذلك مفيدًا في السيناريوهات التي تتطلب فيها المعالجة اللاحقة أن تكون جميع الدفعات بنفس الحجم:

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

البث في حلقة التدريب

يمكن دمج IterableDataset في حلقة التدريب. أولاً، قم بإعادة ترتيب مجموعة البيانات:

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

أخيرًا، أنشئ حلقة تدريب بسيطة وابدأ التدريب:

>>> 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}")

حفظ نقطة تفتيش للبيانات واستئناف التكرار

إذا توقف حلقة التدريب، فقد ترغب في إعادة بدء التدريب من حيث توقف. للقيام بذلك، يمكنك حفظ نقطة تفتيش لنموذجك ومُحسِّناتك، وكذلك مُحمِّل البيانات الخاص بك.

لا توفر مجموعات البيانات القابلة للتكرار وصولاً عشوائياً إلى فهرس مثال محدد للمتابعة منه، لكن يمكنك استخدام IterableDataset.state_dict() و IterableDataset.load_state_dict() للمتابعة من نقطة تفتيش بدلاً من ذلك، على غرار ما يمكنك فعله بالنسبة للنماذج والمُحسِّنات:

>>> 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)

يعيد:

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

في الخلفية، يحافظ مجموعة البيانات القابلة للتكرار على تتبع الشريحة الحالية التي يتم قراءتها وفهرس المثال داخل الشريحة الحالية، ويخزّن هذه المعلومات في state_dict.

للاستئناف من نقطة تفتيش، يتخطى مجموعة البيانات جميع الشرائح التي تم قراءتها سابقًا لإعادة البدء من الشريحة الحالية. ثم يقرأ الشريحة ويتخطى الأمثلة حتى يصل إلى المثال الدقيق من نقطة التفتيش.

لذلك، فإن إعادة تشغيل مجموعة البيانات سريع إلى حد كبير، إذ لن تعيد قراءة الشرائح التي تم المرور عليها بالفعل. ومع ذلك، فإن استئناف مجموعة البيانات ليس فوريًا بشكل عام، إذ يجب أن يعيد القراءة من بداية الشريحة الحالية ويتخطى الأمثلة حتى يصل إلى موقع نقطة التفتيش.

يمكن استخدام ذلك مع StatefulDataLoader من 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

يعود الاستئناف إلى النقطة التي تم فيها حفظ نقطة التفتيش بالضبط، باستثناء استخدام .shuffle(): حيث تُفقد الأمثلة من مخازن الخلط عند الاستئناف، وتُعاد تعبئة المخازن ببيانات جديدة.

حفظ

بمجرد أن يصبح مجموعة البيانات القابلة للتكرار جاهزة، يمكنك حفظها كمجموعة بيانات Hugging Face بتنسيق Parquet وإعادة استخدامها لاحقًا باستخدام load_dataset().

احفظ مجموعة البيانات الخاصة بك من خلال تقديم اسم مستودع مجموعة البيانات على Hugging Face الذي ترغب في حفظها فيه كحجة لـ push_to_hub(). يقوم هذا بالتكرار على مجموعة البيانات ورفع البيانات تدريجياً إلى Hugging Face:

dataset.push_to_hub("username/my_dataset")

بشكل افتراضي، يكتب IterableDataset.push_to_hub() عددًا من الملفات يساوي dataset.num_shards. اضبط num_shards لاختيار عدد مختلف. عند وجود عدد أكبر من الشرائح الإخراجية من dataset.num_shards، يتم توزيع كل شريحة إدخال على مجموعة خاصة بها من الشرائح الإخراجية عن طريق كتابة أمثلتها إليها بطريقة الدوران (round-robin)، في مرور واحد على البيانات. إذا كان عدد الأمثلة أقل من عدد الشرائح المطلوبة، فإن الشرائح المتبقية تكون ملفات Parquet فارغة.

إذا كان مجموعة البيانات تتكون من عدة أجزاء (dataset.num_shards > 1)، يمكنك استخدام عمليات متعددة لرفعها بالتوازي. وهذا مفيد بشكل خاص إذا طبّقت خطوات map() أو filter() لأنها ستعمل بشكل أسرع بالتوازي:

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

استخدم دالة load_dataset() لإعادة تحميل مجموعة البيانات:

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

تصدير

🤗 يدعم Datasets التصدير أيضًا، مما يتيح لك العمل بمجموعتك من البيانات في تطبيقات أخرى. تُظهر الجدول التالي صيغ الملفات المدعومة حاليًا التي يمكنك التصدير إليها:

نوع الملفطريقة التصدير
CSVIterableDataset.to_csv()
JSONIterableDataset.to_json()
ParquetIterableDataset.to_parquet()
SQLIterableDataset.to_sql()
كائن بايثون في الذاكرةIterableDataset.to_pandas(), IterableDataset.to_polars() or IterableDataset.to_dict()

على سبيل المثال، قم بتصدير مجموعة البيانات الخاصة بك إلى ملف CSV على النحو التالي:

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

إذا كان لديك مجموعة بيانات كبيرة، يمكنك حفظ ملف واحد لكل شريحة، على سبيل المثال

>>> 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