基于不同分词器的BERT EncoderDecoder模型训练异常排查求助
问题排查:英德翻译EncoderDecoder模型训练异常
核心问题分析
你的模型出现训练损失骤降但验证损失居高不下、生成结果异常的核心原因是训练时Decoder输入与标签的逻辑错误,搭配其他配置问题导致模型完全没有学习到翻译能力,而是在做无意义的“复制任务”。
具体错误点及修复方案
1. Decoder输入未做右移(关键错误)
Seq2Seq模型训练时,Decoder的输入必须是目标序列右移一位(即去掉末尾的[SEP],保留开头的[CLS]作为start token),但你直接将完整的目标token序列(包含[CLS]和[SEP])同时作为decoder_input_ids和labels,这会让模型只需要预测和输入完全相同的token就能得到0损失,完全跳过了翻译学习的过程。
修复代码:
使用shift_tokens_right工具生成正确的Decoder输入:
from transformers import shift_tokens_right def process_data_to_model_inputs(batch): inputs = tokenizer_en(batch["en"], padding="max_length", truncation=True, max_length=encoder_max_length) outputs = tokenizer_ger(batch["de"], padding="max_length", truncation=True, max_length=decoder_max_length) batch["input_ids"] = inputs.input_ids batch["attention_mask"] = inputs.attention_mask # 生成右移后的Decoder输入 batch["decoder_input_ids"] = shift_tokens_right( torch.tensor(outputs.input_ids), pad_token_id=tokenizer_ger.pad_token_id ).tolist() batch["decoder_attention_mask"] = outputs.attention_mask # 处理labels,PAD token替换为-100以忽略损失计算 batch["labels"] = [[-100 if token == tokenizer_ger.pad_token_id else token for token in labels] for labels in outputs.input_ids] return batch
2. 长度惩罚设置错误
model.config.length_penalty = -1.0为负数,会导致模型生成时极度偏好极短序列,甚至逻辑混乱。长度惩罚应设置为正数,通常取1.0(平衡序列长度与生成概率),若希望生成更长序列可设为大于1的值,反之则小于1。
修复代码:
model.config.length_penalty = 1.0
3. 生成时设备不匹配(潜在问题)
若模型在GPU上训练,但生成时输入tensor留在CPU,会导致推理异常。需将输入tensor移至模型所在设备:
修复generate_result函数:
def generate_result(batch): inputs = tokenizer_en(batch["english"].to_list(), padding="max_length", truncation=True, max_length=100, return_tensors="pt") # 将输入tensor移至模型所在设备 input_ids = inputs.input_ids.to(model.device) attention_mask = inputs.attention_mask.to(model.device) outputs = model.generate(input_ids, attention_mask=attention_mask) output_str = tokenizer_ger.batch_decode(outputs, skip_special_tokens=True) batch["translations"] = output_str return batch
4. 模型配置补充(可选优化)
虽然from_encoder_decoder_pretrained会自动继承Decoder配置,但可显式设置Decoder词汇量,避免潜在维度不匹配:
model.config.decoder.vocab_size = tokenizer_ger.vocab_size model.config.vocab_size = tokenizer_ger.vocab_size # 适配部分Transformers版本要求
修复后预期效果
- 训练损失不会再骤降,会逐步下降至合理区间
- 验证损失随训练逐步降低,与训练损失的差距缩小
- 生成时会根据输入输出对应德语翻译,不再出现重复随机token或固定输出
内容的提问来源于stack exchange,提问作者Georg B
相关产品推荐
相关产品推荐

