transformers多项选择

在自然语言处理(NLP)中,多项选择任务是一种常见的问题类型,它要求模型从给定的多个选项中选择一个或多个正确的答案。这种任务形式常见于自动问答系统、阅读理解测试和一些标准化考试中。例如:

阅读理解题目:给出一篇文章和几个基于文章内容的问题,每个问题下面有若干个候选答案供选择,模型需要理解文本内容并确定正确答案。

例题:
文章:英国是欧洲的一个岛国,首都是伦敦。
问题:英国的首都是?
选项:
A. 巴黎
B. 柏林
C. 伦敦
D. 罗马
正确答案:C. 伦敦
多选题型:在某些情况下,问题可能允许选择多个正确答案。

NLP领域的基准数据集如SQuAD、RACE、SWAG等都包含了多项选择类的任务。

这类任务对NLP模型的理解能力、推理能力和上下文建模能力都有较高的要求。预训练模型如BERT、RoBERTa、MacBERT等,在多项选择任务上取得了显著的进步,它们通过预训练和微调的方式学习如何根据输入的文本信息来判断哪些选项是最合理的。

下面简单介绍使用transformers实现一个多项选择任务问题。

# 多项选择任务 **ForMultipleChoice
import evaluate
from datasets import DatasetDict
from transformers import AutoTokenizer, AutoModelForMultipleChoice, TrainingArguments, Trainer
# 加载数据集
dataset = DatasetDict.load_from_disk("/c3")
# 数据预处理
tokenizer = AutoTokenizer.from_pretrained("../models/chinese-macbert-base")
# 定义数据处理函数
def process_function(examples):
    context = []
    question_choice = []
    labels = []
    for idx in range(len(examples["context"])):
        ctx = "\n".join(examples["context"][idx])
        question = examples["question"][idx]
        choices = examples["choice"][idx]
        for choice in choices:
            context.append(ctx)
            question_choice.append(question + " " + choice)
        if len(choices) < 4:
            for _ in range(4 - len(choices)):
                context.append(ctx)
                question_choice.append(question + " " + "不知道")
        labels.append(choices.index(examples["answer"][idx]))
    tokenized_examples = tokenizer(context, question_choice, truncation="only_first", max_length=256, padding="max_length")     # input_ids: 4000 * 256, 
    tokenized_examples = {k: [v[i: i + 4] for i in range(0, len(v), 4)] for k, v in tokenized_examples.items()}     # 1000 * 4 *256
    tokenized_examples["labels"] = labels
    return tokenized_examples
# 数据处理
tokenized_datasets = datasets.map(process_function, batched=True)
print(tokenized_datasets)
# 创建模型
model = AutoModelForMultipleChoice.from_pretrained("../models/chinese-macbert-base")
# 创建评估函数
import numpy as np
accuracy = evaluate.load("../metrics/accuracy")

def compute_metric(pred):
    predictions, labels = pred
    predictions = np.argmax(predictions, axis=-1)
    return accuracy.compute(predictions=predictions, references=labels)
# 配置训练参数
args = TrainingArguments(
    output_dir="./muliple_choice",
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    logging_steps=5,
    num_train_epochs=2,
    load_best_model_at_end=True,
    fp16=False
)

# 创建训练器
trainer = Trainer(
    model=model,
    args=args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    compute_metrics=compute_metric
)
# 模型训练
trainer.train()
# 模型预测
from typing import Any
import torch

class MultipleChoicePipeline:

    def __init__(self, model, tokenizer) -> None:
        self.model = model
        self.tokenizer = tokenizer
        self.device = model.device

    def preprocess(self, context, quesiton, choices):
        cs, qcs = [], []
        for choice in choices:
            cs.append(context)
            qcs.append(quesiton + " " + choice)
        return tokenizer(cs, qcs, truncation="only_first", max_length=256, return_tensors="pt")

    def predict(self, inputs):
        inputs = {k: v.unsqueeze(0).to(self.device) for k, v in inputs.items()}
        return self.model(**inputs).logits

    def postprocess(self, logits, choices):
        predition = torch.argmax(logits, dim=-1).cpu().item()
        return choices[predition]

    def __call__(self, context, question, choices) -> Any:
        inputs = self.preprocess(context, question, choices)
        logits = self.predict(inputs)
        result = self.postprocess(logits, choices)
        return result
pipe = MultipleChoicePipeline(model, tokenizer)
pipe("铭铭在重庆上班", "铭铭在哪里上班?", ["北京", "深圳", "上海", "海南", "重庆", "海南"])
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灯下夜无眠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值