Hugging Face Datasets Kütüphanesi ile Veri Yükleme ve Kullanma

Veri bilimi ve makine öğrenmesi projelerinde en çok zaman harcanan aşamalardan biri veri toplama ve hazırlama sürecidir. Hugging Face’in datasets kütüphanesi bu süreci dramatik biçimde kısaltıyor. Hub üzerinde on binlerce hazır veri seti barındıran bu ekosistem, hem araştırmacılar hem de production ortamında çalışan mühendisler için ciddi bir kolaylık sağlıyor. Bu yazıda datasets kütüphanesini sıfırdan kurulumdan başlayarak gerçek dünya senaryolarına kadar derinlemesine inceleyeceğiz.

Kurulum ve Temel Gereksinimler

Başlamadan önce ortamımızı hazırlayalım. Python 3.8 ve üzeri bir sürüm önerilir. Sanal ortam kullanmak her zaman iyi bir pratiktir:

# Sanal ortam oluştur ve aktifleştir
python3 -m venv hf-datasets-env
source hf-datasets-env/bin/activate  # Linux/macOS
# Windows için: hf-datasets-envScriptsactivate

# Temel bağımlılıkları yükle
pip install datasets transformers huggingface_hub

# Opsiyonel ama faydalı araçlar
pip install pandas pyarrow fsspec aiohttp

Kurulum tamamlandıktan sonra kütüphanenin doğru yüklendiğini kontrol edelim:

python3 -c "import datasets; print(datasets.__version__)"
# Çıktı: 2.x.x gibi bir sürüm numarası görmeli siniz

datasets kütüphanesi arka planda Apache Arrow formatını kullanır. Bu sayede gigabyte seviyesindeki veri setlerini bile RAM’e tam olarak yüklemeden işleyebilirsiniz. Bu nokta production ortamları için kritik önem taşır.

İlk Veri Seti Yükleme

En temel kullanım senaryosuyla başlayalım. Hugging Face Hub’dan bir veri seti indirmek tek satır kod gerektirir:

python3 << 'EOF'
from datasets import load_dataset

# IMDB film yorum veri setini yükle
dataset = load_dataset("imdb")

print(type(dataset))
print(dataset)
print(dataset["train"][0])
EOF

Bu kodu çalıştırdığınızda kütüphane önce metadata bilgisini çeker, ardından veriyi indirir ve önbellekler. İkinci çalıştırmada önbellekten okuyacağı için çok daha hızlı çalışır. Varsayılan önbellek dizini ~/.cache/huggingface/datasets altındadır.

Çıktıya baktığınızda DatasetDict objesi göreceksiniz. Bu obje genellikle train, validation ve test split’lerini içerir. Her split ise bir Dataset objesidir.

Split ve Konfigürasyon Seçenekleri

Büyük veri setleriyle çalışırken tüm veriyi değil sadece ihtiyaç duyduğunuz kısmı yüklemek istersiniz. load_dataset fonksiyonu bu konuda oldukça esnek:

python3 << 'EOF'
from datasets import load_dataset

# Sadece test split'ini yükle
test_data = load_dataset("imdb", split="train")

# Belirli bir aralık yükle (ilk 1000 örnek)
small_train = load_dataset("imdb", split="train[:1000]")

# Yüzde belirterek yükle
twenty_percent = load_dataset("imdb", split="train[:20%]")

# Son 500 örnek
last_500 = load_dataset("imdb", split="train[-500:]")

print(f"Test boyutu: {len(test_data)}")
print(f"Küçük train boyutu: {len(small_train)}")
print(f"Yüzde 20: {len(twenty_percent)}")
print(f"Son 500: {len(last_500)}")
EOF

Bazı veri setleri birden fazla konfigürasyon içerir. Örneğin çok dilli bir veri seti farklı dil seçenekleri sunabilir:

python3 << 'EOF'
from datasets import load_dataset, get_dataset_config_names

# Mevcut konfigürasyonları listele
configs = get_dataset_config_names("amazon_reviews_multi")
print("Mevcut konfigürasyonlar:", configs[:5])

