微调时如何正确设置Pad Token(非EOS)以避免模型不生成EOS
无Pad Token模型微调的标准Pad Token配置方案及问题解决
官方推荐的两种核心配置方案
针对原生未设置Pad Token的预训练模型(如Falcon、GPT2),Hugging Face官方提供两种标准配置思路:
方案1:复用现有特殊Token(如EOS)作为Pad Token
这种方式无需修改词表,适合快速适配,但需注意全流程参数同步:
- 首先同步Tokenizer与模型配置:
tokenizer.pad_token = tokenizer.eos_token model.config.pad_token_id = model.config.eos_token_id - 训练阶段:数据处理时必须传入
attention_mask,且损失计算设置ignore_index=tokenizer.pad_token_id(避免Pad位置影响模型更新); - 推理阶段:生成参数需同时指定
eos_token_id=tokenizer.eos_token_id和pad_token_id=tokenizer.pad_token_id,必要时设置stop_sequences=[tokenizer.eos_token]或max_new_tokens限制生成长度。
方案2:添加独立Pad Token并适配模型
若需避免EOS与Pad Token混淆,可新增独立Pad Token,步骤如下:
- 向Tokenizer添加Pad Token:
tokenizer.add_special_tokens({'pad_token': '<PAD>'}) - 调整模型嵌入层以适配新的词表长度:
model.resize_token_embeddings(len(tokenizer)) - 同步模型配置的Pad Token ID:
model.config.pad_token_id = tokenizer.pad_token_id
常见问题及解决方法
Falcon设Pad为EOS后生成无法停止
核心原因是训练/推理参数未同步:
- 检查训练时是否正确使用
attention_mask屏蔽Pad位置,且损失计算设置了ignore_index; - 推理时必须在
generate()中明确指定eos_token_id和pad_token_id,否则模型会将Pad Token视为正常生成内容,不会触发停止逻辑。
添加独立Pad Token时的报错处理
配置过时警告:
多因模型配置的特殊Token参数未完全同步,可手动统一配置:model.config.bos_token_id = tokenizer.bos_token_id model.config.eos_token_id = tokenizer.eos_token_id model.config.pad_token_id = tokenizer.pad_token_id或升级
transformers库至最新版本,部分旧版本存在配置同步bug。RuntimeError: 'topk_cpu' not implemented for 'Half':
半精度(FP16)张量在CPU上不支持topk操作,解决方式三选一:- 迁移模型与数据至GPU:
model = model.to('cuda'); - 将模型转为单精度(FP32):
model = model.float(); - 生成时禁用采样(采用贪心搜索):
model.generate(..., do_sample=False),避免触发topk计算。
- 迁移模型与数据至GPU:
GPT2案例:EOS作为Pad Token的潜在风险
GPT2原生无Pad Token,若直接将EOS设为Pad Token,会出现EOS概率无法正常更新的问题:
训练时,Pad位置的损失会被ignore_index屏蔽,但真实标签中的EOS与作为Pad的EOS无法区分,模型会误将所有EOS位置的损失视为无需学习,导致推理时EOS的预测概率偏低,生成无法正常停止。这种场景下,优先推荐使用方案2添加独立Pad Token。
内容的提问来源于stack exchange,提问作者Charlie Parker
相关产品推荐
相关产品推荐

