Datasets documentation

Süreç

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

Süreç

🤗 Datasets, bir veri setinin yapısını ve içeriğini değiştirmek için birçok araç sunar. Bu araçlar, bir veri setini düzenlemek, ek sütunlar oluşturmak, özellikler ve biçimler arasında dönüştürme yapmak ve daha fazlası için önemlidir.

Bu kılavuz size şunları gösterecektir:

  • Satırları yeniden sıralayın ve veri setini bölün.
  • Sütunları yeniden adlandırma ve silme gibi diğer yaygın sütun işlemleri.
  • Bir veri setindeki her örneğe işlevsel işlemleri uygulayın.
  • Veri kümelerini birleştirin.
  • Özel bir biçimlendirme dönüşümü uygulayın.
  • İşlenmiş veri setlerini kaydedin ve dışa aktarın.

Diğer veri seti modalitelerinin işlenmesine özgü daha fazla ayrıntı için ses veri seti işleme kılavuzuna, görsel veri seti işleme kılavuzuna veya metin veri seti işleme kılavuzuna göz atın.

Bu kılavuzdaki örnekler MRPC veri setini kullanır, ancak istediğiniz herhangi bir veri setini yükleyip adımları takip etmekte serbestsiniz!

>>> from datasets import load_dataset
>>> dataset = load_dataset("nyu-mll/glue", "mrpc", split="train")

Bu kılavuzdaki tüm işleme yöntemleri yeni bir Dataset nesnesi döndürür. Değişiklikler yerinde (in-place) yapılmaz. Önceki veri setinizin üzerine yazmamaya dikkat edin!

Sıralama, karıştırma, seçme, bölme ve parçalama

Bir veri setinin yapısını yeniden düzenlemek için birkaç işlev bulunmaktadır. Bu işlevler, yalnızca istediğiniz satırları seçmek, eğitim ve test bölümleri oluşturmak ve çok büyük veri setlerini daha küçük parçalara ayırmak için kullanışlıdır.

Sırala

Sütun değerlerini sayısal değerlerine göre sıralamak için sort() kullanın. Sağlanan sütun NumPy ile uyumlu olmalıdır.

>>> dataset["label"][:10]
[1, 0, 1, 0, 1, 1, 0, 1, 0, 0]
>>> sorted_dataset = dataset.sort("label")
>>> sorted_dataset["label"][:10]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> sorted_dataset["label"][-10:]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Arka planda, bu, sütunun değerlerine göre sıralanmış bir indeks listesi oluşturur. Bu indeks eşlemesi, ardından alttaki Arrow tablosundaki doğru satırlara erişmek için kullanılır.

Karıştır

shuffle() fonksiyonu sütun değerlerini rastgele yeniden sıralar. Veri setini karıştırma algoritması üzerinde daha fazla kontrol istiyorsanız, bu fonksiyonda generator parametresini belirleyerek farklı bir numpy.random.Generator kullanabilirsiniz.

>>> shuffled_dataset = sorted_dataset.shuffle(seed=42)
>>> shuffled_dataset["label"][:10]
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0]

Shuffling, [0:len(my_dataset)] dizisini karıştırarak bir indeks eşlemesi oluşturur. Ancak Dataset nesnenizde bir indeks eşlemesi olduğu anda hız 10 kat yavaşlayabilir. Bunun nedeni, indeks eşlemesini kullanarak okunacak satır indeksini almak için ek bir adımın olması ve en önemlisi, artık veriye ardışık parçalar halinde erişilmemesidir. Hızı geri kazanmak için, indeks eşlemesini kaldıran Dataset.flatten_indices() ile tüm veri setini diskinize yeniden yazmanız gerekir. Alternatif olarak, IterableDataset kullanmaya geçebilir ve hızlı yaklaşık karıştırma özelliği olan IterableDataset.shuffle() metodundan yararlanabilirsiniz:

>>> iterable_dataset = dataset.to_iterable_dataset(num_shards=128)
>>> shuffled_iterable_dataset = iterable_dataset.shuffle(seed=42, buffer_size=1000)

Seç ve Filtrele

Bir veri setindeki satırları filtrelemek için iki seçenek vardır: select() ve filter().

  • select(), indeks listesine göre satırları döndürür:
>>> small_dataset = dataset.select([0, 10, 20, 30, 40, 50])
>>> len(small_dataset)
6
  • filter(), belirtilen koşula uyan satırları döndürür:
>>> start_with_ar = dataset.filter(lambda example: example["sentence1"].startswith("Ar"))
>>> len(start_with_ar)
6
>>> start_with_ar["sentence1"]
['Around 0335 GMT , Tab shares were up 19 cents , or 4.4 % , at A {@html "4.56,havingearliersetarecordhighofA 4.56 , having earlier set a record high of A "} 4.57 .',
'Arison said Mann may have been one of the pioneers of the world music movement and he had a deep love of Brazilian music .',
'Arts helped coach the youth on an eighth-grade football team at Lombardi Middle School in Green Bay .',
'Around 9 : 00 a.m. EDT ( 1300 GMT ) , the euro was at $ 1.1566 against the dollar , up 0.07 percent on the day .',
"Arguing that the case was an isolated example , Canada has threatened a trade backlash if Tokyo 's ban is not justified on scientific grounds .",
'Artists are worried the plan would harm those who need help most - performers who have a difficult time lining up shows .'
]

