Transformers documentation

Token sınıflandırma

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

and get access to the augmented documentation experience

to get started

Token sınıflandırma

Token sınıflandırma, bir cümledeki bireysel token'lara bir etiket atar. Token sınıflandırma görevlerinin en yaygınlarından biri Adlandırılmış Varlık Tanıma (NER)'dır. NER, bir cümledeki her varlık için kişi, konum veya kuruluş gibi bir etiket bulmaya çalışır.

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

  1. Yeni varlıkları tespit etmek için WNUT 17 veri setinde DistilBERT'yi ince ayarlayın.
  2. İnce ayarlanmış modelinizi çıkarım için kullanın.

Bu görevle uyumlu tüm mimarileri ve denetim noktalarını görmek için görev sayfasını kontrol etmenizi öneririz.

Başlamadan önce, gerekli tüm kütüphanelerin yüklendiğinden emin olun:

pip install transformers datasets evaluate seqeval

Modelinizi yükleyip toplulukla paylaşabilmeniz için Hugging Face hesabınıza giriş yapmanızı öneririz. İstendiğinde giriş yapmak için token'ınızı girin:

>>> from huggingface_hub import notebook_login

>>> notebook_login()

WNUT 17 veri setini yükle

🤗 Datasets kütüphanesinden WNUT 17 veri setini yükleyerek başlayın:

>>> from datasets import load_dataset

>>> wnut = load_dataset("flaitenberger/wnut_17")

Sonra bir örneğe göz atın:

>>> wnut["train"][0]
{'id': '0',
 'ner_tags': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0],
 'tokens': ['@paulwalk', 'It', "'s", 'the', 'view', 'from', 'where', 'I', "'m", 'living', 'for', 'two', 'weeks', '.', 'Empire', 'State', 'Building', '=', 'ESB', '.', 'Pretty', 'bad', 'storm', 'here', 'last', 'evening', '.']
}

ner_tags içindeki her sayı bir varlığı temsil eder. Varlıkların ne olduğunu bulmak için sayıları etiket adlarına dönüştürün:

>>> label_list = wnut["train"].features[f"ner_tags"].feature.names
>>> label_list
[
    "O",
    "B-corporation",
    "I-corporation",
    "B-creative-work",
    "I-creative-work",
    "B-group",
    "I-group",
    "B-location",
    "I-location",
    "B-person",
    "I-person",
    "B-product",
    "I-product",
]

Her ner_tag'ın başındaki harf, varlığın token konumunu belirtir:

  • B-, bir varlığın başlangıcını belirtir.
  • I-, bir token'ın aynı varlığın içinde yer aldığını belirtir (örneğin, State token'ı, Empire State Building gibi bir varlığın parçasıdır).
  • 0, token'ın herhangi bir varlığa karşılık gelmediğini belirtir.

Ön işleme

Bir sonraki adım, tokens alanını ön işlemek için bir DistilBERT tokenizer yüklemektir:

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")

Yukarıdaki örnekte tokens alanına baktığınızda, girdinin zaten tokenize edilmiş gibi göründüğünü fark edebilirsiniz. Ancak girdi henüz tokenize edilmedi ve kelimeleri alt kelimelere (subword) bölmek için is_split_into_words=True değerini ayarlamanız gerekir. Örneğin:

>>> example = wnut["train"][0]
>>> tokenized_input = tokenizer(example["tokens"], is_split_into_words=True)
>>> tokens = tokenizer.convert_ids_to_tokens(tokenized_input["input_ids"])
>>> tokens
['[CLS]', '@', 'paul', '##walk', 'it', "'", 's', 'the', 'view', 'from', 'where', 'i', "'", 'm', 'living', 'for', 'two', 'weeks', '.', 'empire', 'state', 'building', '=', 'es', '##b', '.', 'pretty', 'bad', 'storm', 'here', 'last', 'evening', '.', '[SEP]']

Ancak bu, [CLS] ve [SEP] gibi bazı özel jetonlar ekler ve alt kelime (subword) jetonlaştırmada girdi ile etiketler arasında bir uyumsuzluk yaratır. Tek bir etikete karşılık gelen tek bir kelime artık iki alt kelimeye bölünebilir. Jetonları ve etiketleri yeniden hizalamak için şunları yapmanız gerekir:

  1. word_ids yöntemiyle tüm jetonları ilgili kelimelerine eşleme.
  2. Özel jetonlar [CLS] ve [SEP] için -100 etiketini atayarak, PyTorch kayıp fonksiyonu tarafından yok sayılmalarını sağlanır (bkz. CrossEntropyLoss).
  3. Sadece verilen bir kelimenin ilk token'ını etiketleme. Aynı kelimeden gelen diğer alt token'lara -100 atama.

