关于Hugging Face SFTTrainer微调Llama模型的截断疑问
SFTTrainer微调Llama时长样本处理问题解答
关于长样本是否被截断的问题
当你设置max_seq_length=512且packing=True时,长度超过512的样本不会被直接截断。SFTTrainer的packing机制会自动将长样本拆分成多个长度为512的片段(最后一个片段可能不足512),然后把这些片段和其他短样本打包拼接,填充到max_seq_length的序列中进行训练。
不过要注意:如果在tokenization阶段手动设置了truncation=True,那长样本会先被截断到512,packing机制就不会再拆分它了。所以要保留长样本的拆分逻辑,tokenization时不要加截断参数。
替代截断的简便拆分方案
其实SFTTrainer自带的packing已经实现了自动拆分长样本的功能,不需要额外写复杂代码。如果想要更精细控制拆分逻辑,可以在数据集预处理阶段手动拆分:
手动拆分长样本的代码示例
def split_long_samples(examples, max_length=512): new_examples = {"input_ids": [], "attention_mask": [], "labels": []} # 批量处理样本 for input_ids, attention_mask, labels in zip(examples["input_ids"], examples["attention_mask"], examples["labels"]): # 按max_length分段切割 for i in range(0, len(input_ids), max_length): seg_input_ids = input_ids[i:i+max_length] seg_attention_mask = attention_mask[i:i+max_length] seg_labels = labels[i:i+max_length] # 填充到指定长度(可选,根据训练需求) if len(seg_input_ids) < max_length: pad_len = max_length - len(seg_input_ids) seg_input_ids += [tokenizer.pad_token_id] * pad_len seg_attention_mask += [0] * pad_len seg_labels += [-100] * pad_len # padding部分不计算loss new_examples["input_ids"].append(seg_input_ids) new_examples["attention_mask"].append(seg_attention_mask) new_examples["labels"].append(seg_labels) return new_examples # 应用到tokenized后的数据集 tokenized_dataset = tokenized_dataset.map(split_long_samples, batched=True)
额外注意事项
- 处理前要确保Llama的tokenizer设置了pad_token:
tokenizer.pad_token = tokenizer.eos_token,否则填充操作会报错。 - 手动拆分后再开启
packing=True,会把拆分后的片段和原短样本进一步打包,提升训练数据的利用率。
内容的提问来源于stack exchange,提问作者iiiiiiiiiiiiiiiiiiii
相关产品推荐
相关产品推荐