filter(), with_indices=True olarak ayarlarsanız indekslere göre de filtreleyebilir:

>>> even_dataset = dataset.filter(lambda example, idx: idx % 2 == 0, with_indices=True)
>>> len(even_dataset)
1834
>>> len(dataset) / 2
1834.0

Tutulacak indekslerin listesi ardışık değilse, bu yöntemler de arka planda bir indeks eşlemesi oluşturur.

Böl

train_test_split() işlevi, veri setinizde henüz eğitim ve test bölümleri yoksa bunları oluşturur. Bu sayede her bir bölümdeki örneklerin göreli oranlarını veya mutlak sayılarını ayarlayabilirsiniz. Aşağıdaki örnekte, orijinal veri setinin %10'una karşılık gelen bir test bölümü oluşturmak için test_size parametresi kullanılır:

>>> dataset.train_test_split(test_size=0.1)
{'train': Dataset(schema: {'sentence1': 'string', 'sentence2': 'string', 'label': 'int64', 'idx': 'int32'}, num_rows: 3301),
'test': Dataset(schema: {'sentence1': 'string', 'sentence2': 'string', 'label': 'int64', 'idx': 'int32'}, num_rows: 367)}
>>> 0.1 * len(dataset)
366.8

Bölümler varsayılan olarak karıştırılır, ancak karıştırılmasını önlemek için shuffle=False ayarlayabilirsiniz.

Parça

🤗 Datasets, çok büyük bir veri setini önceden tanımlanmış sayıda parçaya bölmek için shard (parçalama) desteği sunar. Veri setinin kaç shard'a bölüneceğini belirlemek için shard() içinde num_shards parametresini belirtin. Ayrıca, döndürmek istediğiniz shard'ı index parametresiyle de sağlamanız gerekir.

Örneğin, stanfordnlp/imdb veri setinde 25000 örnek vardır:

>>> from datasets import load_dataset
>>> dataset = load_dataset("stanfordnlp/imdb", split="train")
>>> print(dataset)
Dataset({
    features: ['text', 'label'],
    num_rows: 25000
})

Veri seti dört parçaya bölündükten sonra, ilk parçada yalnızca 6250 örnek olacaktır:

>>> dataset.shard(num_shards=4, index=0)
Dataset({
    features: ['text', 'label'],
    num_rows: 6250
})
>>> print(25000/4)
6250.0

Yeniden adlandırma, kaldırma, dönüştürme ve düzleştirme

Aşağıdaki işlevler, bir veri setinin sütunlarını değiştirmenize olanak tanır. Bu işlevler, sütunları yeniden adlandırmak veya kaldırmak, sütunları yeni bir özellik kümesine dönüştürmek ve iç içe geçmiş sütun yapılarını düzleştirmek için kullanışlıdır.

Yeniden adlandır

Veri setinizde bir sütunu yeniden adlandırmanız gerektiğinde rename_column() kullanın. Orijinal sütunla ilişkili özellikler, orijinal sütunun yerinde değiştirilmesi yerine aslında yeni sütun adının altına taşınır.

rename_column() fonksiyonuna, orijinal sütunun adını ve yeni sütun adını verin:

>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'label', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.rename_column("sentence1", "sentenceA")
>>> dataset = dataset.rename_column("sentence2", "sentenceB")
>>> dataset
Dataset({
    features: ['sentenceA', 'sentenceB', 'label', 'idx'],
    num_rows: 3668
})

Kaldır

Bir veya daha fazla sütunu kaldırmak gerektiğinde, kaldırılacak sütun adını remove_columns() fonksiyonuna iletin. Birden fazla sütun kaldırmak için sütun adlarının bir listesini sağlayın:

>>> dataset = dataset.remove_columns("label")
>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.remove_columns(["sentence1", "sentence2"])
>>> dataset
Dataset({
    features: ['idx'],
    num_rows: 3668
})

Buna karşılık, select_columns() fonksiyonu, tutulacak bir veya daha fazla sütunu seçer ve kalanları kaldırır. Bu fonksiyon, tek bir sütun adı veya sütun adlarının bir listesini alır:

>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'label', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.select_columns(['sentence1', 'sentence2', 'idx'])
>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.select_columns('idx')
>>> dataset
Dataset({
    features: ['idx'],
    num_rows: 3668
})

Dönüştür

cast() fonksiyonu, bir veya daha fazla sütunun özellik türünü dönüştürür. Bu fonksiyon, argümanı olarak yeni Features nesnenizi kabul eder. Aşağıdaki örnek, ClassLabel ve Value özelliklerinin nasıl değiştirileceğini göstermektedir:

>>> 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, yalnızca orijinal özellik türü ile yeni özellik türü uyumluysa çalışır. Örneğin, orijinal sütun yalnızca birler ve sıfırlar içeriyorsa, Value("int32") özellik türüne sahip bir sütunu Value("bool") olarak cast edebilirsiniz.

Tek bir sütunun özellik türünü değiştirmek için cast_column() fonksiyonunu kullanın. Sütun adını ve yeni özellik türünü argüman olarak iletin:

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

Düzleştir

