为什么BERT NSP head linear layer有两个输出?
Why does the BERT NSP head linear layer have two outputs?
这是有问题的代码。
https://github.com/huggingface/transformers/blob/master/src/transformers/modeling_bert.py#L491
class BertOnlyNSPHead(nn.Module):
def __init__(self, config):
super().__init__()
self.seq_relationship = nn.Linear(config.hidden_size, 2)
def forward(self, pooled_output):
seq_relationship_score = self.seq_relationship(pooled_output)
return seq_relationship_score
我认为它只是对一个句子跟随另一个句子的可能性进行排名?不就是一分吗?
这两个分数旨在表示模型中的非标准化概率 (logits
)。如果我们对它们进行 softmax,我们就会得到我们的预测,其中索引 0 表示下一个句子,索引 1 表示随机。
这只是代表 HuggingFace 作者的风格选择,可能是为了保持损失函数的一致性。
这里是BertForPretraining
的forward
方法,其中self.cls
是BertOnlyNSPHead
:
prediction_scores, seq_relationship_score = self.cls(sequence_output, pooled_output)
outputs = (prediction_scores, seq_relationship_score,) + outputs[
2:
] # add hidden states and attention if they are here
if masked_lm_labels is not None and next_sentence_label is not None:
loss_fct = CrossEntropyLoss()
masked_lm_loss = loss_fct(prediction_scores.view(-1, self.config.vocab_size), masked_lm_labels.view(-1))
next_sentence_loss = loss_fct(seq_relationship_score.view(-1, 2), next_sentence_label.view(-1))
total_loss = masked_lm_loss + next_sentence_loss
outputs = (total_loss,) + outputs
对 MLM 和 NSP 使用相同的 CrossEntropyLoss 很方便。
正如您所描述的,这相当于让 NSP 产生单个输出,然后将该数字输入 sigmoid 以获得下一个句子的概率。然后我们可以用 BCEWithLogitsLoss
进行训练。 (其中 BCE
只是交叉熵损失的特殊二进制情况)。
这是有问题的代码。
https://github.com/huggingface/transformers/blob/master/src/transformers/modeling_bert.py#L491
class BertOnlyNSPHead(nn.Module):
def __init__(self, config):
super().__init__()
self.seq_relationship = nn.Linear(config.hidden_size, 2)
def forward(self, pooled_output):
seq_relationship_score = self.seq_relationship(pooled_output)
return seq_relationship_score
我认为它只是对一个句子跟随另一个句子的可能性进行排名?不就是一分吗?
这两个分数旨在表示模型中的非标准化概率 (logits
)。如果我们对它们进行 softmax,我们就会得到我们的预测,其中索引 0 表示下一个句子,索引 1 表示随机。
这只是代表 HuggingFace 作者的风格选择,可能是为了保持损失函数的一致性。
这里是BertForPretraining
的forward
方法,其中self.cls
是BertOnlyNSPHead
:
prediction_scores, seq_relationship_score = self.cls(sequence_output, pooled_output)
outputs = (prediction_scores, seq_relationship_score,) + outputs[
2:
] # add hidden states and attention if they are here
if masked_lm_labels is not None and next_sentence_label is not None:
loss_fct = CrossEntropyLoss()
masked_lm_loss = loss_fct(prediction_scores.view(-1, self.config.vocab_size), masked_lm_labels.view(-1))
next_sentence_loss = loss_fct(seq_relationship_score.view(-1, 2), next_sentence_label.view(-1))
total_loss = masked_lm_loss + next_sentence_loss
outputs = (total_loss,) + outputs
对 MLM 和 NSP 使用相同的 CrossEntropyLoss 很方便。
正如您所描述的,这相当于让 NSP 产生单个输出,然后将该数字输入 sigmoid 以获得下一个句子的概率。然后我们可以用 BCEWithLogitsLoss
进行训练。 (其中 BCE
只是交叉熵损失的特殊二进制情况)。