Transformers documentation
Maskeli dil modellemesi
Maskeli dil modellemesi
Masked language modeling, bir dizideki maskelenmiş bir token'ı tahmin eder ve model token'lara çift yönlü olarak dikkat edebilir. Bu, modelin solundaki ve sağındaki token'lara tam erişime sahip olduğu anlamına gelir. Masked language modeling, bir dizinin tamamına ilişkin iyi bir bağlamsal anlama gerektiren görevler için idealdir. BERT, bir masked language model örneğidir.
Bu kılavuz size şunları gösterecektir:
- ELI5 veri setinin r/askscience alt kümesinde DistilRoBERTa modelini ince ayarlayın.
- İ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
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()ELI5 veri setini yükle
Önce 🤗 Datasets kütüphanesiyle ELI5-Category veri setinden ilk 5000 örneği yükleyerek başlayın. Bu, tam veri setinde eğitim için daha fazla zaman harcamadan önce deneyler yapmanıza ve her şeyin çalıştığını doğrulamanıza olanak tanır.
>>> from datasets import load_dataset
>>> eli5 = load_dataset("dany0407/eli5_category", split="train[:5000]")Veri setinin train bölümünü train_test_split yöntemiyle eğitim ve test kümesine ayırın:
>>> eli5 = eli5.train_test_split(test_size=0.2)Sonra bir örneğe göz atın:
>>> eli5["train"][0]
{'q_id': '7h191n',
'title': 'What does the tax bill that was passed today mean? How will it affect Americans in each tax bracket?',
'selftext': '',
'category': 'Economics',
'subreddit': 'explainlikeimfive',
'answers': {'a_id': ['dqnds8l', 'dqnd1jl', 'dqng3i1', 'dqnku5x'],
'text': ["The tax bill is 500 pages long and there were a lot of changes still going on right to the end. It's not just an adjustment to the income tax brackets, it's a whole bunch of changes. As such there is no good answer to your question. The big take aways are: - Big reduction in corporate income tax rate will make large companies very happy. - Pass through rate change will make certain styles of business (law firms, hedge funds) extremely happy - Income tax changes are moderate, and are set to expire (though it's the kind of thing that might just always get re-applied without being made permanent) - People in high tax states (California, New York) lose out, and many of them will end up with their taxes raised.",
'None yet. It has to be reconciled with a vastly different house bill and then passed again.',
'Also: does this apply to 2017 taxes? Or does it start with 2018 taxes?',
'This article explains both the House and senate bills, including the proposed changes to your income taxes based on your income level. URL_0'],
'score': [21, 19, 5, 3],
'text_urls': [[],
[],
[],
['https://www.investopedia.com/news/trumps-tax-reform-what-can-be-done/']]},
'title_urls': ['url'],
'selftext_urls': ['url']}Bu çok fazla görünse de, asıl ilgilendiğiniz alan text alanıdır. Dil modelleme görevlerinin güzel yanı, etiketlere (ayrıca denetimsiz görev olarak da bilinir) ihtiyaç duymamanızdır; çünkü bir sonraki kelime etikettir.
Ön işleme
Maskeli dil modellemesi için bir sonraki adım, text alt alanını işlemek üzere bir DistilRoBERTa tokenizer yüklemektir:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilroberta-base")Yukarıdaki örnekte, text alanının aslında answers içinde iç içe geçmiş olduğunu göreceksiniz. Bu, text alt alanını iç içe geçmiş yapısından flatten metoduyla çıkarmanız gerektiği anlamına gelir:
>>> eli5 = eli5.flatten()
>>> eli5["train"][0]
{'q_id': '7h191n',
'title': 'What does the tax bill that was passed today mean? How will it affect Americans in each tax bracket?',
'selftext': '',
'category': 'Economics',
'subreddit': 'explainlikeimfive',
'answers.a_id': ['dqnds8l', 'dqnd1jl', 'dqng3i1', 'dqnku5x'],
'answers.text': ["The tax bill is 500 pages long and there were a lot of changes still going on right to the end. It's not just an adjustment to the income tax brackets, it's a whole bunch of changes. As such there is no good answer to your question. The big take aways are: - Big reduction in corporate income tax rate will make large companies very happy. - Pass through rate change will make certain styles of business (law firms, hedge funds) extremely happy - Income tax changes are moderate, and are set to expire (though it's the kind of thing that might just always get re-applied without being made permanent) - People in high tax states (California, New York) lose out, and many of them will end up with their taxes raised.",
'None yet. It has to be reconciled with a vastly different house bill and then passed again.',
'Also: does this apply to 2017 taxes? Or does it start with 2018 taxes?',
'This article explains both the House and senate bills, including the proposed changes to your income taxes based on your income level. URL_0'],
'answers.score': [21, 19, 5, 3],
'answers.text_urls': [[],
[],
[],
['https://www.investopedia.com/news/trumps-tax-reform-what-can-be-done/']],
'title_urls': ['url'],
'selftext_urls': ['url']}Her alt alan, answers önekiyle belirtildiği üzere artık ayrı bir sütundur ve text alanı artık bir listedir. Her cümleyi ayrı ayrı tokenleştirmek yerine, listeyi bir dizeye dönüştürerek bunları birlikte tokenleştirebilirsiniz.
Her örnek için string listesini birleştirip sonucu tokenlaştıran ilk ön işleme fonksiyonu aşağıdadır:
>>> def preprocess_function(examples):
... return tokenizer([" ".join(x) for x in examples["answers.text"]])Bu ön işleme fonksiyonunu tüm veri setine uygulamak için 🤗 Datasets map yöntemini kullanın. map fonksiyonunu, veri setinin birden çok öğesini aynı anda işlemek için batched=True ayarlayarak ve num_proc ile işlem sayısını artırarak hızlandırabilirsiniz. İhtiyacınız olmayan sütunları kaldırın:
>>> tokenized_eli5 = eli5.map(
... preprocess_function,
... batched=True,
... num_proc=4,
... remove_columns=eli5["train"].column_names,
... )Bu veri seti token dizilerini içerir, ancak bunlardan bazıları modelin maksimum giriş uzunluğundan daha uzundur.
Artık ikinci bir ön işleme işlevi kullanabilirsiniz
- tüm dizileri birleştirin
- Birleştirilen dizileri,
block_sizeile tanımlanan ve hem maksimum giriş uzunluğundan kısa hem de GPU RAM'iniz için yeterince kısa olan daha kısa parçalara ayırın.
>>> block_size = 128
>>> def group_texts(examples):
... # Concatenate all texts.
... concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
... total_length = len(concatenated_examples[list(examples.keys())[0]])
... # We drop the small remainder, we could add padding if the model supported it instead of this drop, you can
... # customize this part to your needs.
... if total_length >= block_size:
... total_length = (total_length // block_size) * block_size
... # Split by chunks of block_size.
... result = {
... k: [t[i : i + block_size] for i in range(0, total_length, block_size)]
... for k, t in concatenated_examples.items()
... }
... return resultTüm veri seti üzerinde group_texts fonksiyonunu uygulayın:
>>> lm_dataset = tokenized_eli5.map(group_texts, batched=True, num_proc=4)Şimdi DataCollatorForLanguageModeling kullanarak örneklerden oluşan bir batch oluşturun. Toplama sırasında cümleleri batch içindeki en uzun uzunluğa dinamik olarak doldurmak, tüm veri setini maksimum uzunluğa doldurmaktan daha verimlidir.
Dizinin sonundaki token'ı dolgu token'ı olarak kullanın ve verinin üzerinde her yinelemede token'ları rastgele maskelemek için mlm_probability parametresini belirtin:
>>> from transformers import DataCollatorForLanguageModeling
>>> tokenizer.pad_token = tokenizer.eos_token
>>> data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm_probability=0.15)Eğit
Trainer ile bir modeli ince ayar yapma konusunda deneyiminiz yoksa, temel öğreticiyi burada inceleyebilirsiniz!
Artık modelinizi eğitmeye hazırsınız! DistilRoBERTa'yı AutoModelForMaskedLM ile yükleyin:
>>> from transformers import AutoModelForMaskedLM
>>> model = AutoModelForMaskedLM.from_pretrained("distilbert/distilroberta-base")Bu noktada yalnızca üç adım kaldı:
- Eğitim hiperparametrelerinizi TrainingArguments içinde tanımlayın. Tek zorunlu parametre, modelinizi nereye kaydedeceğinizi belirleyen
output_dir'dir. Modelinizi Hub'apush_to_hub=Trueayarlayarak yükleyeceksiniz (modelinizi yüklemek için Hugging Face'e giriş yapmış olmanız gerekir). - Eğitim argümanlarını, model, veri kümeleri ve veri toplayıcıyla birlikte Trainer'a iletin.
- Modelinizi ince ayar yapmak için train() çağrın.
>>> training_args = TrainingArguments(
... output_dir="my_awesome_eli5_mlm_model",
... eval_strategy="epoch",
... learning_rate=2e-5,
... num_train_epochs=3,
... weight_decay=0.01,
... push_to_hub=True,
... )
>>> trainer = Trainer(
... model=model,
... args=training_args,
... train_dataset=lm_dataset["train"],
... eval_dataset=lm_dataset["test"],
... data_collator=data_collator,
... processing_class=tokenizer,
... )
>>> trainer.train()Eğitim tamamlandıktan sonra, modelinizi değerlendirmek ve perplexity değerini almak için evaluate() yöntemini kullanın:
>>> import math
>>> eval_results = trainer.evaluate()
>>> print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}")
Perplexity: 8.76Sonra modelinizi herkesin kullanabilmesi için push_to_hub() yöntemiyle Hub'a paylaşın:
>>> trainer.push_to_hub()Maskeli dil modelleme için bir modelin nasıl ince ayar yapılacağına dair daha ayrıntılı bir örnek için ilgili PyTorch defterine göz atın.
Çıkarım
Harika, bir model ayarladıktan sonra artık çıkarım için kullanabilirsiniz!
Modelin boşluğu doldurmasını istediğiniz bir metin oluşturun ve boşluğu belirtmek için <mask> özel jetonunu kullanın:
>>> text = "The Milky Way is a <mask> galaxy."Fincinize edilmiş modelinizi çıkarım için denemenin en basit yolu, onu bir pipeline() içinde kullanmaktır. Modeliniz için fill-mask amaçlı bir pipeline örneği oluşturun ve metninizi ona iletin. İsterseniz, kaç tahminin döndürüleceğini belirtmek için top_k parametresini kullanabilirsiniz:
>>> from transformers import pipeline
>>> mask_filler = pipeline("fill-mask", "username/my_awesome_eli5_mlm_model")
>>> mask_filler(text, top_k=3)
[{'score': 0.5150994658470154,
'token': 21300,
'token_str': ' spiral',
'sequence': 'The Milky Way is a spiral galaxy.'},
{'score': 0.07087188959121704,
'token': 2232,
'token_str': ' massive',
'sequence': 'The Milky Way is a massive galaxy.'},
{'score': 0.06434620916843414,
'token': 650,
'token_str': ' small',
'sequence': 'The Milky Way is a small galaxy.'}]Metni tokenize edin ve input_ids değerlerini PyTorch tensörleri olarak döndürün. Ayrıca <mask> token'ının konumunu belirtmeniz gerekecektir:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("username/my_awesome_eli5_mlm_model")
>>> inputs = tokenizer(text, return_tensors="pt")
>>> mask_token_index = torch.where(inputs["input_ids"] == tokenizer.mask_token_id)[1]Girdilerinizi modele iletin ve maskelenmiş token'ın logits değerlerini döndürün:
>>> from transformers import AutoModelForMaskedLM
>>> model = AutoModelForMaskedLM.from_pretrained("username/my_awesome_eli5_mlm_model")
>>> logits = model(**inputs).logits
>>> mask_token_logits = logits[0, mask_token_index, :]Ardından, en yüksek olasılığa sahip üç maskelenmiş token'ı döndürün ve bunları yazdırın:
>>> top_3_tokens = torch.topk(mask_token_logits, 3, dim=1).indices[0].tolist()
>>> for token in top_3_tokens:
... print(text.replace(tokenizer.mask_token, tokenizer.decode([token])))
The Milky Way is a spiral galaxy.
The Milky Way is a massive galaxy.
The Milky Way is a small galaxy.