Bazen bir sütun, birden fazla türün iç içe geçmiş yapısı olabilir. SQuAD veri setinden aşağıdaki iç içe yapıya bir göz atın:

>>> from datasets import load_dataset
>>> dataset = load_dataset("rajpurkar/squad", split="train")
>>> dataset.features
{'id': Value('string'),
 'title': Value('string'),
 'context': Value('string'),
 'question': Value('string'),
 'answers': {'text': List(Value('string')),
  'answer_start': List(Value('int32'))}}

answers alanı iki alt alan içerir: text ve answer_start. Alt alanları kendi ayrı sütunlarına çıkarmak için flatten() fonksiyonunu kullanın:

>>> flat_dataset = dataset.flatten()
>>> flat_dataset
Dataset({
    features: ['id', 'title', 'context', 'question', 'answers.text', 'answers.answer_start'],
 num_rows: 87599
})

Alt alanların artık kendi bağımsız sütunları olduğunu fark edin: answers.text ve answers.answer_start.

Harita

🤗 Datasets'in daha güçlü uygulamalarından bazıları, map() işlevinin kullanılmasından kaynaklanır. map()'in birincil amacı, işleme işlevlerini hızlandırmaktır. Bu işlev, bir veri setindeki her örneğe bağımsız olarak veya toplu halde bir işleme işlevi uygulamanıza olanak tanır. Bu işlev, yeni satırlar ve sütunlar bile oluşturabilir.

Aşağıdaki örnekte, veri setindeki her sentence1 değerinin başına 'My sentence: ' ekleyin.

Her cümlenin başına 'My sentence: ' ekleyen bir fonksiyon oluşturarak başlayın. Fonksiyonun bir dict kabul etmesi ve bir dict döndürmesi gerekir:

>>> def add_prefix(example):
...     example["sentence1"] = 'My sentence: ' + example["sentence1"]
...     return example

Şimdi map() kullanarak add_prefix fonksiyonunu tüm veri setine uygulayın:

>>> updated_dataset = small_dataset.map(add_prefix)
>>> updated_dataset["sentence1"][:5]
['My sentence: Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
"My sentence: Yucaipa owned Dominick 's before selling the chain to Safeway in 1998 for $ 2.5 billion .",
'My sentence: They had published an advertisement on the Internet on June 10 , offering the cargo for sale , he added .',
'My sentence: Around 0335 GMT , Tab shares were up 19 cents , or 4.4 % , at A {@html "4.56,havingearliersetarecordhighofA 4.56 , having earlier set a record high of A "} 4.57 .',
]

Bir başka örneğe bakalım; bu sefer bir sütunu map() ile kaldıracaksınız. Bir sütun kaldırıldığında, bu kaldırma işlemi örnek, eşlenmiş işlevine sağlandıktan sonra gerçekleşir. Bu sayede eşlenmiş işlev, sütunlar kaldırılmadan önce içeriklerini kullanabilir.

map() içindeki remove_columns parametresiyle kaldırılacak sütunu belirtin:

>>> updated_dataset = dataset.map(lambda example: {"new_sentence": example["sentence1"]}, remove_columns=["sentence1"])
>>> updated_dataset.column_names
['sentence2', 'label', 'idx', 'new_sentence']

🤗 Datasets ayrıca kalan sütunların verilerini kopyalamadığı için daha hızlı olan remove_columns() işlevine de sahiptir.

with_indices=True olarak ayarlarsanız, map() fonksiyonunu indekslerle birlikte de kullanabilirsiniz. Aşağıdaki örnek, her cümlenin başına indeksi ekler:

>>> updated_dataset = dataset.map(lambda example, idx: {"sentence2": f"{idx}: " + example["sentence2"]}, with_indices=True)
>>> updated_dataset["sentence2"][:5]
['0: Referring to him as only " the witness " , Amrozi accused his brother of deliberately distorting his evidence .',
 "1: Yucaipa bought Dominick 's in 1995 for {@html "693millionandsoldittoSafewayfor 693 million and sold it to Safeway for "} 1.8 billion in 1998 .",
 "2: On June 10 , the ship 's owners had published an advertisement on the Internet , offering the explosives for sale .",
 '3: Tab shares jumped 20 cents , or 4.6 % , to set a record closing high at A $ 4.57 .',
 '4: PG & E Corp. shares jumped {@html "1.63or8percentto 1.63 or 8 percent to "} 21.03 on the New York Stock Exchange on Friday .'
]

Çok İşlemcili

Çok işlemcili (multiprocessing), CPU üzerindeki süreçleri paralelleştirerek işleme hızını önemli ölçüde artırır. Kullanılacak süreç sayısını belirlemek için map() içindeki num_proc parametresini ayarlayın:

>>> updated_dataset = dataset.map(lambda example, idx: {"sentence2": f"{idx}: " + example["sentence2"]}, with_indices=True, num_proc=4)

map(), with_rank=True olarak ayarlanırsa, sürecin rank değeriyle de çalışır. Bu, with_indices parametresine benzer. Haritalanmış fonksiyondaki with_rank parametresi, index parametresi zaten varsa onun ardından gelir.