DistilBERT'in maksimum giriş uzunluğunu aşmayacak şekilde dizileri kısaltmak ve jetonları ile etiketleri yeniden hizalamak için bir fonksiyon oluşturmanın yolu aşağıdaki gibidir:

>>> def tokenize_and_align_labels(examples):
...     tokenized_inputs = tokenizer(examples["tokens"], truncation=True, is_split_into_words=True)

...     labels = []
...     for i, label in enumerate(examples[f"ner_tags"]):
...         word_ids = tokenized_inputs.word_ids(batch_index=i)  # Map tokens to their respective word.
...         previous_word_idx = None
...         label_ids = []
...         for word_idx in word_ids:  # Set the special tokens to -100.
...             if word_idx is None:
...                 label_ids.append(-100)
...             elif word_idx != previous_word_idx:  # Only label the first token of a given word.
...                 label_ids.append(label[word_idx])
...             else:
...                 label_ids.append(-100)
...             previous_word_idx = word_idx
...         labels.append(label_ids)

...     tokenized_inputs["labels"] = labels
...     return tokenized_inputs

Tüm veri setine ön işleme fonksiyonunu uygulamak için 🤗 Datasets map fonksiyonunu kullanın. map fonksiyonunu, veri setinin birden çok öğesini aynı anda işlemek için batched=True değerini ayarlayarak hızlandırabilirsiniz:

>>> tokenized_wnut = wnut.map(tokenize_and_align_labels, batched=True)

Şimdi DataCollatorWithPadding kullanarak örneklerden oluşan bir batch oluşturun. Veri setinin tamamını maksimum uzunluğa kadar doldurmak yerine, collation sırasında cümleleri batch içindeki en uzun uzunluğa dinamik olarak doldurmak daha verimlidir.

>>> from transformers import DataCollatorForTokenClassification

>>> data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer)

Değerlendir

Eğitim sırasında bir metrik kullanmak, modelinizin performansını değerlendirmek için genellikle faydalıdır. 🤗 Evaluate kütüphanesiyle bir değerlendirme yöntemini hızla yükleyebilirsiniz. Bu görev için seqeval çerçevesini yükleyin (bir metriğin nasıl yükleneceğini ve hesaplanacağını öğrenmek için 🤗 Evaluate hızlı turuna bakın). Seqeval aslında birkaç puan üretir: hassasiyet (precision), geri çağırma (recall), F1 ve doğruluk (accuracy).

>>> import evaluate

>>> seqeval = evaluate.load("seqeval")

Önce NER etiketlerini alın, ardından gerçek tahminlerinizi ve gerçek etiketlerinizi compute fonksiyonuna geçirerek puanları hesaplayan bir fonksiyon oluşturun:

>>> import numpy as np

>>> labels = [label_list[i] for i in example[f"ner_tags"]]


>>> def compute_metrics(p):
...     predictions, labels = p
...     predictions = np.argmax(predictions, axis=2)

...     true_predictions = [
...         [label_list[p] for (p, l) in zip(prediction, label) if l != -100]
...         for prediction, label in zip(predictions, labels)
...     ]
...     true_labels = [
...         [label_list[l] for (p, l) in zip(prediction, label) if l != -100]
...         for prediction, label in zip(predictions, labels)
...     ]

...     results = seqeval.compute(predictions=true_predictions, references=true_labels)
...     return {
...         "precision": results["overall_precision"],
...         "recall": results["overall_recall"],
...         "f1": results["overall_f1"],
...         "accuracy": results["overall_accuracy"],
...     }

compute_metrics fonksiyonunuz artık hazır ve eğitiminizi kurarken ona geri döneceksiniz.

Eğit

Modelinizi eğitmeye başlamadan önce, id2label ve label2id ile beklenen kimliklerin etiketlere eşlenmesini oluşturun:

>>> id2label = {
...     0: "O",
...     1: "B-corporation",
...     2: "I-corporation",
...     3: "B-creative-work",
...     4: "I-creative-work",
...     5: "B-group",
...     6: "I-group",
...     7: "B-location",
...     8: "I-location",
...     9: "B-person",
...     10: "I-person",
...     11: "B-product",
...     12: "I-product",
... }
>>> label2id = {
...     "O": 0,
...     "B-corporation": 1,
...     "I-corporation": 2,
...     "B-creative-work": 3,
...     "I-creative-work": 4,
...     "B-group": 5,
...     "I-group": 6,
...     "B-location": 7,
...     "I-location": 8,
...     "B-person": 9,
...     "I-person": 10,
...     "B-product": 11,
...     "I-product": 12,
... }

Trainer ile bir modeli ince ayar yapma konusunda deneyiminiz yoksa, temel öğreticiyi burada inceleyebilirsiniz!