# Türkçe yorumlar için
# tr konfigürasyonu varsa yükle
try:
    tr_reviews = load_dataset("amazon_reviews_multi", "tr", split="train[:500]")
    print(f"Türkçe yorum sayısı: {len(tr_reviews)}")
    print(tr_reviews[0])
except Exception as e:
    print(f"Hata: {e}")
EOF

Veri Seti Özelliklerini İnceleme

Bir veri setiyle çalışmaya başlamadan önce yapısını anlamak önemlidir. features özelliği size kolonlar ve veri tiplerini gösterir:

python3 << 'EOF'
from datasets import load_dataset

dataset = load_dataset("squad", split="train[:100]")

# Veri seti özelliklerini incele
print("Özellikler:")
print(dataset.features)
print()

# Kolon isimleri
print("Kolon isimleri:", dataset.column_names)
print()

# Veri seti bilgisi
print("Veri seti boyutu:", dataset.shape)
print()

# İlk birkaç örneği gör
for i in range(3):
    print(f"Örnek {i+1}:", dataset[i]["question"])
    print()
EOF

SQuAD gibi soru-cevap veri setlerinde iç içe yapılar görebilirsiniz. Sequence ve Value tipleri Arrow’un güçlü tip sistemini yansıtır.

Filtreleme ve Dönüşüm İşlemleri

Veri ön işleme datasets kütüphanesinin en güçlü olduğu alanlardan biri. filter ve map fonksiyonları büyük veri setleri üzerinde paralel işlem yapabilir:

python3 << 'EOF'
from datasets import load_dataset

dataset = load_dataset("imdb", split="train")

# Sadece pozitif yorumları filtrele
positive_reviews = dataset.filter(lambda x: x["label"] == 1)
print(f"Pozitif yorum sayısı: {len(positive_reviews)}")

# Uzun yorumları filtrele (500 karakterden uzun)
long_reviews = dataset.filter(lambda x: len(x["text"]) > 500)
print(f"Uzun yorum sayısı: {len(long_reviews)}")

# map ile metin temizleme
def clean_text(example):
    example["text"] = example["text"].lower().strip()
    example["text_length"] = len(example["text"])
    return example

cleaned = dataset.select(range(100)).map(clean_text)
print("Temizleme sonrası örnek:")
print(cleaned[0]["text"][:100])
print(f"Metin uzunluğu: {cleaned[0]['text_length']}")
EOF

Çok büyük veri setlerinde map fonksiyonuna num_proc parametresi geçerek çok çekirdekli işlem yapabilirsiniz. Sunucu ortamında bu ciddi hız kazanımı sağlar:

python3 << 'EOF'
from datasets import load_dataset
import multiprocessing

dataset = load_dataset("imdb", split="train")

def tokenize_simple(example):
    example["tokens"] = example["text"].lower().split()
    example["token_count"] = len(example["tokens"])
    return example

# CPU çekirdek sayısını al
num_cores = multiprocessing.cpu_count()
print(f"Kullanılabilir çekirdek sayısı: {num_cores}")

# Çok işlemcili map işlemi
processed = dataset.map(
    tokenize_simple,
    num_proc=min(4, num_cores),
    desc="Tokenizasyon yapılıyor"
)

print(f"İşlem tamamlandı. Ortalama token sayısı: {sum(processed['token_count']) / len(processed):.1f}")
EOF

Batch İşleme ve Bellek Yönetimi

Production ortamında bellek yönetimi kritik önem taşır. datasets kütüphanesi batch parametresi ile büyük dönüşümleri verimli hale getirir:

python3 << 'EOF'
from datasets import load_dataset

dataset = load_dataset("imdb", split="train")

def batch_process(examples):
    # Toplu işlem daha verimlidir
    processed_texts = []
    sentiment_scores = []
    
    for text, label in zip(examples["text"], examples["label"]):
        # Basit bir sentiment skoru hesapla
        clean = text.lower()
        pos_words = clean.count("good") + clean.count("great") + clean.count("excellent")
        neg_words = clean.count("bad") + clean.count("terrible") + clean.count("awful")
        
        processed_texts.append(clean[:200])  # İlk 200 karakter
        sentiment_scores.append(pos_words - neg_words)
    
    return {
        "processed_text": processed_texts,
        "keyword_score": sentiment_scores
    }