>>> import torch
>>> from multiprocess import set_start_method
>>> from transformers import AutoTokenizer, AutoModelForCausalLM
>>> from datasets import load_dataset
>>>
>>> # Get an example dataset
>>> dataset = load_dataset("fka/awesome-chatgpt-prompts", split="train")
>>>
>>> # Get an example model and its tokenizer
>>> model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B-Chat").eval()
>>> tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B-Chat")
>>>
>>> def gpu_computation(batch, rank):
...     # Move the model on the right GPU if it's not there already
...     device = f"cuda:{(rank or 0) % torch.cuda.device_count()}"
...     model.to(device)
...
...     # Your big GPU call goes here, for example:
...     chats = [[
...         {"role": "system", "content": "You are a helpful assistant."},
...         {"role": "user", "content": prompt}
...     ] for prompt in batch["prompt"]]
...     texts = [tokenizer.apply_chat_template(
...         chat,
...         tokenize=False,
...         add_generation_prompt=True
...     ) for chat in chats]
...     model_inputs = tokenizer(texts, padding=True, return_tensors="pt").to(device)
...     with torch.no_grad():
...         outputs = model.generate(**model_inputs, max_new_tokens=512)
...     batch["output"] = tokenizer.batch_decode(outputs, skip_special_tokens=True)
...     return batch
>>>
>>> if __name__ == "__main__":
...     set_start_method("spawn")
...     updated_dataset = dataset.map(
...         gpu_computation,
...         batched=True,
...         batch_size=16,
...         with_rank=True,
...         num_proc=torch.cuda.device_count(),  # one process per GPU
...     )

rank'in ana kullanım senaryosu, hesaplamayı birden fazla GPU arasında paralelleştirmektir. Bunun için multiprocess.set_start_method("spawn") ayarının yapılması gerekir. Bunu yapmazsanız aşağıdaki CUDA hatasını alırsınız:

RuntimeError: Cannot re-initialize CUDA in forked subprocess. To use CUDA with multiprocessing, you must use the 'spawn' start method.

Toplu işleme

map() fonksiyonu, örneklerin toplu (batch) olarak işlenmesini destekler. Toplular üzerinde işlem yapmak için batched=True değerini ayarlayın. Varsayılan top büyüklüğü 1000'dir ancak bu değeri batch_size parametresiyle değiştirebilirsiniz. Toplu işleme, uzun cümleleri daha kısa parçalara bölmek ve veri artırma gibi ilginç uygulamalara olanak tanır.

Uzun örnekleri böl

Örnekler çok uzunsa, onları birkaç küçük parçaya bölmek isteyebilirsiniz. Şu işlevi gerçekleştiren bir fonksiyon oluşturarak başlayın:

  1. sentence1 alanını 50 karakterlik parçalara böler.

  2. Yeni veri setini oluşturmak için tüm parçaları bir araya getirir.

>>> def chunk_examples(examples):
...     chunks = []
...     for sentence in examples["sentence1"]:
...         chunks += [sentence[i:i + 50] for i in range(0, len(sentence), 50)]
...     return {"chunks": chunks}

Fonksiyonu map() ile uygulayın:

>>> chunked_dataset = dataset.map(chunk_examples, batched=True, remove_columns=dataset.column_names)
>>> chunked_dataset[:10]
{'chunks': ['Amrozi accused his brother , whom he called " the ',
            'witness " , of deliberately distorting his evidenc',
            'e .',
            "Yucaipa owned Dominick 's before selling the chain",
            ' to Safeway in 1998 for $ 2.5 billion .',
            'They had published an advertisement on the Interne',
            't on June 10 , offering the cargo for sale , he ad',
            'ded .',
            'Around 0335 GMT , Tab shares were up 19 cents , or',
            ' 4.4 % , at A $ 4.56 , having earlier set a record']}

Cümlelerin şimdi daha kısa parçalara ayrıldığını ve veri setinde daha fazla satır olduğunu fark edin.

>>> dataset
Dataset({
 features: ['sentence1', 'sentence2', 'label', 'idx'],
 num_rows: 3668
})
>>> chunked_dataset
Dataset({
    features: ['chunks'],
    num_rows: 10470
})

Veri artırma

map() fonksiyonu veri artırma için de kullanılabilir. Aşağıdaki örnek, bir cümledeki maskelenmiş bir token için ek kelimeler üretir.

🤗 Transformers'ın FillMaskPipeline bileşeninde RoBERTA modelini yükleyip kullanın:

>>> from random import randint
>>> from transformers import pipeline

>>> fillmask = pipeline("fill-mask", model="roberta-base")
>>> mask_token = fillmask.tokenizer.mask_token
>>> smaller_dataset = dataset.filter(lambda e, i: i<100, with_indices=True)

Cümlede maskelenmek üzere rastgele bir kelime seçmek için bir fonksiyon oluşturun. Fonksiyon, orijinal cümleyi ve RoBERTA tarafından üretilen en iyi iki ikameyi de döndürmelidir.

>>> def augment_data(examples):
...     outputs = []
...     for sentence in examples["sentence1"]:
...         words = sentence.split(' ')
...         K = randint(1, len(words)-1)
...         masked_sentence = " ".join(words[:K]  + [mask_token] + words[K+1:])
...         predictions = fillmask(masked_sentence)
...         augmented_sequences = [predictions[i]["sequence"] for i in range(3)]
...         outputs += [sentence] + augmented_sequences
...
...     return {"data": outputs}

