我可以使用 BERT 作为特征提取器,而不对我的特定数据集进行任何微调吗?

SBf*_*ing 5 pytorch bert-language-model huggingface-transformers

我正在尝试解决 10 个类别的多标签分类任务,其中相对平衡的训练集由约 25K 样本组成,评估集由约 5K 样本组成。

我正在使用拥抱脸:

model = transformers.BertForSequenceClassification.from_pretrained(...
Run Code Online (Sandbox Code Playgroud)

并获得相当不错的结果(ROC AUC = 0.98)。

然而,我目睹了一些奇怪的行为,我似乎无法理解 -

我添加以下代码行:

for param in model.bert.parameters():
    param.requires_grad = False
Run Code Online (Sandbox Code Playgroud)

同时确保学习模型的其他层,即:

[param[0] for param in model.named_parameters() if param[1].requires_grad == True]
gives
['classifier.weight', 'classifier.bias']
Run Code Online (Sandbox Code Playgroud)

像这样配置时训练模型会产生一些令人尴尬的糟糕结果(ROC AUC = 0.59)。

我的假设是,开箱​​即用的预训练 BERT 模型(无需任何微调)应该作为分类层相对较好的特征提取器。那么,我到底哪里做错了呢?

den*_*ger 3

根据我的经验,你的假设是错误的

开箱即用的预训练 BERT 模型(无需任何微调)应该作为分类层相对较好的特征提取器。

当我尝试使用 BERT 的输出层作为词嵌入值时,我注意到了类似的经历,几乎没有微调,这也给出了非常差的结果;这也是有道理的,因为您可以有效地768*num_classes以最简单形式的输出层建立连接。与 BERT 的数百万个参数相比,这使您对复杂模型的控制量几乎可以忽略不计。然而,我还想在训练完整模型时谨慎地指出过度拟合的结果,尽管我确信您已经意识到这一点。

BERT 的整个想法是微调模型的成本非常低,因此为了获得理想的结果,我建议不要冻结任何层。禁用至少部分层会有所帮助的一个实例是嵌入组件,具体取决于模型的词汇量大小(BERT-base 约为 30k)。