Transformers documentation
Trả lời câu hỏi
Trả lời câu hỏi
Các tác vụ trả lời câu hỏi sẽ trả về một câu trả lời dựa trên một câu hỏi được đưa ra. Nếu bạn từng hỏi trợ lý ảo như Alexa, Siri hoặc Google về thời tiết, thì bạn đã từng sử dụng một mô hình trả lời câu hỏi. Có hai loại phổ biến của các tác vụ trả lời câu hỏi:
- Extractive: trích xuất câu trả lời từ ngữ cảnh được cung cấp.
- Abstractive: tạo ra câu trả lời từ ngữ cảnh sao cho trả lời đúng câu hỏi.
Hướng dẫn này sẽ cho bạn thấy cách:
- Huấn luyện lại DistilBERT trên bộ dữ liệu SQuAD cho câu hỏi trả lời trích xuất.
- Sử dụng mô hình đã tinh chỉnh của bạn để suy luận.
Để xem tất cả các kiến trúc và checkpoint tương thích với tác vụ này, chúng tôi khuyến nghị bạn kiểm tra trang tác vụ
Trước khi bắt đầu, hãy đảm bảo bạn đã cài đặt tất cả các thư viện cần thiết:
pip install transformers datasets evaluate
Chúng tôi khuyến khích bạn đăng nhập vào tài khoản Hugging Face của mình để có thể tải lên và chia sẻ mô hình của bạn với cộng đồng. Khi được yêu cầu, hãy nhập token của bạn để đăng nhập:
>>> from huggingface_hub import notebook_login
>>> notebook_login()Tải bộ dữ liệu SQuAD
Hãy bắt đầu bằng cách tải một tập con nhỏ hơn của bộ dữ liệu SQuAD từ thư viện 🤗 Datasets. Điều này sẽ cho bạn cơ hội thử nghiệm và đảm bảo mọi thứ hoạt động trước khi dành thêm thời gian huấn luyện trên toàn bộ bộ dữ liệu.
>>> from datasets import load_dataset
>>> squad = load_dataset("rajpurkar/squad", split="train[:5000]")Chia split train của bộ dữ liệu thành tập train và tập test bằng phương thức train_test_split:
>>> squad = squad.train_test_split(test_size=0.2)Sau đó, hãy xem một ví dụ:
>>> 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'
}Có một số trường quan trọng ở đây:
answers: vị trí bắt đầu của token câu trả lời và văn bản câu trả lời.context: thông tin nền mà mô hình cần trích xuất câu trả lời.question: câu hỏi mà mô hình cần trả lời.
Tiền xử lý
Bước tiếp theo là nạp một tokenizer DistilBERT để xử lý các trường question và context:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")Có một số bước tiền xử lý đặc thù cho các tác vụ trả lời câu hỏi mà bạn nên lưu ý:
- Một số ví dụ trong tập dữ liệu có thể có
contextrất dài, vượt quá độ dài đầu vào tối đa của mô hình. Để xử lý các chuỗi dài hơn, hãy chỉ cắt ngắncontextbằng cách đặttruncation="only_second". - Tiếp theo, ánh xạ vị trí bắt đầu và kết thúc của câu trả lời về
contextgốc bằng cách đặtreturn_offset_mapping=True. - Với ánh xạ trong tay, giờ bạn có thể tìm các token bắt đầu và kết thúc của câu trả lời. Sử dụng phương thức
sequence_idsđể xác định phần nào của offset tương ứng vớiquestionvà phần nào tương ứng vớicontext.
Dưới đây là cách bạn có thể tạo một hàm để cắt bớt và ánh xạ các token bắt đầu và kết thúc của answer vào 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Để áp dụng hàm tiền xử lý cho toàn bộ bộ dữ liệu, hãy sử dụng hàm map của 🤗 Datasets. Bạn có thể tăng tốc độ của hàm map bằng cách đặt batched=True để xử lý nhiều phần tử của bộ dữ liệu cùng lúc. Xóa các cột không cần thiết:
>>> tokenized_squad = squad.map(preprocess_function, batched=True, remove_columns=squad["train"].column_names)Bây giờ hãy tạo một lô ví dụ sử dụng DefaultDataCollator. Khác với các data collator khác trong 🤗 Transformers, DefaultDataCollator không áp dụng bất kỳ bước tiền xử lý bổ sung nào như padding.
>>> from transformers import DefaultDataCollator
>>> data_collator = DefaultDataCollator()Huấn luyện
Nếu bạn chưa quen với việc tinh chỉnh mô hình bằng Trainer, hãy xem hướng dẫn cơ bản tại đây!
Bạn đã sẵn sàng để bắt đầu huấn luyện mô hình của mình! Nạp DistilBERT bằng AutoModelForQuestionAnswering:
>>> from transformers import AutoModelForQuestionAnswering, TrainingArguments, Trainer
>>> model = AutoModelForQuestionAnswering.from_pretrained("distilbert/distilbert-base-uncased")Tới bước này, chỉ còn ba bước nữa:
- Định nghĩa các siêu tham số huấn luyện của bạn trong TrainingArguments. Tham số bắt buộc duy nhất là
output_dir, chỉ định nơi lưu trữ mô hình của bạn. Bạn sẽ đẩy mô hình này lên Hub bằng cách đặtpush_to_hub=True(bạn cần đăng nhập vào Hugging Face để tải lên mô hình của mình). - Truyền các đối số huấn luyện vào Trainer cùng với mô hình, tập dữ liệu, tokenizer và data collator.
- Gọi train() để tinh chỉnh mô hình của bạn.
>>> 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()Khi quá trình huấn luyện hoàn tất, hãy chia sẻ mô hình của bạn lên Hub bằng phương thức push_to_hub() để mọi người có thể sử dụng mô hình của bạn:
>>> trainer.push_to_hub()Để xem một ví dụ chi tiết hơn về cách tinh chỉnh mô hình cho câu hỏi và trả lời, hãy xem notebook PyTorch tương ứng.
Đánh giá
Đánh giá cho câu hỏi và trả lời đòi hỏi một lượng đáng kể các bước xử lý hậu kỳ. Để không chiếm quá nhiều thời gian của bạn, hướng dẫn này bỏ qua bước đánh giá. Trainer vẫn tính toán tổn thất đánh giá trong quá trình huấn luyện nên bạn không hoàn toàn mù mờ về hiệu suất của mô hình.
Nếu bạn có thêm thời gian và quan tâm đến cách đánh giá mô hình của mình cho câu hỏi trả lời, hãy xem chương Trả lời câu hỏi trong Khóa học 🤗 Hugging Face!
Suy luận
Tuyệt, giờ đây bạn đã tinh chỉnh một mô hình, bạn có thể sử dụng nó để suy luận!
Hãy nghĩ ra một câu hỏi và một số ngữ cảnh mà bạn muốn mô hình dự đoán:
>>> 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."Phân tách token văn bản và trả về các tensor PyTorch:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("my_awesome_qa_model")
>>> inputs = tokenizer(question, context, return_tensors="pt")Truyền các đầu vào của bạn vào mô hình và trả về logits:
>>> import torch
>>> from transformers import AutoModelForQuestionAnswering
>>> model = AutoModelForQuestionAnswering.from_pretrained("my_awesome_qa_model")
>>> with torch.no_grad():
... outputs = model(**inputs)Lấy xác suất cao nhất từ đầu ra của mô hình cho vị trí bắt đầu và kết thúc:
>>> answer_start_index = outputs.start_logits.argmax()
>>> answer_end_index = outputs.end_logits.argmax()Giải mã các token dự đoán để lấy câu trả lời:
>>> 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'