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

如何用Hub数据集微调Huggingface Seq2Seq模型?代码与损失计算解惑

问题解惑:用dxiao/requirements-ner-id微调flax-community/t5-large-wikisplit

一、核心概念拆解

1. 模型获取预期值与损失计算逻辑

T5属于序列到序列(Seq2Seq)模型,训练时必须同时提供编码器输入和解码器的真实标签:

  • 编码器输入对应你要处理的原始文本(比如你的complex_sentence),用来生成语义表示
  • 解码器的真实标签(labels字段)是模型要生成的目标文本(比如你的simplified_sentence),模型通过对比预测token与labels中的真实token,计算交叉熵损失来完成参数更新

你的原代码里只设置了decoder_input_ids,但缺少关键的labels字段,导致模型无法计算损失。另外decoder_input_ids一般是目标序列的左移版本(自动在开头加<s>、去掉末尾</s>),HuggingFace的Trainer会自动处理这一步,无需手动设置。

2. Seq2Seq模型微调核心流程

  1. 数据准备:明确输入文本(编码器输入)和目标文本(解码器输出)的对应关系
  2. 预处理:对输入、目标文本分别tokenize,生成input_ids、attention_mask(编码器用,标记有效token)、labels(目标token的id序列,用于损失计算)
  3. 参数配置:设置训练batch大小、学习率、训练轮数等控制训练过程的参数
  4. 启动训练:Trainer自动完成前向传播、损失计算、反向传播、参数更新全流程

3. 关键参数说明

数据集层面(模型必需)

  • input_ids:输入文本tokenize后的id序列,是编码器的核心输入
  • attention_mask:标记哪些token是有效输入(避免padding部分干扰注意力计算)
  • labels:目标文本tokenize后的id序列,模型靠它计算损失(注意要把padding的token_id替换为-100,模型会自动忽略这些位置的损失)

训练参数(Seq2SeqTrainingArguments核心项)

  • per_device_train_batch_size:单GPU/CPU上的训练batch大小,根据显存调整
  • learning_rate:控制参数更新的步长,T5微调一般用1e-5~5e-5,太大容易过拟合
  • num_train_epochs:训练轮数,即整个数据集被遍历的次数,0.25轮太少,建议至少1轮
  • evaluation_strategy:评估时机,steps表示每N步评估一次,epoch表示每轮结束评估
  • predict_with_generate:评估时让模型生成结果,再计算BLEU等生成类指标
  • gradient_accumulation_steps:梯度累积步数,显存不足时用,相当于把N个小batch的梯度合并后再更新参数

二、修正后的完整微调示例

1. 加载依赖与模型、Tokenizer

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
from datasets import load_dataset
from transformers import Seq2SeqTrainer, Seq2SeqTrainingArguments, DataCollatorForSeq2Seq
import evaluate

# 加载预训练模型和Tokenizer
checkpoint = "flax-community/t5-large-wikisplit"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSeq2SeqLM.from_pretrained(checkpoint).cuda()

2. 加载并预处理数据集

# 加载目标数据集
raw_dataset = load_dataset("dxiao/requirements-ner-id")

# 将tokens数组转换为完整句子
def token_to_string(token_array):
    return " ".join(token_array)

# 处理单条数据,生成输入-目标对
def process_example(example):
    raw_sentence = token_to_string(example["tokens"])
    # 这里用替换"The"作为简化示例,实际任务可根据需求调整目标生成逻辑
    simplified_sentence = raw_sentence.replace("The", "XXXXXXXXXXX")
    return {
        "complex_sentence": raw_sentence,
        "target_sentence": simplified_sentence
    }

# 批量处理数据集,移除无用字段
processed_dataset = raw_dataset.map(process_example).remove_columns(["id", "tokens", "tags", "ner_tags"])

3. Tokenize数据集

def tokenize_function(examples):
    # 处理编码器输入
    model_inputs = tokenizer(
        examples["complex_sentence"],
        truncation=True,
        padding="max_length",
        max_length=128
    )
    # 处理目标文本,作为模型的labels
    with tokenizer.as_target_tokenizer():
        labels = tokenizer(
            examples["target_sentence"],
            truncation=True,
            padding="max_length",
            max_length=128
        )
    # 将padding部分的token_id替换为-100,模型计算损失时会忽略这些位置
    model_inputs["labels"] = [
        [-100 if token == tokenizer.pad_token_id else token for token in label]
        for label in labels["input_ids"]
    ]
    return model_inputs

# 批量执行tokenize
tokenized_datasets = processed_dataset.map(tokenize_function, batched=True)
# 设置数据集格式为PyTorch张量,方便Trainer加载
tokenized_datasets.set_format("torch", columns=["input_ids", "attention_mask", "labels"])

4. 配置训练参数与启动训练

# 加载BLEU评估指标
bleu = evaluate.load("bleu")

# 定义自定义指标计算函数
def compute_metrics(eval_pred):
    predictions, labels = eval_pred
    # 解码预测结果,跳过特殊token
    decoded_preds = tokenizer.batch_decode(predictions, skip_special_tokens=True)
    # 还原labels中的-100为pad_token_id,再解码
    labels = [[label if label != -100 else tokenizer.pad_token_id for label in label_seq] for label_seq in labels]
    decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)
    # 计算BLEU分数(注意references要嵌套成二维数组)
    result = bleu.compute(predictions=decoded_preds, references=[[label] for label in decoded_labels])
    return {"bleu": result["bleu"]}

# 配置训练参数
training_args = Seq2SeqTrainingArguments(
    output_dir="./t5-wikisplit-finetuned",  # 模型保存路径
    log_level="error",
    num_train_epochs=1,
    learning_rate=3e-5,
    lr_scheduler_type="linear",
    warmup_steps=50,
    optim="adafactor",
    weight_decay=0.01,
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    gradient_accumulation_steps=8,
    evaluation_strategy="steps",
    eval_steps=100,
    predict_with_generate=True,
    generation_max_length=128,
    save_steps=500,
    logging_steps=10,
    push_to_hub=False,
    auto_find_batch_size=True
)

# 使用Seq2Seq专用的数据收集器,自动处理decoder_input_ids等细节
data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)

# 初始化Trainer
trainer = Seq2SeqTrainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    tokenizer=tokenizer,
    data_collator=data_collator,
    compute_metrics=compute_metrics
)

# 启动训练
trainer.train()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:55:44