HuggingFace Trainer微调InCoder报dim1序列长度不匹配错误
报错根因
这个序列长度不匹配的错误核心原因是未给Trainer配置支持动态填充的批处理逻辑:
- 你在tokenize阶段只开启了截断(
truncation=True),没有做统一长度填充,不同样本经过tokenizer处理后长度存在差异 - Trainer默认使用的
torch_default_data_collator没有自动对齐序列长度的能力,只会直接尝试将同批次的样本列表拼接为张量,遇到长度不一致的序列就会抛出你看到的ValueError - 你代码里还存在两个隐性bug:一是数据集切分后的变量名和后续删列步骤引用的变量名不匹配,二是
optimizers参数传了未实例化的类,运行时也会触发错误
修复方案
按以下步骤调整代码即可解决问题:
- 导入HuggingFace Transformers内置的因果语言模型专用数据整理器
DataCollatorForLanguageModeling,该组件会在每次加载批次时,动态将当前批次内的所有序列填充到和批次内最长序列一致的长度,同时自动将padding位置的标签设为-100(训练时这部分位置不计算损失,比手动复制input_ids作为labels的逻辑更规范) - 修正变量名引用错误,删除手动添加labels列的冗余逻辑,这部分交给数据整理器自动处理
- 初始化Trainer时传入配置好的
data_collator参数,移除错误的优化器传参(如果没有自定义优化器的强需求,直接用Trainer默认的AdamW优化器+线性学习率调度器即可,不需要手动传入) - 补充InCoder tokenizer缺失的pad token配置,InCoder默认没有独立pad token,用eos_token代替即可
修正后完整代码
from datasets import load_dataset dataset = load_dataset("ablam/gcode") from transformers import AutoTokenizer # 加载InCoder tokenizer,保留大小写 tokenizer = AutoTokenizer.from_pretrained( "facebook/incoder-1B", use_fast=True, do_lower_case=False ) # 配置pad token tokenizer.pad_token = tokenizer.eos_token # 批量tokenize,只开截断,不开固定长度填充(交给collator做动态padding更省显存) def tokenize_function(examples): return tokenizer(examples["text"], truncation=True, max_length=1024) # 可根据显存调整最大长度阈值 tokenized_datasets = dataset.map(tokenize_function, batched=True, num_proc=4) # 直接删掉不需要的列,省得后续重复处理 tokenized_datasets = tokenized_datasets.remove_columns(['text', 'token_type_ids']) # 切分1%的数据集用于测试 train_1percent = tokenized_datasets['train'].train_test_split(test_size=0.01)['test'] test_1percent = tokenized_datasets['test'].train_test_split(test_size=0.01)['test'] import numpy as np from datasets import load_metric metric = load_metric("accuracy") def compute_metrics(eval_pred): logits, labels = eval_pred # 过滤padding位置的标签,避免干扰指标计算 mask = labels != -100 predictions = np.argmax(logits, axis=-1)[mask] labels = labels[mask] return metric.compute(predictions=predictions, references=labels) from transformers import TrainingArguments, Trainer, AutoModelForCausalLM, DataCollatorForLanguageModeling # 加载模型 model = AutoModelForCausalLM.from_pretrained("facebook/incoder-1B") # 初始化因果语言模型数据整理器,mlm设为False(自回归生成任务不需要掩码逻辑) data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False) training_args = TrainingArguments( output_dir="test_trainer", evaluation_strategy="epoch", per_device_train_batch_size=4, # 可根据显存大小调整 per_device_eval_batch_size=4, gradient_accumulation_steps=4, fp16=True # 支持CUDA的显卡可开启半精度训练,大幅降低显存占用 ) trainer = Trainer( model=model, args=training_args, train_dataset=train_1percent, eval_dataset=test_1percent, data_collator=data_collator, # 传入支持动态padding的数据整理器 compute_metrics=compute_metrics ) trainer.train()
补充说明:如果你确实需要固定长度填充而不是动态padding,可以在tokenize函数里加上
padding="max_length", max_length=自定义固定长度,这样所有样本都会被提前填充到统一长度,就算用默认collator也不会报长度错误,但这种方式会浪费大量显存在padding token上,训练速度也更慢,优先推荐动态padding方案。
内容的提问来源于stack exchange,提问作者ablam
相关产品推荐
相关产品推荐