Tüm veri setine fonksiyonu uygulamak için map() kullanın:

>>> augmented_dataset = smaller_dataset.map(augment_data, batched=True, remove_columns=dataset.column_names, batch_size=8)
>>> augmented_dataset[:9]["data"]
['Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
 'Amrozi accused his brother, whom he called " the witness ", of deliberately withholding his evidence.',
 'Amrozi accused his brother, whom he called " the witness ", of deliberately suppressing his evidence.',
 'Amrozi accused his brother, whom he called " the witness ", of deliberately destroying his evidence.',
 "Yucaipa owned Dominick 's before selling the chain to Safeway in 1998 for $ 2.5 billion .",
 'Yucaipa owned Dominick Stores before selling the chain to Safeway in 1998 for $ 2.5 billion.',
 "Yucaipa owned Dominick's before selling the chain to Safeway in 1998 for $ 2.5 billion.",
 'Yucaipa owned Dominick Pizza before selling the chain to Safeway in 1998 for $ 2.5 billion.'
]

Her orijinal cümle için RoBERTa, rastgele bir kelimeyi üç alternatifle artırdı. Orijinal kelime olan distorting, withholding, suppressing ve destroying ile tamamlanır.

Asenkron işleme

Asenkron işlevler, örneğin görseller gibi içerik indirmek veya bir model uç noktasını çağırmak için API uç noktalarını paralel olarak çağırmak üzere kullanışlıdır.

async ve await anahtar kelimelerini kullanarak asenkron bir fonksiyon tanımlayabilirsiniz; Hugging Face'ten bir sohbet modelini çağıran örnek bir fonksiyon aşağıdadır:

>>> import aiohttp
>>> import asyncio
>>> from huggingface_hub import get_token
>>> sem = asyncio.Semaphore(20)  # max number of simultaneous queries
>>> async def query_model(model, prompt):
...     api_url = f"https://api-inference.huggingface.co/models/{model}/v1/chat/completions"
...     headers = {"Authorization": f"Bearer {get_token()}", "Content-Type": "application/json"}
...     json = {"messages": [{"role": "user", "content": prompt}], "max_tokens": 20, "seed": 42}
...     async with sem, aiohttp.ClientSession() as session, session.post(api_url, headers=headers, json=json) as response:
...         output = await response.json()
...         return {"Output": output["choices"][0]["message"]["content"]}

Asenkron işlevler paralel çalışır ve bu da süreci büyük ölçüde hızlandırır. Aynı kod sıralı olarak çalıştırılırsa, model yanıtını beklerken hiçbir şey yapmadığı için çok daha fazla zaman alır. Bir işlevin örneğin bir API'den yanıt beklemesi veya veri indirmesi ve bunun biraz zaman alması gerekiyorsa, genellikle async / await kullanılması önerilir.

Semaphore varlığına dikkat edin: paralel olarak çalıştırılabilecek sorguların maksimum sayısını belirler. API çağrılarında hız sınırı hatalarından kaçınmak için Semaphore kullanılması önerilir.

Bunu kullanarak microsoft/Phi-3-mini-4k-instruct modelini çağıralım ve Maxwell-Jia/AIME_2024 veri setindeki her matematik sorusunun ana konusunu döndürmesini isteyelim:

>>> from datasets import load_dataset
>>> ds = load_dataset("Maxwell-Jia/AIME_2024", split="train")
>>> model = "microsoft/Phi-3-mini-4k-instruct"
>>> prompt = 'What is this text mainly about ? Here is the text:\n\n```\n{Problem}\n```\n\nReply using one or two words max, e.g. "The main topic is Linear Algebra".'
>>> async def get_topic(example):
...     return await query_model(model, prompt.format(Problem=example['Problem']))
>>> ds = ds.map(get_topic)
>>> ds[0]
{'ID': '2024-II-4',
 'Problem': 'Let {@html "x,yx,y"} and {@html "zz"} be positive real numbers that...',
 'Solution': 'Denote $\\log_2(x) = a$, $\\log_2(y) = b$, and...,
 'Answer': 33,
 'Output': 'The main topic is Logarithms.'}

Burada Dataset.map(), her bir model yanıtını beklemek zorunda kalmaması için birçok get_topic fonksiyonunu asenkron olarak çalıştırır; bu işlemler sıralı olarak yapılsaydı çok fazla zaman alırdı.

Varsayılan olarak Dataset.map(), en fazla bin map işlevini paralel olarak çalıştırır; bu nedenle, modelin hız sınırı hataları döndürmesine veya aşırı yüklenmesine izin vermemek için paralel olarak çalıştırılabilecek API çağrılarının maksimum sayısını bir Semaphore ile ayarlamayı unutmayın. Gelişmiş kullanım senaryolarında, datasets.config içinde paralel sorguların maksimum sayısını değiştirebilirsiniz.

Birden çok bölümleri işleyin

Birçok veri seti, DatasetDict.map() ile eş zamanlı olarak işlenebilecek bölümlere sahiptir. Örneğin, train ve test bölümlerindeki sentence1 alanını şu şekilde belirterek tokenleştirebilirsiniz:

>>> from datasets import load_dataset

