# Menjawab pertanyaan

Tugas question answering mengembalikan jawaban berdasarkan 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](https://huggingface.co/distilbert/distilbert-base-uncased) pada dataset [SQuAD](https://huggingface.co/datasets/rajpurkar/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](https://huggingface.co/tasks/question-answering)

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

```bash
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:

```py
>>> from huggingface_hub import notebook_login

>>> notebook_login()
```

## Muat dataset SQuAD

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

```py
>>> from datasets import load_dataset

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

Pisahkan split `train` dari dataset menjadi set train dan test dengan metode [train_test_split](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.train_test_split):

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

Lalu, lihatlah sebuah contoh:

```py
>>> 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`:

```py
>>> 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 mana yang sesuai dengan `context`.

Berikut cara membuat fungsi untuk memotong dan memetakan token awal dan akhir dari `answer` ke `context`:

```py
>>> 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](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.map) dari 🤗 Datasets. Anda dapat mempercepat fungsi `map` dengan mengatur `batched=True` untuk memproses beberapa elemen dataset sekaligus. Hapus kolom apa pun yang tidak Anda butuhkan:

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

Sekarang buat satu batch contoh menggunakan [DefaultDataCollator](/docs/transformers/main/id/main_classes/data_collator#transformers.DefaultDataCollator). Berbeda dengan data collator lainnya di 🤗 Transformers, [DefaultDataCollator](/docs/transformers/main/id/main_classes/data_collator#transformers.DefaultDataCollator) tidak menerapkan prapemrosesan tambahan seperti padding.

```py
>>> from transformers import DefaultDataCollator

>>> data_collator = DefaultDataCollator()
```

## Latih

Jika Anda belum familiar dengan finetuning model menggunakan [Trainer](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer), silakan lihat tutorial dasar [di sini](../training)!

Anda siap untuk mulai melatih model Anda sekarang! Muat DistilBERT dengan [AutoModelForQuestionAnswering](/docs/transformers/main/id/model_doc/auto#transformers.AutoModelForQuestionAnswering):

```py
>>> 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](/docs/transformers/main/id/main_classes/trainer#transformers.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](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer) bersama dengan model, dataset, tokenizer, dan data collator.
3. Panggil [train()](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer.train) untuk melakukan finetuning pada model Anda.

```py
>>> 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()](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer.push_to_hub) agar semua orang dapat menggunakan model Anda:

```py
>>> trainer.push_to_hub()
```

Untuk contoh yang lebih mendalam tentang cara melakukan finetuning model untuk question answering, lihat [notebook PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/question_answering.ipynb) yang sesuai.

## Evaluasi

Evaluasi untuk question answering memerlukan banyak pascaproses. Agar tidak memakan waktu Anda terlalu banyak, panduan ini melewati langkah evaluasi. [Trainer](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer) tetap menghitung evaluasi loss selama pelatihan sehingga Anda tidak sepenuhnya buta terhadap kinerja model Anda.

Jika Anda memiliki lebih banyak waktu dan tertarik pada cara mengevaluasi model Anda untuk question answering, lihat bab [Question answering](https://huggingface.co/course/chapter7/7?fw=pt#post-processing) dari 🤗 Hugging Face Course!

## Inferensi

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

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

```py
>>> 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:

```py
>>> 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`:

```py
>>> 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:

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

Decode token yang diprediksi untuk mendapatkan jawaban:

```py
>>> 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'
```

