使用DataCollatorForCompletionOnlyLM的SFT训练无效果问题求助
项目背景
我正在开展一个参数提取项目,需要在数据集GalaktischeGurke/parameter_extraction_1500_mail_contract_invoice上微调Llama-2-7b模型。由于数据集上下文过长,全量训练会导致性能大幅下降,因此计划使用SFTTrainer搭配DataCollatorForCompletionOnlyLM,仅针对回复部分进行微调。
测试过程与问题
在调整自己的训练循环前,我先测试了官方示例代码:
from transformers import AutoModelForCausalLM, AutoTokenizer from datasets import load_dataset from trl import SFTTrainer, DataCollatorForCompletionOnlyLM dataset = load_dataset("timdettmers/openassistant-guanaco", split="train") output_dir = "./results" model = AutoModelForCausalLM.from_pretrained("facebook/opt-350m") tokenizer = AutoTokenizer.from_pretrained("facebook/opt-350m") instruction_template = "### Human:" response_template = "### Assistant:" collator = DataCollatorForCompletionOnlyLM(instruction_template=instruction_template, response_template=response_template, tokenizer=tokenizer, mlm=False) trainer = SFTTrainer( model, train_dataset=dataset, dataset_text_field="text", data_collator=collator, ) trainer.train() import os output_dir = os.path.join(output_dir, "final_checkpoint") trainer.model.save_pretrained(output_dir)
训练循环未报错,但完全没有训练效果:wandb上无train/loss曲线,保存的模型也未发生变化。
已尝试的方案
- 使用带预格式化函数的代码
- 在trainer中设置
packing=False - 自定义训练循环
以上尝试均无效果;同时发现DataCollatorForCompletionOnlyLM在Transformers官方文档中无相关说明。
1. 模板匹配失败,损失掩码未生成
DataCollatorForCompletionOnlyLM的核心是通过模板定位回复区域,仅对该区域计算损失。如果数据集文本格式和设置的instruction_template/response_template不匹配,会导致collator无法识别回复部分,所有位置损失被掩码,模型无梯度更新。
- 解决方法:
- 手动打印数据集的
text字段,确认### Human:和### Assistant:与数据中的实际分隔符完全一致(包括空格、大小写)。 - 若数据集格式不同,修改模板参数为数据中实际使用的分隔符。
- 手动打印数据集的
2. Tokenizer缺失pad token或设置错误
OPT、Llama-2等模型默认无pad token,DataCollatorForCompletionOnlyLM需要正确的pad token处理批量数据,否则掩码逻辑可能失效。
- 解决方法:
- 为tokenizer设置pad token:
tokenizer.pad_token = tokenizer.eos_token - 确认tokenizer的
padding_side设置为"right"(符合因果语言模型的训练逻辑)。
- 为tokenizer设置pad token:
3. SFTTrainer训练配置缺失或参数冻结
若模型参数被意外冻结,或SFTTrainer未配置基础训练参数,会导致模型权重不更新。
- 解决方法:
- 检查模型参数的
requires_grad状态,确保至少部分参数可训练:for param in model.parameters(): print(param.requires_grad) # 应存在True值 - 为SFTTrainer添加
TrainingArguments,明确训练批次、日志步长等参数,确保训练流程正常触发:from transformers import TrainingArguments training_args = TrainingArguments( per_device_train_batch_size=4, logging_steps=10, output_dir="./results", num_train_epochs=1 ) trainer = SFTTrainer( model, args=training_args, train_dataset=dataset, dataset_text_field="text", data_collator=collator, )
- 检查模型参数的
4. TRL版本兼容性问题
DataCollatorForCompletionOnlyLM属于trl库而非transformers,旧版本可能存在掩码逻辑bug。
- 解决方法:
- 升级trl到最新版本:
pip install --upgrade trl
- 升级trl到最新版本:
5. 手动验证掩码效果
在训练前检查collator的输出,确认labels字段是否正确掩码(非回复区域为-100,回复区域为正常token id):
sample = dataset[0] tokenized_sample = tokenizer(sample["text"], return_tensors="pt") collated = collator([tokenized_sample]) print(collated["labels"])
若所有值均为-100,说明模板匹配失败,需调整模板参数。
内容的提问来源于stack exchange,提问作者user21537823