# load all the splits
>>> dataset = load_dataset('nyu-mll/glue', 'mrpc')
>>> encoded_dataset = dataset.map(lambda examples: tokenizer(examples["sentence1"]), batched=True)
>>> encoded_dataset["train"][0]
{'sentence1': 'Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
'sentence2': 'Referring to him as only " the witness " , Amrozi accused his brother of deliberately distorting his evidence .',
'label': 1,
'idx': 0,
'input_ids': [  101,  7277,  2180,  5303,  4806,  1117,  1711,   117,  2292, 1119,  1270,   107,  1103,  7737,   107,   117,  1104,  9938, 4267, 12223, 21811,  1117,  2554,   119,   102],
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}

Dağıtık kullanım

Dağıtık bir ortamda map() kullandığınızda, torch.distributed.barrier kullanmanız da gerekir. Bu, ana sürecin eşlemeyi (mapping) yapmasını, diğer süreçlerin ise sonuçları yüklemesini sağlayarak tekrarlanan işten kaçınılmasını sağlar.

Aşağıdaki örnek, süreçleri senkronize etmek için torch.distributed.barrier nasıl kullanabileceğinizi gösterir:

>>> from datasets import Dataset
>>> import torch.distributed

>>> dataset1 = Dataset.from_dict({"a": [0, 1, 2]})

>>> if training_args.local_rank > 0:
...     print("Waiting for main process to perform the mapping")
...     torch.distributed.barrier()

>>> dataset2 = dataset1.map(lambda x: {"a": x["a"] + 1})

>>> if training_args.local_rank == 0:
...     print("Loading results from main process")
...     torch.distributed.barrier()

Toplu

batch() yöntemi, veri setindeki örnekleri toplu işlere (batch) gruplamanızı sağlar. Bu, özellikle derin öğrenme modelleriyle çalışırken eğitim veya değerlendirme için veri toplu işleri oluşturmak istediğinizde son derece faydalıdır.

batch() metodunun nasıl kullanılacağına dair bir örnek:

>>> from datasets import load_dataset
>>> dataset = load_dataset("cornell-movie-review-data/rotten_tomatoes", split="train")
>>> batched_dataset = dataset.batch(batch_size=4)
>>> batched_dataset[0]
{'text': ['the rock is destined to be the 21st century\'s new " conan " and that he\'s going to make a splash even greater than arnold schwarzenegger , jean-claud van damme or steven segal .',
        'the gorgeously elaborate continuation of " the lord of the rings " trilogy is so huge that a column of words cannot adequately describe co-writer/director peter jackson\'s expanded vision of j . r . r . tolkien\'s middle-earth .',
        'effective but too-tepid biopic',
        'if you sometimes like to go to the movies to have fun , wasabi is a good place to start .'],
'label': [1, 1, 1, 1]}

batch() yöntemi aşağıdaki parametreleri kabul eder:

  • batch_size (int): Her batch'teki örnek sayısı.
  • drop_last_batch (bool, varsayılan False): Veri seti boyutu, parti boyutuna tam bölünmüyorsa son eksik partinin atılıp atılmayacağını belirtir.
  • num_proc (int, isteğe bağlı, varsayılan None): Çok işlemci kullanımı için kullanılacak işlem sayısı. None ise çok işlemci kullanılmaz. Bu, büyük veri kümeleri için toplu işlemleri (batching) önemli ölçüde hızlandırabilir.

Dataset.batch() işlevinin, orijinal veri setinden çok sayıda örnek içeren birer parti (batch) olan her öğeye sahip yeni bir Dataset döndürdüğünü unutmayın. Verileri partiler halinde işlemek istiyorsanız, doğrudan partili bir map() kullanmalısınız; bu işlev fonksiyonu partilere uygular ancak çıktı veri seti partilendirilmemiş (unbatched) olur.

Birleştir

Aynı sütun türlerini paylaşan ayrı veri setleri birleştirilebilir. Veri setlerini concatenate_datasets() ile birleştirin:

>>> from datasets import concatenate_datasets, load_dataset

>>> stories = load_dataset("ajibawa-2023/General-Stories-Collection", split="train")
>>> stories = stories.select_columns(["text"])  # only keep the 'text' column
>>> wiki = load_dataset("wikimedia/wikipedia", "20231101.en", split="train")
>>> wiki = wiki.select_columns(["text"])  # only keep the 'text' column

>>> assert stories.features.type == wiki.features.type
>>> bert_dataset = concatenate_datasets([stories, wiki])

Ayrıca, veri kümelerinin aynı sayıda satıra sahip olması koşuluyla, axis=1 değerini ayarlayarak iki veri kümesini yatay olarak birleştirebilirsiniz:

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

Araya Ser

Birkaç veri setini bir araya getirerek her birinden dönüşümlü örnekler almak suretiyle yeni bir veri seti oluşturabilirsiniz. Bu işlem interleaving olarak bilinir ve interleave_datasets() fonksiyonu ile sağlanır. Hem interleave_datasets() hem de concatenate_datasets(), standart Dataset ve IterableDataset nesneleriyle çalışır. IterableDataset nesnelerini nasıl iç içe geçireceğinize dair bir örnek için Stream kılavuzuna başvurun.

Orijinal veri kümelerinin her biri için örneklem olasılıkları tanımlayarak veri kümelerinin nasıl iç içe geçirileceğini belirleyebilirsiniz. Bu durumda, yeni veri kümesi, veri kümelerinden biri örneklemelerinin bitirilmesi kadar rastgele bir veri kümesinden örnekleri tek tek alarak oluşturulur.

