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

如何基于自有数据在Hugging Face构建问答模型?新手求助

基于自有Excel数据构建Hugging Face问答模型的实现方案

问题分析

你之前直接将表格数据转为连续文本调用预训练SQUAD模型效果不佳,核心原因是结构化表格信息被打散后,模型难以精准定位对应字段的答案。针对这类场景,更适合通过生成结构化问答对+微调预训练模型的方式实现,下面是完整的示例代码和步骤。

前置依赖安装

首先安装所需工具包:

pip install pandas transformers torch datasets openpyxl

完整示例代码

1. 读取Excel并生成训练数据

将表格数据转换为SQUAD格式的问答样本(每个样本包含上下文、问题、答案位置信息):

import pandas as pd
from datasets import Dataset

# 读取Excel数据(需根据你的表格列名调整字段)
df = pd.read_excel("s_o_data.xlsx")

# 将每行表格数据转为问答样本
def build_training_sample(row):
    # 构造自然语言上下文
    context = f"Im Jahr {row['Jahr']} betrugen die Aufwendungen für FuE-Personal im Bereich '{row['Bereich']}' {row['Aufwendungen_FuE_Personal']} VZÄ."
    # 构造对应问题
    question = f"Wie hoch waren die Aufwendungen für FuE-Personal im Bereich '{row['Bereich']}' im Jahr {row['Jahr']}?"
    # 提取答案及起始位置
    answer_text = f"{row['Aufwendungen_FuE_Personal']} VZÄ"
    answer_start = context.find(answer_text)
    
    return {
        "context": context,
        "question": question,
        "answers": {
            "text": [answer_text],
            "answer_start": [answer_start]
        }
    }

# 生成所有训练样本并转为Hugging Face Dataset格式
train_samples = df.apply(build_training_sample, axis=1).tolist()
train_dataset = Dataset.from_list(train_samples)

2. 加载模型与预处理数据

选用针对德语优化的预训练问答模型,并对数据进行分词处理:

from transformers import AutoTokenizer, AutoModelForQuestionAnswering, TrainingArguments, Trainer
import torch

# 德语专用预训练问答模型
model_name = "deepset/bert-base-german-cased-finetuned-squad"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForQuestionAnswering.from_pretrained(model_name)

# 数据分词与位置映射转换
def preprocess_data(examples):
    questions = [q.strip() for q in examples["question"]]
    contexts = [c.strip() for c in examples["context"]]
    
    # 对问题和上下文进行分词
    inputs = tokenizer(
        questions,
        contexts,
        max_length=384,
        truncation="only_second",
        return_offsets_mapping=True,
        padding="max_length",
    )
    
    offset_mapping = inputs.pop("offset_mapping")
    start_positions = []
    end_positions = []
    
    for i, offset in enumerate(offset_mapping):
        answer = examples["answers"][i]
        start_char = answer["answer_start"][0]
        end_char = start_char + len(answer["text"][0])
        sequence_ids = inputs.sequence_ids(i)
        
        # 定位上下文对应的token区间
        idx = 0
        while sequence_ids[idx] != 1:
            idx += 1
        context_start = idx
        while sequence_ids[idx] == 1:
            idx += 1
        context_end = idx - 1
        
        # 将字符位置转换为token位置
        start_token = None
        end_token = None
        for j in range(context_start, context_end + 1):
            if offset[j][0] <= start_char and offset[j][1] >= start_char:
                start_token = j
            if offset[j][0] <= end_char and offset[j][1] >= end_char:
                end_token = j
        
        start_positions.append(start_token if start_token is not None else 0)
        end_positions.append(end_token if end_token is not None else 0)
    
    inputs["start_positions"] = start_positions
    inputs["end_positions"] = end_positions
    return inputs

# 处理训练数据集
tokenized_train = train_dataset.map(preprocess_data, batched=True)

3. 微调模型

设置训练参数并启动微调:

# 训练参数配置
training_args = TrainingArguments(
    output_dir="./german_fue_qa_model",
    per_device_train_batch_size=8,
    num_train_epochs=3,
    logging_dir="./logs",
    logging_steps=10,
    learning_rate=2e-5,
    weight_decay=0.01,
    save_total_limit=2,
)

# 初始化训练器并开始微调
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_train,
)

trainer.train()

# 保存微调后的模型与分词器
model.save_pretrained("./german_fue_qa_model")
tokenizer.save_pretrained("./german_fue_qa_model")

4. 使用微调后的模型预测

def get_answer(question, context):
    inputs = tokenizer.encode_plus(question, context, return_tensors="pt")
    with torch.no_grad():
        outputs = model(**inputs)
    
    answer_start = torch.argmax(outputs.start_logits)
    answer_end = torch.argmax(outputs.end_logits) + 1
    
    answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(inputs["input_ids"][0][answer_start:answer_end]))
    return answer

# 测试示例
test_context = "Im Jahr 2011 betrugen die Aufwendungen für FuE-Personal im Bereich 'H.v. DV-Geräten, elektronischen u. opt. Erzeugnissen' 54647 VZÄ."
test_question = "Wie hoch waren die Aufwendungen für FuE-Personal im Bereich 'H.v. DV-Geräten, elektronischen u. opt. Erzeugnissen' im Jahr 2011?"
print(f"问题:{test_question}")
print(f"答案:{get_answer(test_question, test_context)}")

关键说明

  • 选用deepset/bert-base-german-cased-finetuned-squad模型,该模型是专门针对德语问答任务优化的预训练模型,比通用英文模型更适配你的数据场景。
  • 通过将表格行数据转为自然语言上下文+对应问题的方式,让模型学习从指定语境中抽取精准答案,解决了原始连续文本方案的信息混乱问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:49:56