基于 Transformers 的问答系统实现
在自然语言处理领域,问答系统一直是一个重要的研究方向。本文将介绍如何使用 Transformers 库实现一个简单的问答系统。
·
在自然语言处理领域,问答系统一直是一个重要的研究方向。本文将介绍如何使用 Transformers 库实现一个简单的问答系统。
一:准备环境
确保已经安装了以下库:
transformers
datasets
pandas
torch
二:代码实现步骤
(一)加载预训练模型和分词器
from transformers import BertTokenizer, BertForQuestionAnswering
from datasets import Dataset
import pandas as pd
# 加载预训练的 BERT 模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
model = BertForQuestionAnswering.from_pretrained('bert-base-chinese')
这里我们使用了bert-base-chinese预训练模型和对应的分词器。
(二)加载数据集
# 加载数据集
df = pd.read_csv('qa_data.csv')
dataset = Dataset.from_pandas(df)
假设我们有一个名为qa_data.csv的数据集,通过pandas读取后转换为Dataset对象。
(三)数据编码函数
def encode_examples(examples):
print(f"Examples received: {examples}")
questions = examples['question']
answers = examples['answer']
inputs = tokenizer(
questions,
answers,
max_length=512,
truncation='only_second',
padding='max_length',
return_tensors='pt'
)
batch_size = len(questions)
return {
'input_ids': inputs['input_ids'],
'attention_mask': inputs['attention_mask'],
'start_positions': [0] * batch_size,
'end_positions': [inputs['input_ids'].size(1) - 1] * batch_size
}
这个函数用于对数据集中的问题和答案进行编码,以便输入到模型中进行训练。
(四)对数据集进行编码
encoded_dataset = dataset.map(encode_examples, batched=True)
encoded_dataset.save_to_disk('encoded_dataset')
对整个数据集应用编码函数,并将编码后的数据集保存到磁盘。
(五)训练模型
import torch
from transformers import BertTokenizer, BertForQuestionAnswering, Trainer, TrainingArguments, TrainerCallback
from datasets import load_from_disk
# 加载编码后的数据集
encoded_dataset = load_from_disk('encoded_dataset')
# 加载预训练的 BERT 模型和分词器
model = BertForQuestionAnswering.from_pretrained('bert-base-chinese')
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
# 检查是否有可用的 GPU
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
training_args = TrainingArguments(
output_dir='./results',
num_train_epochs=20,
per_device_train_batch_size=8,
per_device_eval_batch_size=8,
warmup_steps=500,
weight_decay=0.01,
logging_dir='./logs',
logging_steps=10,
save_steps=1000,
evaluation_strategy="steps",
eval_steps=500,
load_best_model_at_end=True,
report_to="tensorboard"
)
# 自定义 Callback 以记录训练过程中的日志
class LogCallback(TrainerCallback):
def __init__(self):
self.logs = []
def on_log(self, args, state, control, logs=None, **kwargs):
if logs is not None:
self.logs.append(logs)
log_callback = LogCallback()
trainer = Trainer(
model=model,
args=training_args,
train_dataset=encoded_dataset,
eval_dataset=encoded_dataset,
callbacks=[log_callback]
)
trainer.train()
# 保存模型和分词器
model.save_pretrained('./results')
tokenizer.save_pretrained('./results')
这里我们设置了训练参数,包括输出目录、训练轮数、批次大小等。使用自定义的LogCallback来记录训练过程中的日志。最后,训练模型并保存到指定目录。
(六)进行推理
import torch
from transformers import BertTokenizer, BertForQuestionAnswering
# 加载模型和分词器
tokenizer = BertTokenizer.from_pretrained('./results')
model = BertForQuestionAnswering.from_pretrained('./results')
def answer_question(question, context):
inputs = tokenizer.encode_plus(question, context, return_tensors='pt', truncation=True, padding=True)
input_ids = inputs['input_ids']
attention_mask = inputs['attention_mask']
model.eval()
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device)
input_ids = input_ids.to(device)
attention_mask = attention_mask.to(device)
with torch.no_grad():
outputs = model(input_ids, attention_mask=attention_mask)
start_scores = outputs.start_logits
end_scores = outputs.end_logits
start_index = torch.argmax(start_scores)
end_index = torch.argmax(end_scores)
answer_tokens = tokenizer.convert_ids_to_tokens(input_ids[0][start_index:end_index + 1])
answer = tokenizer.convert_tokens_to_string(answer_tokens)
print(f"Question: {question}")
print(f"Context: {context}")
print(f"Answer Tokens: {answer_tokens}")
print(f"Answer: {answer}")
return answer
这个函数用于根据给定的问题和上下文,使用训练好的模型进行推理,得到答案。
(七)测试推理函数
if __name__ == '__main__':
question = "省直医保的参保范围是什么?"
context = "省直医保的参保范围包括中央直属、省直属在哈尔滨的机关、事业单位、社会团体及其职工和退休人员。"
answer = answer_question(question, context)
print(answer)
这里我们测试了推理函数,给定一个问题和上下文,输出模型给出的答案。
推理结果:
三、总结
通过以上步骤,我们实现了一个基于 Transformers 的问答系统。这个系统可以根据给定的问题和上下文,准确地回答问题。在实际应用中,可以根据具体需求调整数据集和模型参数,以提高问答系统的性能。
希望本文对大家在自然语言处理领域的学习和实践有所帮助。如有任何问题或建议,欢迎在评论区留言。
更多推荐
所有评论(0)