>>> from datasets import Dataset, interleave_datasets
>>> seed = 42
>>> probabilities = [0.3, 0.5, 0.2]
>>> d1 = Dataset.from_dict({"a": [0, 1, 2]})
>>> d2 = Dataset.from_dict({"a": [10, 11, 12, 13]})
>>> d3 = Dataset.from_dict({"a": [20, 21, 22]})
>>> dataset = interleave_datasets([d1, d2, d3], probabilities=probabilities, seed=seed)
>>> dataset["a"]
[10, 11, 20, 12, 0, 21, 13]

stopping_strategy parametresini de belirleyebilirsiniz. Varsayılan strateji olan first_exhausted, bir alt örneklem (subsampling) stratejisidir; yani veri setlerinden biri örneklerini tükettiği anda veri seti inşası durdurulur. Aşırı örneklem (oversampling) stratejisi uygulamak için stopping_strategy=all_exhausted parametresini belirleyebilirsiniz. Bu durumda, veri setlerindeki her örnek en az bir kez eklendiği anda veri seti inşası durdurulur. Pratikte bu, bir veri seti tükendiğinde durdurma kriterine ulaşıncaya kadar bu veri setinin başına dönülerek örneklerin tekrar alınacağı anlamına gelir. Örnekleme olasılıkları belirtilmezse, yeni veri setinin max_length_datasets*nb_dataset samples örnek içereceğini unutmayın. Her örneğin tam olarak bir kez görüleceğinden emin olmak için stopping_strategy=all_exhausted_without_replacement seçeneği de mevcuttur.

>>> d1 = Dataset.from_dict({"a": [0, 1, 2]})
>>> d2 = Dataset.from_dict({"a": [10, 11, 12, 13]})
>>> d3 = Dataset.from_dict({"a": [20, 21, 22]})
>>> dataset = interleave_datasets([d1, d2, d3], stopping_strategy="all_exhausted")
>>> dataset["a"]
[0, 10, 20, 1, 11, 21, 2, 12, 22, 0, 13, 20]

Biçim

with_format() fonksiyonu, bir sütunun biçimini yaygın veri biçimleriyle uyumlu olacak şekilde değiştirir. İstediğiniz çıktıyı type parametresinde belirtin. columns= kullanarak biçimlendirmek istediğiniz sütunları da seçebilirsiniz. Biçimlendirme anlık olarak uygulanır.

Örneğin, type="torch" ayarlayarak PyTorch tensörleri oluşturun:

>>> dataset = dataset.with_format(type="torch")

set_format() fonksiyonu da bir sütunun biçimini değiştirir, ancak yerinde çalışır:

>>> dataset.set_format(type="torch")

Veri setini orijinal biçimine sıfırlamanız gerekiyorsa, biçimi None olarak ayarlayın (veya reset_format() kullanın):

>>> dataset.format
{'type': 'torch', 'format_kwargs': {}, 'columns': [...], 'output_all_columns': False}
>>> dataset = dataset.with_format(None)
>>> dataset.format
{'type': None, 'format_kwargs': {}, 'columns': [...], 'output_all_columns': False}

Tensör biçimleri

Birkaç tensör veya dizi biçimi desteklenir. Gereksiz veri kopyalamalarını önlemek ve veri yükleme hızını artırmak için, bir veri setinin çıktılarını tensörlere veya dizilere manuel olarak dönüştürmek yerine bu biçimleri kullanmak genel olarak önerilir.

Desteklenen tensör veya dizi biçimleri listesi aşağıdadır:

TensorFlow veri setini verimli bir şekilde oluşturmanın ayrıntıları için TensorFlow ile Veri Setleri Kullanma kılavuzuna göz atın.

Bir veri seti tensör veya dizi biçiminde biçimlendirildiğinde, tüm veriler tensör veya dizi olarak biçimlendirilir (PyTorch için örneğin dizgiler gibi desteklenmeyen türler hariç):

>>> ds = Dataset.from_dict({"text": ["foo", "bar"], "tokens": [[0, 1, 2], [3, 4, 5]]})
>>> ds = ds.with_format("torch")
>>> ds[0]
{'text': 'foo', 'tokens': tensor([0, 1, 2])}
>>> ds[:2]
{'text': ['foo', 'bar'],
 'tokens': tensor([[0, 1, 2],
         [3, 4, 5]])}

Tablo biçimleri

Veri yükleme ve veri işleme süreçlerini optimize etmek için dataframes veya tables biçimini kullanabilirsiniz; bu biçimler genellikle sıfır kopyalama (zero-copy) işlemleri ve düşük seviyeli dillerde yazılmış dönüşümler sunar.

Desteklenen dataframe veya tablo biçimleri listesi aşağıdadır:

Bir veri seti dataframe veya tablo biçiminde formatlanmışsa, veri setindeki her satır veya satır toplulukları bir dataframe veya tablo olarak, veri seti sütunları ise bir seri veya dizi olarak formatlanır:

>>> ds = Dataset.from_dict({"text": ["foo", "bar"], "label": [0, 1]})
>>> ds = ds.with_format("pandas")
>>> ds[:2]
  text  label
0  foo      0
1  bar      1

Bu formatlar, veri kopyalamalarını önleyerek veriler üzerinde daha hızlı ilerlemeyi ve map() veya filter() içinde daha hızlı veri işleme yapılmasını sağlar:

>>> ds = ds.map(lambda df: df.assign(upper_text=df.text.str.upper()), batched=True)
>>> ds[:2]
  text  label upper_text
0  foo      0        FOO
1  bar      1        BAR

Özel biçim dönüştürme

with_transform() işlevi, özel bir biçimlendirme dönüşümünü anlık olarak uygular. Bu işlev, daha önce belirtilmiş herhangi bir biçimi değiştirir. Örneğin, bu işlevi jetonları (token) anlık olarak jetonlaştırmak (tokenize) ve dolgu (pad) yapmak için kullanabilirsiniz. Jetonlaştırma (tokenization), örnekler erişildiğinde uygulanır:

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
>>> def encode(batch):
...     return tokenizer(batch["sentence1"], batch["sentence2"], padding="longest", truncation=True, max_length=512, return_tensors="pt")
>>> dataset = dataset.with_transform(encode)
>>> dataset.format
{'type': 'custom', 'format_kwargs': {'transform': <function __main__.encode(batch)>}, 'columns': ['idx', 'label', 'sentence1', 'sentence2'], 'output_all_columns': False}

Aynı işlevi gören ancak yerinde (in-place) çalışan set_transform() de mevcuttur.

Features üzerinde özel çözümleme için with_transform() fonksiyonunu da kullanabilirsiniz.

Aşağıdaki örnek, torchcodec çözümleme yerine pydub paketini kullanır:

>>> import numpy as np
>>> from pydub import AudioSegment

>>> audio_dataset_amr = Dataset.from_dict({"audio": ["audio_samples/audio.amr"]})

>>> def decode_audio_with_pydub(batch, sampling_rate=16_000):
...     def pydub_decode_file(audio_path):
...         sound = AudioSegment.from_file(audio_path)
...         if sound.frame_rate != sampling_rate:
...             sound = sound.set_frame_rate(sampling_rate)
...         channel_sounds = sound.split_to_mono()
...         samples = [s.get_array_of_samples() for s in channel_sounds]
...         fp_arr = np.array(samples).T.astype(np.float32)
...         fp_arr /= np.iinfo(samples[0].typecode).max
...         return fp_arr
...
...     batch["audio"] = [pydub_decode_file(audio_path) for audio_path in batch["audio"]]
...     return batch

>>> audio_dataset_amr.set_transform(decode_audio_with_pydub)

Kaydet

Veri setiniz hazır olduğunda, Parquet biçiminde bir Hugging Face Dataset olarak kaydedebilir ve daha sonra load_dataset() ile yeniden kullanabilirsiniz.

Veri setinizi, Hugging Face üzerinde kaydetmek istediğiniz veri seti deposunun adını push_to_hub() parametresi olarak sağlayarak kaydedin:

encoded_dataset.push_to_hub("username/my_dataset")

Paralel olarak yüklemek için birden çok süreç kullanabilirsiniz. Bu, süreci hızlandırmak istiyorsanız özellikle faydalıdır:

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

Veri setini yeniden yüklemek için (akış modunda veya değil) load_dataset() işlevini kullanın:

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

Alternatif olarak, dosyayı diske Arrow biçiminde yerel olarak kaydedebilirsiniz. Parquet ile karşılaştırıldığında Arrow sıkıştırılmamış olduğu için yeniden yüklenmesi çok daha hızlıdır; bu da disk üzerinde yerel kullanım ve geçici önbellekleme için idealdir. Ancak boyutu daha büyük ve üst verisi daha az olduğu için Parquet'e kıyasla yüklemesi/indirmesi/sorgulanması daha yavaştır ve uzun vadeli depolama için daha az uygundur.

Diskten veri setini yeniden yüklemek için save_to_disk() ve load_from_disk() işlevlerini kullanın:

>>> encoded_dataset.save_to_disk("path/of/my/dataset/directory")
>>> # later
>>> from datasets import load_from_disk
>>> reloaded_dataset = load_from_disk("path/of/my/dataset/directory")

Dışa Aktar

🤗 Datasets, veri setinizi diğer uygulamalarda çalışabilmeniz için dışa aktarmayı da destekler. Aşağıdaki tablo, dışa aktarabileceğiniz şu anda desteklenen dosya biçimlerini gösterir:

Dosya türüDışa aktarma yöntemi
CSVDataset.to_csv()
JSONDataset.to_json()
ParquetDataset.to_parquet()
SQLDataset.to_sql()
Bellek içi Python nesnesiDataset.to_pandas(), Dataset.to_polars() or Dataset.to_dict()

Örneğin, veri setinizi bir CSV dosyasına şu şekilde dışa aktarın:

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

Hugging Face'te bir Dataset deposuna veya bir Storage Bucket'a dışa aktarmak için hf:// yolunu kullanın:

>>> encoded_dataset.to_csv("hf://datasets/username/dataset_name/path/of/my/dataset.csv")
>>> encoded_dataset.to_csv("hf://buckets/username/raw_data_bucket/path/of/my/dataset.csv")
Update on GitHub