# batched=True ile toplu işlem
result = dataset.map(
    batch_process,
    batched=True,
    batch_size=256,
    remove_columns=["text"]  # Eski kolonu kaldır
)

print("İşlenmiş veri seti kolonları:", result.column_names)
print("Örnek kayıt:", result[0])
EOF

Yerel Dosyalardan Veri Yükleme

Her zaman Hub’daki veri setleriyle çalışmayabilirsiniz. Kendi CSV, JSON veya Parquet dosyalarınızı da load_dataset ile yükleyebilirsiniz:

python3 << 'EOF'
import csv
import json
from datasets import load_dataset, Dataset
import pandas as pd

# Örnek CSV dosyası oluştur
with open("/tmp/ornek_veri.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["metin", "etiket", "kategori"])
    writer.writerow(["Bu ürün harika!", 1, "elektronik"])
    writer.writerow(["Kalite berbat çıktı.", 0, "giyim"])
    writer.writerow(["Fiyat performans iyi.", 1, "elektronik"])
    writer.writerow(["Beklentimi karşılamadı.", 0, "giyim"])

# CSV'den yükle
csv_dataset = load_dataset("csv", data_files="/tmp/ornek_veri.csv")
print("CSV veri seti:")
print(csv_dataset)
print(csv_dataset["train"][0])

# JSON Lines formatından yükle
with open("/tmp/ornek_veri.jsonl", "w") as f:
    for item in [
        {"metin": "Mükemmel hizmet.", "puan": 5},
        {"metin": "Geç teslimat.", "puan": 2},
        {"metin": "Tam istediğim gibi.", "puan": 5}
    ]:
        f.write(json.dumps(item, ensure_ascii=False) + "n")

jsonl_dataset = load_dataset("json", data_files="/tmp/ornek_veri.jsonl")
print("nJSON Lines veri seti:")
print(jsonl_dataset["train"][0])

# Pandas DataFrame'den doğrudan Dataset oluştur
df = pd.DataFrame({
    "metin": ["İyi ürün", "Kötü deneyim", "Tavsiye ederim"],
    "etiket": [1, 0, 1]
})
pandas_dataset = Dataset.from_pandas(df)
print("nPandas'tan oluşturulan veri seti:")
print(pandas_dataset[0])
EOF

Gerçek Dünya Senaryosu: Türkçe NLP Pipeline

Pratik bir senaryo üzerinden gidelim. Diyelim ki bir Türkçe duygu analizi modeli için veri hazırlıyorsunuz. Hem Hub’dan veri çekecek hem de kendi verilerinizi ekleyeceksiniz:

python3 << 'EOF'
from datasets import load_dataset, Dataset, concatenate_datasets, DatasetDict
import json

# Adım 1: Hub'dan çok dilli bir veri seti çek
print("Hub'dan veri çekiliyor...")
multilingual = load_dataset(
    "amazon_reviews_multi",
    "tr",
    split="train[:200]",
    trust_remote_code=True
)
print(f"Hub'dan çekilen örnek sayısı: {len(multilingual)}")

# Adım 2: Kendi yerel verimizi hazırla
local_data = [
    {"review_body": "Ürün tam açıklandığı gibi geldi.", "stars": 5},
    {"review_body": "Paket ezilmiş geldi, içi sağlam.", "stars": 3},
    {"review_body": "Kesinlikle almayın, sahte ürün.", "stars": 1},
    {"review_body": "Hızlı kargo, kaliteli malzeme.", "stars": 5},
    {"review_body": "Renk soldu ilk yıkamada.", "stars": 1},
]

with open("/tmp/yerel_veri.jsonl", "w") as f:
    for item in local_data:
        f.write(json.dumps(item, ensure_ascii=False) + "n")

local_dataset = load_dataset("json", data_files="/tmp/yerel_veri.jsonl", split="train")

# Adım 3: Veri normalizasyonu
def normalize_review(example):
    # Yıldız puanını binary etikete çevir
    stars = example.get("stars", 3)
    example["label"] = 1 if stars >= 4 else 0
    example["text"] = example.get("review_body", "").strip()
    return example

hub_normalized = multilingual.map(normalize_review)
local_normalized = local_dataset.map(normalize_review)

# Adım 4: Veri setlerini birleştir
# Ortak kolonları seç
common_cols = ["text", "label"]
hub_final = hub_normalized.select_columns(common_cols)
local_final = local_normalized.select_columns(common_cols)

combined = concatenate_datasets([hub_final, local_final])
print(f"nBirleşik veri seti boyutu: {len(combined)}")

# Adım 5: Train/validation/test bölme
combined_shuffled = combined.shuffle(seed=42)
train_size = int(0.8 * len(combined_shuffled))
val_size = int(0.1 * len(combined_shuffled))

final_dataset = DatasetDict({
    "train": combined_shuffled.select(range(train_size)),
    "validation": combined_shuffled.select(range(train_size, train_size + val_size)),
    "test": combined_shuffled.select(range(train_size + val_size, len(combined_shuffled)))
})

print("nFinal veri seti yapısı:")
print(final_dataset)

# Adım 6: Diske kaydet
final_dataset.save_to_disk("/tmp/turkce_sentiment_dataset")
print("nVeri seti kaydedildi!")

# Tekrar yükle
from datasets import load_from_disk
reloaded = load_from_disk("/tmp/turkce_sentiment_dataset")
print(f"Yeniden yüklenen train boyutu: {len(reloaded['train'])}")
EOF

Streaming Modu: Dev Veri Setleri İçin

Common Crawl, The Pile gibi terabayt boyutundaki veri setleriyle çalışırken hepsini indirmek mümkün olmayabilir. Streaming modu tam da bu durumlar için tasarlanmıştır:

python3 << 'EOF'
from datasets import load_dataset

# Streaming modunu aktifleştir
streamed_dataset = load_dataset(
    "wikipedia",
    "20220301.simple",
    split="train",
    streaming=True,
    trust_remote_code=True
)

print(f"Veri seti tipi: {type(streamed_dataset)}")

# İlk 5 makaleyi işle
print("nİlk 5 Wikipedia makalesi:")
count = 0
for article in streamed_dataset:
    print(f"Başlık: {article['title']}")
    print(f"İlk 100 karakter: {article['text'][:100]}")
    print("---")
    count += 1
    if count >= 5:
        break

# take() ile belirli sayıda örnek al
sample = streamed_dataset.take(100)
titles = [item["title"] for item in sample]
print(f"n100 makale başlığı toplandı. İlk 5: {titles[:5]}")

# filter() streaming ile de çalışır
long_articles = streamed_dataset.filter(
    lambda x: len(x["text"]) > 1000
)

print("n1000+ karakter içeren makaleler (ilk 3):")
count = 0
for article in long_articles:
    print(f"- {article['title']} ({len(article['text'])} karakter)")
    count += 1
    if count >= 3:
        break
EOF

Önbellek Yönetimi ve Disk Alanı Kontrolü

Uzun süre çalışan bir geliştirme ortamında önbellek hızla büyüyebilir. Sunucu yöneticisi olarak disk alanını takip etmek önemlidir:

# Hugging Face önbellek dizinini kontrol et
du -sh ~/.cache/huggingface/
du -sh ~/.cache/huggingface/datasets/
du -sh ~/.cache/huggingface/hub/

# Hangi veri setleri önbellekte var?
ls -la ~/.cache/huggingface/datasets/

# Belirli bir veri setinin önbelleğini temizle
# (Önce Python'dan)
python3 << 'EOF'
from datasets import load_dataset

dataset = load_dataset("imdb", split="train[:10]")
# Önbellek bilgisini görüntüle
print("Önbellek dosyaları:")
for cache_file in dataset.cache_files:
    print(f"  {cache_file['filename']}")
EOF

# Tüm dataset önbelleğini temizle (dikkatli kullanın!)
# rm -rf ~/.cache/huggingface/datasets/

# Sadece belirli bir veri setini temizle
# rm -rf ~/.cache/huggingface/datasets/imdb*/

Python tarafında önbellek yönetimi:

python3 << 'EOF'
from datasets import load_dataset
from datasets.utils.file_utils import get_datasets_user_agent
import os

# Önbellek dizinini özelleştir (production için önemli)
os.environ["HF_DATASETS_CACHE"] = "/data/hf_cache/datasets"
os.environ["HF_HOME"] = "/data/hf_cache"

# Önbelleği devre dışı bırak (her seferinde yeniden indir)
# load_dataset("imdb", download_mode="force_redownload")

# Sadece önbellekten yükle, indirme yapma
try:
    dataset = load_dataset("imdb", download_mode="reuse_cache_if_exists", split="train[:5]")
    print("Önbellekten yüklendi")
    print(dataset.info.dataset_name)
except Exception as e:
    print(f"Önbellekte bulunamadı: {e}")
EOF

Kimlik Doğrulama ve Private Veri Setleri

Kurumsal ortamlarda private repo’larla çalışmak yaygındır. Hugging Face token yönetimi:

# CLI ile login
huggingface-cli login
# Token'ı gir

# Veya environment variable ile (CI/CD için ideal)
export HUGGING_FACE_HUB_TOKEN="hf_xxxxxxxxxxxx"

# .env dosyasına ekle (güvenli bir yere koy)
echo "HUGGING_FACE_HUB_TOKEN=hf_xxxxxxxxxxxx" >> ~/.env
python3 << 'EOF'
import os
from datasets import load_dataset
from huggingface_hub import login

# Token ile login (CI/CD ortamları için)
token = os.environ.get("HUGGING_FACE_HUB_TOKEN")
if token:
    login(token=token)
    print("Login başarılı")

# Private veri seti yükle
# dataset = load_dataset("organization/private-dataset", token=token)

# Kendi yüklenmiş veri setini Hub'a push et
# (Public bir örnek)
# dataset.push_to_hub("kullanici-adi/veri-seti-adi", private=True)
print("Token tabanlı erişim yapılandırıldı")
EOF

Performans İpuçları ve Production Notları

Gerçek ortamlarda karşılaştığım bazı önemli noktalar:

  • Arrow formatı: Veri setlerini save_to_disk() ile kaydedin. to_csv() veya to_json() yerine Arrow formatı çok daha hızlı okuma/yazma sağlar.
  • num_proc parametresi: map ve filter işlemlerinde CPU sayısının yarısını kullanmak genel kural olarak güvenlidir. Tüm çekirdekleri vermek diğer system proseslerini etkileyebilir.
  • batch_size: Bellek kısıtlı ortamlarda batch_size=64 veya 128 başlangıç için güvenlidir. GPU’ya veri beslerken batch_size=1000+ değerleri düşünülebilir.
  • Disk alanı takibi: Büyük veri setleri önbellekleyince /tmp veya home dizini dolabilir. HF_DATASETS_CACHE env variable’ını ayrı bir partition’a yönlendirin.
  • Network timeout: Yavaş bağlantılarda indirme kesilirse DATASETS_VERBOSITY=debug ile loglayın ve resume_download=True kullanın.
  • Reproducibility: shuffle(seed=42) ile sabit seed kullanmak deneyler arası tutarlılığı sağlar.
  • Token güvenliği: HF token’ını asla koda hardcode etmeyin, her zaman environment variable veya ~/.cache/huggingface/token dosyasını kullanın.

Sonuç

Hugging Face datasets kütüphanesi, veri mühendisliği workflow’unu kökten değiştiren bir araç. Hub üzerindeki on binlerce hazır veri setine tek satır kodla erişmek, streaming modu ile terabayt veriye RAM sınırı olmaksızın ulaşmak ve Arrow formatının sağladığı performans kazanımları, bu kütüphaneyi hem araştırma hem de production ortamlarında birinci tercih haline getiriyor.

Özellikle Türkçe NLP projeleri üzerinde çalışıyorsanız çok dilli veri setlerinden yararlanmak, kendi yerel verilerinizle Hub kaynaklarını birleştirmek ve sonucu Hub’a geri push etmek ile açık kaynak ekosisteme katkı sağlamak mümkün. Bir sonraki adım olarak datasets kütüphanesini transformers ile entegre ederek tam bir fine-tuning pipeline kurabilirsiniz. O konuyu da ayrı bir yazıda ele alacağız.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir