Transformers documentation

Menjawab pertanyaan

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

Menjawab pertanyaan

Tugas question answering mengembalikan jawaban berdasarkan sebuah pertanyaan. Jika Anda pernah bertanya kepada asisten virtual seperti Alexa, Siri, atau Google tentang cuaca, maka Anda sudah pernah menggunakan model question answering. Ada dua jenis umum tugas question answering:

  • Extractive: mengekstrak jawaban dari konteks yang diberikan.
  • Abstraktif: menghasilkan jawaban dari konteks yang menjawab pertanyaan dengan benar.

Panduan ini akan menunjukkan cara Anda untuk:

  1. Lakukan finetuning DistilBERT pada dataset SQuAD untuk extractive question answering.
  2. Gunakan model yang telah Anda finetune untuk inferensi.

Untuk melihat semua arsitektur dan checkpoint yang kompatibel dengan tugas ini, kami menyarankan untuk memeriksa halaman tugas

Sebelum memulai, pastikan Anda telah menginstal semua pustaka yang diperlukan:

pip install transformers datasets evaluate

Kami menyarankan Anda untuk masuk ke akun Hugging Face Anda agar dapat mengunggah dan membagikan model Anda kepada komunitas. Saat diminta, masukkan token Anda untuk masuk:

>>> from huggingface_hub import notebook_login

>>> notebook_login()

Muat dataset SQuAD

Mulai dengan memuat subset kecil dari dataset SQuAD dari pustaka 🤗 Datasets. Hal ini memberi Anda kesempatan untuk bereksperimen dan memastikan semuanya berfungsi dengan baik sebelum menghabiskan lebih banyak waktu untuk pelatihan pada dataset lengkap.

>>> from datasets import load_dataset

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

Bagi split train dari dataset menjadi set train dan test dengan metode train_test_split:

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

Lalu, lihatlah sebuah contoh:

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

Ada beberapa bidang penting di sini:

  • answers: lokasi awal token jawaban dan teks jawaban.
  • context: informasi latar belakang yang harus diekstrak oleh model untuk mendapatkan jawaban.
  • question: pertanyaan yang harus dijawab oleh model.

Pra-pemrosesan

Langkah selanjutnya adalah memuat tokenizer DistilBERT untuk memproses field question dan context:

>>> from transformers import AutoTokenizer

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

Ada beberapa langkah pra-pemrosesan yang khusus untuk tugas menjawab pertanyaan yang perlu Anda ketahui:

  1. Beberapa contoh dalam dataset mungkin memiliki context yang sangat panjang sehingga melebihi panjang input maksimum model. Untuk menangani sekuens yang lebih panjang, pangkas hanya context dengan mengatur truncation="only_second".
  2. Selanjutnya, petakan posisi awal dan akhir jawaban ke context asli dengan mengatur return_offset_mapping=True.
  3. Dengan pemetaan di tangan, sekarang Anda dapat menemukan token awal dan akhir dari jawaban. Gunakan metode sequence_ids untuk menemukan bagian offset mana yang sesuai dengan question dan bagian mana yang sesuai dengan context.

Berikut cara membuat fungsi untuk memotong dan memetakan token awal dan akhir dari answer ke 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

Untuk menerapkan fungsi pra-pemrosesan ke seluruh dataset, gunakan fungsi map dari 🤗 Datasets. Anda dapat mempercepat fungsi map dengan mengatur batched=True untuk memproses beberapa elemen dataset sekaligus. Hapus kolom yang tidak Anda butuhkan:

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

Sekarang buat satu batch contoh menggunakan DefaultDataCollator. Berbeda dengan data collator lainnya di 🤗 Transformers, DefaultDataCollator tidak menerapkan prapemrosesan tambahan seperti padding.

>>> from transformers import DefaultDataCollator

>>> data_collator = DefaultDataCollator()

Latih

Jika Anda belum familiar dengan finetuning model menggunakan Trainer, silakan lihat tutorial dasar di sini!

Anda siap untuk mulai melatih model Anda sekarang! Muat DistilBERT dengan AutoModelForQuestionAnswering:

>>> from transformers import AutoModelForQuestionAnswering, TrainingArguments, Trainer

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

Pada titik ini, hanya tersisa tiga langkah:

  1. Definisikan hiperparameter pelatihan Anda di TrainingArguments. Satu-satunya parameter yang wajib diisi adalah output_dir yang menentukan lokasi penyimpanan model Anda. Anda akan mendorong model ini ke Hub dengan mengatur push_to_hub=True (Anda harus masuk ke Hugging Face untuk mengunggah model Anda).
  2. Lewatkan argumen pelatihan ke Trainer bersama dengan model, dataset, tokenizer, dan data collator.
  3. Panggil train() untuk melakukan finetuning pada model Anda.
>>> 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()

Setelah pelatihan selesai, bagikan model Anda ke Hub dengan metode push_to_hub() agar semua orang dapat menggunakan model Anda:

>>> trainer.push_to_hub()

Untuk contoh yang lebih mendalam tentang cara melakukan finetuning model untuk question answering, lihat notebook PyTorch yang sesuai.

Evaluasi

Evaluasi untuk question answering memerlukan banyak pascapemrosesan. Agar tidak menghabiskan terlalu banyak waktu Anda, panduan ini melewati langkah evaluasi. Trainer tetap menghitung evaluasi loss selama pelatihan, sehingga Anda tidak sepenuhnya buta terhadap kinerja model Anda.

Jika Anda memiliki lebih banyak waktu dan tertarik untuk mengetahui cara mengevaluasi model Anda untuk question answering, lihatlah bab Question answering dari 🤗 Hugging Face Course!

Inferensi

Bagus, sekarang setelah Anda melakukan finetuning pada model, Anda dapat menggunakannya untuk inferensi!

Buatlah sebuah pertanyaan dan beberapa konteks yang ingin Anda prediksi oleh model:

>>> 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."

Tokenisasi teks dan kembalikan tensor PyTorch:

>>> from transformers import AutoTokenizer

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

Lewatkan input Anda ke model dan kembalikan logits:

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

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

Dapatkan probabilitas tertinggi dari keluaran model untuk posisi awal dan akhir:

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

Decode token yang diprediksi untuk mendapatkan jawaban:

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