Transformers documentation

إجابة الأسئلة

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

إجابة الأسئلة

تُعيد مهام الإجابة عن الأسئلة إجابةً محددة بناءً على سؤال معيّن. إذا سبق لك أن سألت مساعداً افتراضياً مثل Alexa أو Siri أو Google عن حالة الطقس، فقد تكون قد استخدمت نموذجاً للإجابة عن الأسئلة من قبل. هناك نوعان شائعان من مهام الإجابة عن الأسئلة:

  • استخراجي: استخراج الإجابة من السياق المُعطى.
  • التوليد التلخيصي: توليد إجابة من السياق تجيب بشكل صحيح على السؤال.

ستُظهر لك هذه الدليل كيفية:

  1. قم بضبط DistilBERT على مجموعة بيانات SQuAD للإجابة الاستخراجية على الأسئلة.
  2. استخدم النموذج المُحسَّن لديك للاستدلال.

للاطلاع على جميع البنى المعمارية ونقاط التفتيش المتوافقة مع هذه المهمة، ننصح بالتحقق من صفحة المهمة

قبل أن تبدأ، تأكد من تثبيت جميع المكتبات اللازمة:

pip install transformers datasets evaluate

ننصحك بتسجيل الدخول إلى حسابك على Hugging Face حتى تتمكن من رفع نموذجك ومشاركته مع المجتمع. عند الطلب، أدخل رمزك (token) لتسجيل الدخول:

>>> from huggingface_hub import notebook_login

>>> notebook_login()

تحميل مجموعة بيانات SQuAD

ابدأ بتحميل مجموعة فرعية أصغر من مجموعة بيانات SQuAD من مكتبة 🤗 Datasets. سيمنحك هذا فرصة للتجربة والتأكد من عمل كل شيء بشكل صحيح قبل قضاء مزيد من الوقت في التدريب على مجموعة البيانات الكاملة.

>>> from datasets import load_dataset

>>> squad = load_dataset("rajpurkar/squad", split="train[:5000]")

قسّم مجموعة train من مجموعة البيانات إلى مجموعة تدريب ومجموعة اختبار باستخدام طريقة train_test_split:

>>> squad = squad.train_test_split(test_size=0.2)

ثم اطّلع على مثال:

>>> squad["train"][0]
{'answers': {'answer_start': [515], 'text': ['Saint Bernadette Soubirous']},
 'context': 'Architecturally, the school has a Catholic character. Atop the Main Building\'s gold dome is a golden statue of the Virgin Mary. Immediately in front of the Main Building and facing it, is a copper statue of Christ with arms upraised with the legend "Venite Ad Me Omnes". Next to the Main Building is the Basilica of the Sacred Heart. Immediately behind the basilica is the Grotto, a Marian place of prayer and reflection. It is a replica of the grotto at Lourdes, France where the Virgin Mary reputedly appeared to Saint Bernadette Soubirous in 1858. At the end of the main drive (and in a direct line that connects through 3 statues and the Gold Dome), is a simple, modern stone statue of Mary.',
 'id': '5733be284776f41900661182',
 'question': 'To whom did the Virgin Mary allegedly appear in 1858 in Lourdes France?',
 'title': 'University_of_Notre_Dame'
}

توجد هنا عدة حقول مهمة:

  • answers: موقع بداية رمز الإجابة ونص الإجابة.
  • context: معلومات خلفية يحتاج النموذج إلى استخراج الإجابة منها.
  • question: السؤال الذي يجب على النموذج الإجابة عنه.

المعالجة المسبقة

الخطوة التالية هي تحميل مُرمِّز DistilBERT لمعالجة حقلي question وcontext:

>>> from transformers import AutoTokenizer

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

هناك بعض خطوات المعالجة المسبقة الخاصة بمهام الإجابة على الأسئلة يجب أن تكون على دراية بها:

  1. قد تحتوي بعض الأمثلة في مجموعة البيانات على context طويل جداً يتجاوز الحد الأقصى لطول الإدخال للنموذج. للتعامل مع التسلسلات الأطول، قم بقص context فقط عن طريق تعيين truncation="only_second".
  2. بعد ذلك، قم بربط مواضع البداية والنهاية للإجابة بالنص الأصلي context من خلال تعيين return_offset_mapping=True.
  3. بمجرد الحصول على الترميز، يمكنك الآن تحديد توكنات بداية وإجابة النهاية. استخدم طريقة sequence_ids للعثور على الجزء من الإزاحة الذي يتوافق مع question والجزء الذي يتوافق مع context.

إليك كيفية إنشاء دالة لقصّ رموز البداية والنهاية الخاصة بـanswer وتعيينها إلى context:

>>> def preprocess_function(examples):
...     questions = [q.strip() for q in examples["question"]]
...     inputs = tokenizer(
...         questions,
...         examples["context"],
...         max_length=384,
...         truncation="only_second",
...         return_offsets_mapping=True,
...         padding="max_length",
...     )

...     offset_mapping = inputs.pop("offset_mapping")
...     answers = examples["answers"]
...     start_positions = []
...     end_positions = []

...     for i, offset in enumerate(offset_mapping):
...         answer = answers[i]
...         start_char = answer["answer_start"][0]
...         end_char = answer["answer_start"][0] + len(answer["text"][0])
...         sequence_ids = inputs.sequence_ids(i)

...         # Find the start and end of the context
...         idx = 0
...         while sequence_ids[idx] != 1:
...             idx += 1
...         context_start = idx
...         while sequence_ids[idx] == 1:
...             idx += 1
...         context_end = idx - 1

...         # If the answer is not fully inside the context, label it (0, 0)
...         if offset[context_start][0] > end_char or offset[context_end][1] < start_char:
...             start_positions.append(0)
...             end_positions.append(0)
...         else:
...             # Otherwise it's the start and end token positions
...             idx = context_start
...             while idx <= context_end and offset[idx][0] <= start_char:
...                 idx += 1
...             start_positions.append(idx - 1)

...             idx = context_end
...             while idx >= context_start and offset[idx][1] >= end_char:
...                 idx -= 1
...             end_positions.append(idx + 1)

...     inputs["start_positions"] = start_positions
...     inputs["end_positions"] = end_positions
...     return inputs

لتطبيق دالة المعالجة المسبقة على مجموعة البيانات بأكملها، استخدم دالة map في 🤗 Datasets. يمكنك تسريع دالة map عن طريق تعيين batched=True لمعالجة عدة عناصر من مجموعة البيانات في وقت واحد. احذف أي أعمدة لا تحتاج إليها:

>>> tokenized_squad = squad.map(preprocess_function, batched=True, remove_columns=squad["train"].column_names)

الآن أنشئ دفعة من الأمثلة باستخدام DefaultDataCollator. على عكس مُجمِّعات البيانات الأخرى في 🤗 Transformers، لا يطبّق DefaultDataCollator أي معالجة مسبقة إضافية مثل الحشو (padding).

>>> from transformers import DefaultDataCollator

>>> data_collator = DefaultDataCollator()

تدريب

إذا لم تكن على دراية بتدريب نموذج باستخدام Trainer، فاطّلع على الدرس الأساسي هنا!

أنت مستعد الآن لبدء تدريب نموذجك! حمّل DistilBERT باستخدام AutoModelForQuestionAnswering:

>>> from transformers import AutoModelForQuestionAnswering, TrainingArguments, Trainer

>>> model = AutoModelForQuestionAnswering.from_pretrained("distilbert/distilbert-base-uncased")

في هذه المرحلة، تبقى ثلاث خطوات فقط:

  1. حدّد معاملات التدريب الفائقة في TrainingArguments. المعامل الوحيد الإلزامي هو output_dir الذي يحدد مكان حفظ النموذج. ستقوم بدفع هذا النموذج إلى Hub عن طريق تعيين push_to_hub=True (يتعين عليك تسجيل الدخول إلى Hugging Face لرفع النموذج).
  2. مرّر حُجج التدريب إلى Trainer مع النموذج، ومجموعة البيانات، ومُجزّئ الرموز، ومُجمِّع البيانات.
  3. استدعِ train() لضبط نموذجك.
>>> training_args = TrainingArguments(
...     output_dir="my_awesome_qa_model",
...     eval_strategy="epoch",
...     learning_rate=2e-5,
...     per_device_train_batch_size=16,
...     per_device_eval_batch_size=16,
...     num_train_epochs=3,
...     weight_decay=0.01,
...     push_to_hub=True,
... )

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

>>> trainer.train()

بمجرد اكتمال التدريب، شارك نموذجك على Hub باستخدام طريقة push_to_hub() ليتمكن الجميع من استخدام نموذجك:

>>> trainer.push_to_hub()

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

تقييم

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

إذا كان لديك المزيد من الوقت وتُهمّك طريقة تقييم نموذجك للإجابة على الأسئلة، فتعرّف على فصل الإجابة على الأسئلة من دورة 🤗 Hugging Face!

الاستدلال

رائع، والآن بعد أن قمت بضبط نموذج، يمكنك استخدامه للاستدلال!

فكّر في سؤال وبعض السياق الذي تريد أن يتنبأ به النموذج:

>>> question = "How many programming languages does BLOOM support?"
>>> context = "BLOOM has 176 billion parameters and can generate text in 46 languages natural languages and 13 programming languages."

قم بتجزئة النص وإرجاع متجهات PyTorch:

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("my_awesome_qa_model")
>>> inputs = tokenizer(question, context, return_tensors="pt")

مرّر مدخلاتك إلى النموذج وأعد logits:

>>> import torch
>>> from transformers import AutoModelForQuestionAnswering

>>> model = AutoModelForQuestionAnswering.from_pretrained("my_awesome_qa_model")
>>> with torch.no_grad():
...     outputs = model(**inputs)

احصل على أعلى احتمالية من مخرجات النموذج لموقعي البداية والنهاية:

>>> answer_start_index = outputs.start_logits.argmax()
>>> answer_end_index = outputs.end_logits.argmax()

فكّ ترميز الرموز المتنبأ بها للحصول على الإجابة:

>>> predict_answer_tokens = inputs.input_ids[0, answer_start_index : answer_end_index + 1]
>>> tokenizer.decode(predict_answer_tokens)
'176 billion parameters and can generate text in 46 languages natural languages and 13'
Update on GitHub