Artık modelinizi eğitmeye hazırsınız! AutoModelForTokenClassification ile DistilBERT'i, beklenen etiket sayısı ve etiket eşlemeleriyle birlikte yükleyin:

>>> from transformers import AutoModelForTokenClassification, TrainingArguments, Trainer

>>> model = AutoModelForTokenClassification.from_pretrained(
...     "distilbert/distilbert-base-uncased", num_labels=13, id2label=id2label, label2id=label2id
... )

Bu noktada yalnızca üç adım kaldı:

  1. Eğitim hiperparametrelerinizi TrainingArguments içinde tanımlayın. Tek zorunlu parametre, modelin nereye kaydedileceğini belirleyen output_dir'dir. Modeli Hub'a push_to_hub=True ayarlayarak yükleyeceksiniz (modelinizi yüklemek için Hugging Face hesabına giriş yapmış olmanız gerekir). Her epoch'un sonunda Trainer, seqeval skorlarını değerlendirir ve eğitim checkpoint'ini kaydeder.
  2. Eğitim argümanlarını, model, veri seti, tokenizer, veri toplayıcı ve compute_metrics fonksiyonuyla birlikte Trainer'a iletin.
  3. Modelinizi ince ayar yapmak için train() çağrın.
>>> training_args = TrainingArguments(
...     output_dir="my_awesome_wnut_model",
...     learning_rate=2e-5,
...     per_device_train_batch_size=16,
...     per_device_eval_batch_size=16,
...     num_train_epochs=2,
...     weight_decay=0.01,
...     eval_strategy="epoch",
...     save_strategy="epoch",
...     load_best_model_at_end=True,
...     push_to_hub=True,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     train_dataset=tokenized_wnut["train"],
...     eval_dataset=tokenized_wnut["test"],
...     processing_class=tokenizer,
...     data_collator=data_collator,
...     compute_metrics=compute_metrics,
... )

>>> trainer.train()

Eğitim tamamlandıktan sonra, modelinizi herkesin kullanabilmesi için push_to_hub() yöntemiyle Hub'a paylaşın:

>>> trainer.push_to_hub()

Bir modeli token sınıflandırma için ince ayar yapmanın daha ayrıntılı bir örneği için ilgili PyTorch defterine göz atın.

Çıkarım

Harika, bir model ayarladıktan sonra artık çıkarım için kullanabilirsiniz!

Çıkarım (inference) çalıştırmak istediğiniz bazı metin alın:

>>> text = "The Golden State Warriors are an American professional basketball team based in San Francisco."

Eğitimini tamamladığınız modeli çıkarım için denemenin en basit yolu, onu bir pipeline() içinde kullanmaktır. Modelinizi kullanarak NER için bir pipeline örneği oluşturun ve metninizi ona iletin:

>>> from transformers import pipeline

>>> classifier = pipeline("ner", model="stevhliu/my_awesome_wnut_model")
>>> classifier(text)
[{'entity': 'B-location',
  'score': 0.42658573,
  'index': 2,
  'word': 'golden',
  'start': 4,
  'end': 10},
 {'entity': 'I-location',
  'score': 0.35856336,
  'index': 3,
  'word': 'state',
  'start': 11,
  'end': 16},
 {'entity': 'B-group',
  'score': 0.3064001,
  'index': 4,
  'word': 'warriors',
  'start': 17,
  'end': 25},
 {'entity': 'B-location',
  'score': 0.65523505,
  'index': 13,
  'word': 'san',
  'start': 80,
  'end': 83},
 {'entity': 'B-location',
  'score': 0.4668663,
  'index': 14,
  'word': 'francisco',
  'start': 84,
  'end': 93}]

İsterseniz pipeline sonuçlarını manuel olarak da yeniden üretebilirsiniz:

Metni tokenleştirin ve PyTorch tensörlerini döndürün:

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("stevhliu/my_awesome_wnut_model")
>>> inputs = tokenizer(text, return_tensors="pt")

Girdilerinizi modele iletin ve logits değerlerini döndürün:

>>> from transformers import AutoModelForTokenClassification

>>> model = AutoModelForTokenClassification.from_pretrained("stevhliu/my_awesome_wnut_model")
>>> with torch.no_grad():
...     logits = model(**inputs).logits

En yüksek olasılığa sahip sınıfı alın ve modelin id2label eşlemesini kullanarak bunu bir metin etiketine dönüştürün:

>>> predictions = torch.argmax(logits, dim=2)
>>> predicted_token_class = [model.config.id2label[t.item()] for t in predictions[0]]
>>> predicted_token_class
['O',
 'O',
 'B-location',
 'I-location',
 'B-group',
 'O',
 'O',
 'O',
 'O',
 'O',
 'O',
 'O',
 'O',
 'B-location',
 'B-location',
 'O',
 'O']
Update on GitHub