BertForSequenceClassification 是不是在 CLS 向量上进行分类?

Posted

技术标签:

【中文标题】BertForSequenceClassification 是不是在 CLS 向量上进行分类?【英文标题】:Does BertForSequenceClassification classify on the CLS vector?BertForSequenceClassification 是否在 CLS 向量上进行分类? 【发布时间】:2020-07-07 15:00:17 【问题描述】:

我正在使用 Huggingface Transformer 包和带有 PyTorch 的 BERT。我正在尝试进行 4 向情感分类,并正在使用 BertForSequenceClassification 构建一个模型,最终最终导致 4 向 softmax。

我阅读 BERT 论文的理解是,输入 CLS 标记的最终密集向量用作整个文本字符串的表示:

每个序列的第一个标记始终是一个特殊的分类标记 ([CLS])。这个token对应的最终隐藏状态作为分类任务的聚合序列表示。

那么,BertForSequenceClassification 真的会训练并使用这个向量来执行最终分类吗?

我问的原因是因为当我print(model) 时,CLS 向量正在被使用对我来说并不明显。

model = BertForSequenceClassification.from_pretrained(
    model_config,
    num_labels=num_labels,
    output_attentions=False,
    output_hidden_states=False
)

print(model)

这是输出的底部:

        (11): BertLayer(
          (attention): BertAttention(
            (self): BertSelfAttention(
              (query): Linear(in_features=768, out_features=768, bias=True)
              (key): Linear(in_features=768, out_features=768, bias=True)
              (value): Linear(in_features=768, out_features=768, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
            )
            (output): BertSelfOutput(
              (dense): Linear(in_features=768, out_features=768, bias=True)
              (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
              (dropout): Dropout(p=0.1, inplace=False)
            )
          )
          (intermediate): BertIntermediate(
            (dense): Linear(in_features=768, out_features=3072, bias=True)
          )
          (output): BertOutput(
            (dense): Linear(in_features=3072, out_features=768, bias=True)
            (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
            (dropout): Dropout(p=0.1, inplace=False)
          )
        )
      )
    )
    (pooler): BertPooler(
      (dense): Linear(in_features=768, out_features=768, bias=True)
      (activation): Tanh()
    )
  )
  (dropout): Dropout(p=0.1, inplace=False)
  (classifier): Linear(in_features=768, out_features=4, bias=True)

我看到有一个池化层 BertPooler 通向一个 Dropout 通向一个 Linear,这大概执行了最终的 4-way softmax。但是,我不清楚BertPooler 的使用。它是仅在 CLS 的隐藏状态上运行,还是对所有输入标记的隐藏状态进行某种池化?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

简短的回答:是的,你是对的。事实上,他们将 CLS 令牌(仅此而已)用于BertForSequenceClassification

查看BertPooler 的实现表明它正在使用第一个隐藏状态,它对应于[CLS] 标记。 我简要检查了另一个模型(RoBERTa),看看这在模型之间是否一致。在这里,也只根据 [CLS] 标记进行分类,尽管不太明显(检查行 539-542 here)。

【讨论】:

感谢您在 BertPooler 中找到该代码。这个名称具有误导性,因为深度学习中的“池化”通常意味着对多个值进行操作,例如平均池化或最大池化。他们应该把它称为GetHiddenStateOfFirstToken 哈哈,没错。就个人而言,我认为在池选项(仅第一个令牌与平均顺序)之间进行选择也会很好。可能最初的意图是后一种情况,在这种情况下,pooler 将是一个好名字。 ;-)

以上是关于BertForSequenceClassification 是不是在 CLS 向量上进行分类?的主要内容,如果未能解决你的问题,请参考以下文章