微调TrOCR在自定义收据数据集训练时Loss与CER上升问题排查
可能导致TrOCR微调性能持续恶化的原因及解决方法
数据预处理存在疏漏
TrOCR的TrOCRProcessor需要严格匹配预训练的处理逻辑,若手动构建batch而非用processor的prepare_seq2seq_batch方法,极易出现问题:- 确认
decoder_input_ids是否为左移一位的标签(Seq2Seq训练要求decoder输入是去掉最后一个token的标签,labels则是去掉第一个token的标签)。如果直接把labels当作decoder_input_ids喂入模型,训练逻辑会完全错误。 - 检查图像预处理是否和预训练一致:比如输入图像尺寸是否为384x384(trocr-base-printed的默认要求),归一化的均值、方差是否匹配processor的设置。
- 核对数据集的标签与bbox图像的对应关系:有没有标签标注错误、bbox裁剪失误(比如裁入空白区域或无关文字)的情况,样本错误率过高会导致模型学习方向偏离。
- 确认
训练参数设置不合理
- 学习率过高:5e-5对于仅5000样本的全参数微调来说可能偏大,建议下调至1e-5~3e-5,同时搭配学习率调度器(比如
ReduceLROnPlateau),当验证loss停滞时自动降学习率。 - 未使用梯度累积:若单GPU batch size过小(比如<8),梯度会极度不稳定,可设置梯度累积步数,每N步更新一次权重:
accumulation_steps = 4 for batch_idx, batch in enumerate(tqdm(self.train_dataloader)): for k, v in batch.items(): batch[k] = v.to(self.device) outputs = self.model(**batch) loss = outputs.loss / accumulation_steps # 均分loss避免梯度爆炸 loss.backward() if (batch_idx + 1) % accumulation_steps == 0: self.optimizer.step() self.optimizer.zero_grad() - 未冻结预训练Encoder:TrOCR的Encoder基于ViT预训练,直接全参数微调小数据集可能破坏已有的特征提取能力。建议先冻结Encoder(设置
model.encoder.requires_grad_(False)),仅训练Decoder,2~3个epoch后再解冻全模型微调。
- 学习率过高:5e-5对于仅5000样本的全参数微调来说可能偏大,建议下调至1e-5~3e-5,同时搭配学习率调度器(比如
损失计算未屏蔽Pad Token
检查batch中是否包含attention_mask和decoder_attention_mask,若缺失,模型计算loss时会把Pad Token的损失也纳入,导致loss异常波动。确保processor生成的batch包含这些mask,或手动设置model.config.pad_token_id为processor的pad token id,让模型自动忽略Pad部分的损失。训练指标计算逻辑有误
确认CER、精度等指标是在训练集还是验证集上计算的:- 若训练集指标持续恶化,说明模型完全无法拟合训练数据,大概率是预处理或训练流程存在根本性错误;
- 若训练集loss下降但验证集指标恶化,属于过拟合问题,可通过添加dropout层、增加图像数据增强(随机旋转、亮度调整、模糊等)、减少训练轮数来缓解。
内容的提问来源于stack exchange,提问作者SauceyP
相关产品推荐
相关产品推荐

