BERT - 池化输出与序列输出的第一个向量不同

use*_*376 6 nlp deep-learning keras tensorflow

我在 Tensorflow 中使用 BERT,但有一个细节我不太明白。根据文档(https://tfhub.dev/google/bert_uncased_L-12_H-768_A-12/1),汇集的输出是整个序列的。根据原始论文,这似乎是 setence 开头标记“CLS”的输出。

pooled_output[0]
Run Code Online (Sandbox Code Playgroud)

但是,当我查看句子中第一个标记对应的输出时

setence_output[0,0,:]
Run Code Online (Sandbox Code Playgroud)

我相信它对应于标记“CLS”(句子中的第一个标记),两个结果不同。

Mas*_*ari 12

正如BertModel输出的 Huggingface 文档中提到的,池化器输出为:

序列的第一个标记(分类标记)的最后一层隐藏状态由线性层和 Tanh 激活函数进一步处理。

因此,由于further processed by a Linear layer and a Tanh activation function,序列输出(CLS token)的第一个向量的输出和池化输出的输出不具有相同的值(但两个向量的大小相同)


Ash*_*'Sa 11

pooled_output和的意图sequence_output不同。由于输出层的 BERT 模型的嵌入被称为上下文嵌入,因此第一个令牌(即令牌)的输出[CLS]将捕获足够的上下文。因此,BERT 论文的作者发现仅使用第一个标记的输出就足以完成分类等少数任务。他们将单个令牌(即第一个令牌)的输出称为 pooled_output

由于 TF Hub 模块的源代码不可用,并且假设 TFHub 将使用与 BERT 作者的开源版本代码相同的实现(https://github.com/google-research/bert /)。modeling.py正如脚本(https://github.com/google-research/bert/blob/bee6030e31e42a9394ac567da170a89a98d2062f/modeling.py)的源代码所示, pooled_output(通常由函数调用get_pooled_output())返回第一个隐藏状态的激活令牌。

  • 这并没有解决OP问题 - 为什么 pooled_output[0] 与 setence_output[0,0,:] 不同 (2认同)

小智 3

当我使用 Transformers 库中的 BertModel 时,我遇到了类似的问题,我认为您的问题可能是相同的。这是我发现的\xe2\x80\x99:

\n

BertModel的输出包含一个sequence_output(通常形状为[batch_size, max_sequence_length, 768]),它是Bert的最后一层。它还有一个 pooled_output (通常形状为 [batch_size, 768]),它是附加 \xe2\x80\x9cpooler\xe2\x80\x9d 层的输出。池化层采用sequence_output[:, 0](第一个令牌,即CLS令牌),然后是密集层和Tanh激活。

\n

pooled_output 的名字来自于\xe2\x80\x99s,以及为什么它\xe2\x80\x99s 与 CLS 令牌不同,但两者应该具有相同的目的。

\n