基于DistilBERT的Cross-encoder模型CLS嵌入趋同问题排查求助
问题排查与修复方案
1. 模型类初始化的致命错误
你的CrossEncoderModel类的__init__方法中,super()调用的类名错误:
super(ParagraphCrossEncoderModel, self).__init__()
错误的父类名称会导致模型参数无法正确注册,反向传播的梯度更新逻辑完全混乱,这是引发embedding坍缩的核心原因之一。
修正后:
super(CrossEncoderModel, self).__init__()
2. 损失函数调用方式错误
BCEWithLogitsLoss的正确用法是先实例化损失函数对象,再传入预测值和标签。你的写法:
loss = torch.nn.BCEWithLogitsLoss(logits, labels)
会错误地将logits和labels当成损失函数的初始化参数(实际对应weight和pos_weight),导致损失计算完全错误,反向传播的梯度异常,最终触发embedding快速趋同。
修正后:
# 实例化损失函数(建议放在训练循环外) criterion = torch.nn.BCEWithLogitsLoss() # 训练循环内计算损失 loss = criterion(logits, labels.float()) # labels需转为float类型,与logits dtype匹配 loss.backward() optimizer.step() optimizer.zero_grad()
3. 分层学习率设置缺失
直接用统一学习率训练预Transformer层和随机初始化的FC层,会导致预训练参数被过大的梯度冲垮,引发embedding坍缩。冻结Transformer能正常训练,说明FC层逻辑没问题,但全量训练时必须给Transformer层设置远小于FC层的学习率。
修正方案:
from torch.optim import AdamW # 分层配置参数与学习率 optimizer_grouped_parameters = [ {"params": self.transformer.parameters(), "lr": 2e-5}, # 预训练层用小学习率 {"params": self.fc.parameters(), "lr": 1e-3} # 随机初始化的FC层用较大学习率 ] optimizer = AdamW(optimizer_grouped_parameters)
4. 自定义损失函数的逻辑问题
你的自定义损失函数硬编码了固定目标值[10.0, -10.0, -10.0],未与输入labels关联,不符合二分类任务的损失逻辑,但核心问题仍集中在前面的初始化和损失调用错误,导致换损失函数也无法解决坍缩问题。
验证步骤
- 优先修复模型类
super()调用和损失函数调用的错误 - 配置分层学习率
- 用3样本dummy数据集测试,此时模型应能正常过拟合,embedding不会趋同
内容的提问来源于stack exchange,提问作者Ben Chen
相关产品推荐
相关产品推荐

