You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何评估用于语义搜索的AutoModelForQuestionAnswering模型?

基于AutoModelForQuestionAnswering的语义搜索模型评估方案

一、核心问题拆解

你当前用CamemBERT-base做的是抽取式问答(可适配语义搜索场景的评估逻辑),缺少标注数据(训练/测试集、真实答案)是评估的核心障碍,以下是无需大规模标注也能落地的评估思路:

二、无标注数据下的评估方法

1. 人工评估(最直接)

  • 自己构造一批典型的问题-文本对,手动写出预期答案
  • 用你的模型生成答案后,从三个维度打分:
    • 准确性:答案是否和真实信息匹配
    • 完整性:是否覆盖了问题要求的全部要点
    • 流畅性:拼接后的答案读起来是否通顺
  • 统计所有样本的平均得分,作为模型性能的参考

2. 用公开数据集评估

直接用成熟的抽取式问答法语数据集(比如SQuAD法语版、MLQA法语子集,适配CamemBERT的语言特性):

  • 加载数据集后,用模型批量预测答案
  • 计算两个行业标准指标:
    • Exact Match(EM):预测答案和真实答案完全一致的样本比例
    • F1 Score:预测答案和真实答案的词级重叠率,数值越高匹配度越好

3. 自监督式评估(无标注数据也能用)

  • 困惑度(Perplexity):计算模型在无标注文本上的预测困惑度,数值越低说明模型对文本的理解越到位
  • 答案合理性校验:统计模型输出"No Answer"的比例,结合问题和文本的相关性判断是否合理(比如问题和文本完全无关时,模型应该输出"No Answer")

三、适配评估的代码调整建议

你的代码存在几个小问题,先修正再开展评估:

import torch
from transformers import CamembertTokenizer, AutoModelForQuestionAnswering

def load_model():
    model_name = "camembert-base"
    tokenizer = CamembertTokenizer.from_pretrained(model_name)
    model = AutoModelForQuestionAnswering.from_pretrained(model_name)
    return model, tokenizer

def get_answer(search, text, model, tokenizer):
    # 修正token_type_ids错误:encode_plus返回的token_type_ids是区分问题和上下文的标识,不能硬设为0
    encoded_output = tokenizer.encode_plus(text=search, text_pair=text, padding=True, return_tensors="pt")
    # 直接用返回的tensor,无需手动转换
    input_ids = encoded_output['input_ids']
    attention_mask = encoded_output['attention_mask']
    token_type_ids = encoded_output['token_type_ids']
    tokens = tokenizer.convert_ids_to_tokens(input_ids[0])

    # 切换到推理模式,禁用梯度计算节省资源
    model.eval()
    with torch.no_grad():
        output = model(input_ids=input_ids, token_type_ids=token_type_ids, attention_mask=attention_mask)

    # 获取答案区间
    answer_start = torch.argmax(output.start_logits)
    answer_end = torch.argmax(output.end_logits)
    if answer_end >= answer_start:
        # 用tokenizer自带方法合并子词,避免手动拼接的混乱
        answer = tokenizer.convert_tokens_to_string(tokens[answer_start:answer_end + 1])
    else:
        answer = "No Answer"
    return answer

# 使用示例
model, tokenizer = load_model()
question = "Quelle est la capitale de la France ?"
context = "La France est un pays d'Europe occidentale. Sa capitale est Paris."
print(get_answer(question, context, model, tokenizer))

修正点说明:

  • 移除手动tensor转换,用encode_plus的return_tensors="pt"直接生成可用的张量
  • 修复token_type_ids的错误赋值,保证模型能区分问题和上下文
  • 添加model.eval()和torch.no_grad()优化推理效率
  • 用convert_tokens_to_string替代手动拼接,解决CamemBERT子词拆分的问题

四、评估指标计算示例(以SQuAD数据集为例)

假设你加载了SQuAD法语版数据集,计算EM和F1的代码逻辑如下:

def compute_em(pred_answer, true_answers):
    # 真实答案可能有多个候选,匹配任意一个就算EM
    pred_clean = pred_answer.strip().lower()
    for ans in true_answers:
        ans_clean = ans.strip().lower()
        if pred_clean == ans_clean:
            return 1
    return 0

def compute_f1(pred_answer, true_answers):
    pred_tokens = pred_answer.strip().lower().split()
    max_f1 = 0
    for ans in true_answers:
        true_tokens = ans.strip().lower().split()
        # 计算词的交集
        common = set(pred_tokens) & set(true_tokens)
        if len(common) == 0:
            f1 = 0
        else:
            precision = len(common) / len(pred_tokens)
            recall = len(common) / len(true_tokens)
            f1 = 2 * (precision * recall) / (precision + recall)
        if f1 > max_f1:
            max_f1 = f1
    return max_f1

# 批量评估统计
total_em = 0
total_f1 = 0
data_samples = [...]  # 替换为加载的数据集样本,每个样本包含question、context、true_answers
for sample in data_samples:
    pred = get_answer(sample['question'], sample['context'], model, tokenizer)
    total_em += compute_em(pred, sample['true_answers'])
    total_f1 += compute_f1(pred, sample['true_answers'])

avg_em = total_em / len(data_samples)
avg_f1 = total_f1 / len(data_samples)
print(f"Exact Match: {avg_em:.2f}, F1 Score: {avg_f1:.2f}")

内容的提问来源于stack exchange,提问作者Emna Talbi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:05:34