Chapter 12
基于截断策略的机器阅读理解任务实现
Notebooktransformers27 cells
基于截断策略的机器阅读理解任务实现
Step1 导入相关包
In [ ]python · cell 3
python
from datasets import load_dataset, DatasetDict
from transformers import AutoTokenizer, AutoModelForQuestionAnswering, TrainingArguments, Trainer, DefaultDataCollatorStep2 数据集加载
In [ ]python · cell 5
python
# 如果可以联网,直接使用load_dataset进行加载
#datasets = load_dataset("cmrc2018", cache_dir="data")
# 如果无法联网,则使用下面的方式加载数据集
datasets = DatasetDict.load_from_disk("mrc_data")
datasetsIn [ ]python · cell 6
python
datasets["train"][0]Step3 数据预处理
In [ ]python · cell 8
python
tokenizer = AutoTokenizer.from_pretrained("hfl/chinese-macbert-base")
tokenizerIn [ ]python · cell 9
python
sample_dataset = datasets["train"].select(range(10))In [ ]python · cell 10
python
tokenized_examples = tokenizer(text=sample_dataset["question"],
text_pair=sample_dataset["context"],
return_offsets_mapping=True,
max_length=512, truncation="only_second", padding="max_length")
tokenized_examples.keys()In [ ]python · cell 11
python
print(tokenized_examples["offset_mapping"][0], len(tokenized_examples["offset_mapping"][0]))In [ ]python · cell 12
python
offset_mapping = tokenized_examples.pop("offset_mapping")In [ ]python · cell 13
python
for idx, offset in enumerate(offset_mapping):
answer = sample_dataset[idx]["answers"]
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
print(answer, start_char, end_char, context_start, context_end, start_token_pos, end_token_pos)
print("token answer decode:", tokenizer.decode(tokenized_examples["input_ids"][idx][start_token_pos: end_token_pos + 1]))In [ ]python · cell 14
python
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_examplesIn [ ]python · cell 15
python
tokenied_datasets = datasets.map(process_func, batched=True, remove_columns=datasets["train"].column_names)
tokenied_datasetsStep4 加载模型
In [ ]python · cell 17
python
model = AutoModelForQuestionAnswering.from_pretrained("hfl/chinese-macbert-base")Step5 配置TrainingArguments
In [ ]python · cell 19
python
args = TrainingArguments(
output_dir="models_for_qa",
per_device_train_batch_size=32,
per_device_eval_batch_size=32,
eval_strategy="epoch",
save_strategy="epoch",
logging_steps=50,
num_train_epochs=3
)Step6 配置Trainer
In [ ]python · cell 21
python
trainer = Trainer(
model=model,
args=args,
tokenizer=tokenizer,
train_dataset=tokenied_datasets["train"],
eval_dataset=tokenied_datasets["validation"],
data_collator=DefaultDataCollator()
)Step7 模型训练
In [ ]python · cell 23
python
trainer.train()Step8 模型预测
In [ ]python · cell 25
python
from transformers import pipeline
pipe = pipeline("question-answering", model=model, tokenizer=tokenizer, device=0)In [ ]python · cell 26
python
pipe(question="小明在哪里上班?", context="小明在北京上班。")In [ ]python · cell 27
python
