使用SciBERT初始化TFBertForTokenClassification出现权重及梯度警告的原因?
咱们一步步拆解你遇到的这几个警告,其实都是正常现象,不用太担心,下面给你详细解释:
1. 加载模型时的权重不匹配警告
你用的allenai/scibert_scivocab_uncased是预训练好的SciBERT模型,它原本是针对掩码语言模型(MLM)和句子对分类任务训练的,自带的任务头部是cls.predictions(用于MLM)和cls.seq_relationship(用于句子对任务)。
而你现在要做的是命名实体识别(NER),属于Token级分类任务,用的TFBertForTokenClassification模型类需要的是一个针对每个token输出分类结果的classifier层。所以加载时会出现两种情况:
- 提示未被使用的
classifier.weight和classifier.bias,其实是原预训练模型根本没有这个Token分类任务的头部权重,这条提示有点误导,但本质是预训练模型的任务头部和你当前任务不匹配。 - 新初始化的
cls.predictions.*、cls.seq_relationship.*权重,是原预训练模型的任务头部,但你当前的Token分类任务用不到这些,所以框架会重新初始化它们(后续训练也不会更新这些参数,因为和你的任务无关)。
总结:这个警告是因为你用通用预训练SciBERT初始化了特定任务(Token分类)的模型,任务头部不匹配是正常的,后续在你的NER数据集上fine-tune模型,训练专属的classifier层即可。
2. 拟合模型时的梯度不存在警告
BERT模型里的pooler层是用来生成句子级表征的(把<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>token的输出经过全连接层得到向量,用于句子分类这类任务),但NER是Token级任务,只需要处理每个token的输出,完全用不到pooler层的参数。
所以训练时,loss的计算和pooler层参数没有任何关联,自然不会产生梯度,TensorFlow就会提示“Gradients do not exist”。这完全是正常现象,不会影响你的NER模型训练,pooler层参数会保持预训练状态,也不会干扰任务结果。
最终结论
这两个警告都属于任务切换时的正常情况,你只需要继续在自己的NER数据集上对模型进行fine-tune训练,完成后就可以正常用于预测和推理了。
内容的提问来源于stack exchange,提问作者Ghazi Sultan

