LLM报错——ValueError: Cannot handle batch sizes > 1 if no padding token is defined.
LLM报错ValueError: Cannot handle batch sizes > 1 if no padding token is defined.的解决方案
1 问题描述
我尝试对 Qwen2.5-0.5B-Instruct 进行 SFT,封装了 DataLoader 后模型在运行的时候报错:ValueError: Cannot handle batch sizes > 1 if no padding token is defined.
2 解决方案
问题报错的内容是当 batch sizes > 1 时 pad_token 没有定义,所以采用以下步骤排查问题:
步骤1:先排查是不是 tokenizer 的问题,最简单的思路就是先打印出来 DataLoader 中的 input_ids 和 att_masks 的 shape。
步骤2:如果 input_ids 和 att_masks 的 shape 不对,那么检查 tokenizer 做 padding 的代码对不对,很有可能在做 padding 的时候只对单句做了处理,如:
inputs = self.tokenizer(
text,
truncation=True,
padding=True,
max_length=self.max_length,
return_tensors='pt'
)
而上述代码有个问题,如果 Dataset 是采用 __getitem__ 的方式实现的,那么实际上是一次只抽取一条数据做 padding,这里需要把上述代码改为:
inputs = self.tokenizer(
text,
truncation=True,
padding='max_length',
max_length=self.max_length,
return_tensors='pt'
)
从而保证 padding 的长度是固定的。
步骤3:如果上述代码是正确的,那么再排查是不是 tokenizer 的问题,采用下述代码排查:
print(tokenizer.pad_token)
print(tokenizer.pad_token_id)
检查这两个是否为 None,如果为 None,说明是 tokenizer 在加载预训练参数时没有加载 pad_token 或者根本没有,那么可以采用下述方法设置:
tokenizer.pad_token = tokenizer.eos_token
如果 tokenizer 也没有 eos_token,那么可以自定义 pad_token:
tokenizer.add_special_tokens({'pad_token': '[PAD]'})
步骤4:如果上述排查都没问题,那么继续排查 model 的问题,首先用下述代码排查:
# 注意这里的 model 指的是模型本身, 比如 Qwen2ForSequenceClassification
# 而非自己定义的 model 这个类
# 而且这里的 model 是 from_pretrained 加载后的
print(self.model.config.pad_token_id)
如果步骤1-3都没问题,那么理论上这里 print 出来的结果会为 None。接着只需要在模型 from_pretrained 之后加上如下代码即可:
self.model.config.pad_token_id = tokenizer.pad_token_id
3 问题产生原因
由于我没有在网上找到原因,我个人觉得该问题产生是因为 LLM 默认只处理单句任务,所以当模型加载后不会额外加载 pad_token_id。而 tokenizer 在处理数据的时候会给句子进行 padding,而没有加载 pad_token_id 的模型不认识这些 pad_token,所以导致的报错。
反正就我个人而言我觉得这个问题真的欺诈性太强了,我一直以为是我自己 tokenizer 或者 DataLoader 的问题,排查了好久TAT
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)