Bert

发布于 18 天前  1 次阅读


在 NLP 任务中,模型接收到的输入并不是原始文本,而是经过 tokenizer 处理后的结构化数据,比如 input_idstoken_type_idsattention_mask 等。本篇文章将通过“我爱你,你爱我”这句话,详细讲清楚这些字段的真正含义。

一、Bert模型的输入

以“我爱你,你爱我”为例

sen_code = tokenizer.encode_plus("我爱你,你爱我")

#Tokenizer 会输出如下字典(示例):
{
    'input_ids': [101, 2769, 4263, 872, 102, 872, 4263, 2769, 102],
    'token_type_ids': [0, 0, 0, 0, 0, 1, 1, 1, 1],
    'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]
}

Tokenizer 输出说明:

  • input_ids:每个字符在词表中的编码,101表示[CLS]开始符号,[102]表示[SEP]句子结尾分割符号。
    • 转换回 token:
      tokenizer.convert_ids_to_tokens(sen_code['input_ids'])
      ['[CLS]', '我', '爱', '你', '[SEP]', '你', '爱', '我', '[SEP]']
  • token_type_ids:是区分上下句的编码,上句全0,下句全1,用在Bert的NSP(下一句预测)任务上
    • 若使用 RoBERTa / Chinese-RoBERTa(如 hfl/chinese-roberta-wwm-ext)token_type_ids 始终全 0,RoBERTa 取消了 NSP 任务,即使 tokenizer 输出 1,模型也不会使用。对于中文常用的 chinese-roberta-wwm-ext、roberta-large 等模型,这一字段实际上被忽略
  • attention_mask:哪些 token 是有效输入
    • 1表示有效 token,可被 attention,0标识padding,不参与 attention
    • 注意:所有 token 都会作为 query,但它们只会关注 mask 为 1 的 key/value。

Bert模型的输入是三个embedding的求和,token embedding,segment embedding和position embedding

# token embedding(词向量)
tokens_tensor = torch.tensor([sen_code['input_ids']]) # 添加batch维度

# segment embedding(句子区分,对 BERT-base 是需要的,在 NSP任务中使用)
segments_tensors = torch.tensor([sen_code['token_type_ids']]) # 添加batch维度

#position_embedding  由bert生成,根据 input_ids 的长度创建,我们不用考虑。

input_embedding = token_embedding  + segment_embedding + position_embedding