微调T5模型不收敛求助:文本转结构化JSON任务优化
问题
作为Transformer与NLP领域新手,在针对特定任务微调T5模型时遇到性能瓶颈。任务目标是让模型接收输入文本,输出包含相关信息的JSON字符串,共有3种响应格式,示例如下:
输入:Hey, can you give one hundred dollars to John?
预期输出:'{"action": "T", "data": {"name": "John", "amount": 100, "currency": "USD"}}'
输入:I want to add Benjamin Franklin to my contacts. He has an account on citibank, with number 412389124.
预期输出:'{"action": "A", "data": {"name": "Benjamin Franklin", "account_no": 412389124, "entity": "Citibank", "id_num": null}}'
输入:Hey, what's the weather gonna be tonight?
预期输出:'{"accion": "N", "datos": {}}'
使用Python生成20000条随机数据点,基于google/t5-base模型,通过PyTorch Trainer训练,核心代码如下:
model_name_huggingface = "google/t5-base" tokenizer = T5Tokenizer.from_pretrained(model_name_huggingface) model = T5ForConditionalGeneration.from_pretrained(model_name_huggingface)
分词后设置训练参数:
batch_size = 16 training_args = Seq2SeqTrainingArguments( output_dir="models/chimi-mt5-base", evaluation_strategy="steps", eval_steps=100, logging_strategy="steps", logging_steps=100, save_strategy="steps", save_steps=200, optim="adafactor", learning_rate=5e-4, per_device_train_batch_size=batch_size, per_device_eval_batch_size=batch_size, predict_with_generate=True, weight_decay=0.05, save_total_limit=3, num_train_epochs=2, metric_for_best_model="exact_match", load_best_model_at_end=True )
数据处理与指标计算:
data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=base_model) cer = evaluate.load("cer", module_type="metric") exact_match = evaluate.load("exact_match", module_type="metric")
import numpy as np def compute_metrics(eval_pred): predictions, labels = eval_pred decoded_preds = tokenizer.batch_decode(predictions, skip_special_tokens=True) # Replace -100 in the labels as we can't decode them. labels = np.where(labels != -100, labels, tokenizer.pad_token_id) decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True) result = {} # Compute CER result["cer"] = cer.compute(predictions=decoded_preds, references=decoded_labels) # Compute Exact Match exact_match_res = exact_match.compute(predictions=decoded_preds, references=decoded_labels, ignore_case=True) result["exact_match"] = exact_match_res["exact_match"] return {k: round(v, 4) for k, v in result.items()}
训练执行:
trainer = Seq2SeqTrainer( model=base_model, args=training_args, train_dataset=tokenized_chimi_dataset["train"], eval_dataset=tokenized_chimi_dataset["validation"], data_collator=data_collator, tokenizer=tokenizer, compute_metrics=compute_metrics ) result = trainer.train()
训练后,训练损失降至0.054后不再提升,验证损失降至0.034后不再提升;CER指标最低0.4875,Exact Match最高0.3089。测试发现模型能输出正确JSON格式,action字段通常正确,但JSON内的数据常出错。已尝试平衡数据集、调优超参数,性能无明显提升,寻求可行的优化方案。
优化方案
1. 优化数据集构建
- 增强数据质量:手动校验随机生成的样本,确保输入文本与输出JSON的映射完全准确;补充真实场景的指令样本(而非纯随机生成),提升模型对真实表述的泛化能力。
- 统一输出格式:将输出JSON的键名统一(比如第三个示例的
accion/datos改为与前两个一致的action/data),减少模型的学习负担;确保所有JSON的语法规范完全统一(引号、逗号、括号使用一致)。 - 数据增强:对输入文本进行同义改写(替换同义词、调整句式),生成更多变体样本,同时保持输出JSON不变,提升模型对同语义不同表述的识别能力。
2. 调整训练策略
- 增加训练轮次与学习率调度:将训练轮次提升至5-8轮,同时使用
cosine或linear学习率衰减策略;初始学习率降至1e-4或2e-4,避免大学习率导致的训练不稳定。 - 分层冻结训练:先冻结T5编码器的前6层,仅训练顶层和解码器,1-2轮后再解冻全部层微调,让模型先保留预训练的通用语言能力,再适配特定任务。
- 切换更大模型:尝试
google/t5-large或google/t5-xl,更大的模型容量能更好地学习细粒度的数据抽取规则(需注意硬件资源是否支持)。
3. 优化训练目标与评价指标
- 自定义加权损失:针对JSON的
data字段设置加权损失,对name、amount等关键字段的预测错误赋予更高权重,引导模型关注细粒度信息。 - 添加字段级评价指标:除Exact Match外,新增
action字段准确率、data内各字段准确率、JSON结构合规率等指标,精准定位模型薄弱环节,针对性优化。 - 推理时使用束搜索:设置
num_beams=3或5进行生成,替代贪心搜索,提升输出文本的准确性和一致性。
4. 输入输出的任务提示优化
- 添加固定任务前缀:在输入文本前添加
"extract information to JSON: "这类固定前缀,明确告知模型任务类型,提升任务针对性。 - 标准化输出顺序:训练时固定JSON字段的生成顺序(比如先
action,再data内的name、amount等),减少模型的决策空间,提升抽取准确性。
内容的提问来源于stack exchange,提问作者Enzo De Filippis

