在自然语言处理(NLP)领域,阅读理解是一项重要的任务,它的目标是让模型能够理解文本,并根据给定的查询准确地从文本中抽取或生成相关信息。
具体来说,阅读理解任务通常会提供一段长文本和一个或多个与该文本相关的问题,模型需要理解这段文本的内容,并根据问题从中找到答案。例如,在SQuAD(Stanford Question Answering Dataset)这样的数据集中,模型需要读取一段文章,然后回答基于该文章提出的具体问题,输出的答案通常是原文中的某个片段。
此外,还有一些更复杂的阅读理解任务,比如多文档阅读理解,要求模型处理并整合多篇文档的信息来回答问题;或者开放型阅读理解,其中的问题可能无法直接从给定文本中找到确切答案,而需要模型具备一定的推理能力才能得出结论。
此次介绍使用transformer来实现一个较为简单的问答形式的阅读理解任务。
# 阅读理解任务 **ForQuestionAnswering
from datasets import load_dataset, DatasetDict
from transformers import AutoTokenizer, AutoModelForQuestionAnswering, TrainingArguments, Trainer, DefaultDataCollator
# 加载数据集
datasets = DatasetDict.load_from_disk("/question_answering/mrc_data")
print(datasets)
# 数据处理
tokenizer = AutoTokenizer.from_pretrained("../models/chinese-macbert-base")
# 处理函数
def process_func(examples):
tokenized_examples = tokenizer(text=examples["question"],
text_pair=examples["context"],
return_offsets_mapping=True,
max_length=384, truncation="only_second", padding="max_length")
offset_mapping = tokenized_examples.pop("offset_mapping")
start_positions = []
end_positions = []
for idx, offset in enumerate(offset_mapping):
answer = examples["answers"][idx]
start_char = answer["answer_start"][0]
end_char = start_char + len(answer["text"][0])
# 定位答案在token中的起始位置和结束位置
# 一种策略,我们要拿到context的起始和结束,然后从左右两侧向答案逼近
context_start = tokenized_examples.sequence_ids(idx).index(1)
context_end = tokenized_examples.sequence_ids(idx).index(None, context_start) - 1
# 判断答案是否在context中
if offset[context_end][1] < start_char or offset[context_start][0] > end_char:
start_token_pos = 0
end_token_pos = 0
else:
token_id = context_start
while token_id <= context_end and offset[token_id][0] < start_char:
token_id += 1
start_token_pos = token_id
token_id = context_end
while token_id >= context_start and offset[token_id][1] > end_char:
token_id -=1
end_token_pos = token_id
start_positions.append(start_token_pos)
end_positions.append(end_token_pos)
tokenized_examples["start_positions"] = start_positions
tokenized_examples["end_positions"] = end_positions
return tokenized_examples
# 数据处理
tokenied_datasets = datasets.map(process_func, batched=True, remove_columns=datasets["train"].column_names)
tokenied_datasets
# 创建模型
model = AutoModelForQuestionAnswering.from_pretrained("../models/chinese-macbert-base")
# 配置训练参数
args = TrainingArguments(
output_dir="models_for_qa",
per_device_train_batch_size=16,
per_device_eval_batch_size=32,
evaluation_strategy="epoch",
save_strategy="epoch",
save_total_limit=3,
logging_steps=10,
num_train_epochs=2
)
# 创建训练器
trainer = Trainer(
model=model,
args=args,
train_dataset=tokenied_datasets["train"],
eval_dataset=tokenied_datasets["validation"],
data_collator=DefaultDataCollator()
)
# 模型训练
trainer.train()
# 模型预测
from transformers import pipeline
pipe = pipeline("question-answering", model=model, tokenizer=tokenizer)
pipe(question="铭铭是哪里人?", context="铭铭说她是重庆人")