赞
踩
BERT 的具体介绍,我就略过了,一是网上可以找到很多资料,二是我也只是刚使用了下 BERT,很多细节还不清楚,就不乱说话误导人了。老实说,最开始查资料,找相关工程时,看的头大,不知从何入手。现在总结下我认为的上手BERT的合适流程。
# 我参考的一个工程是从 pytorch_pretrained_bert 中加载的 BERT 预训练模型。现在更推荐使用 transformers 库
from pytorch_pretrained_bert import BertModel, BertTokenizer
self.bert = BertModel.from_pretrained(config.bert_path)
_, pooled = self.bert(input_ids=token_tensors, token_type_ids=segments_tensor, attention_mask=mask_tensor, output_all_encoded_layers=False)
先忽略output_all_encoded_layers
这个参数,重点关注input_ids
, token_type_ids
, attention_mask
这三个输入参数,这三个参数需要从输入文本中得到并正确设置,模型才能正确工作。下面介绍这三个参数的含义以及如何设置。
大多数地方只展示了上图中第二条分隔线之上 的内容,而实际在 PyTorch 中使用 BERT 时,第二条分隔线之下的内容才是最重要的。我们需要将文本转化为3种 id tensors:
tensors | 含义 |
---|---|
tokens_tensor | 对应上文的 input_ids,存储每个 token 的索引值,用 tokenizer 转化文本获得。所有任务都需要有这个输入 |
segments_tensor | 对应上文的 token_type_ids,用来识别句子界限。如果是单句子分类任务,默认为全0,可以不用设置该参数;如果是文本蕴含关系等句对任务,则第一个句子对应的位置全0,句子间分隔符 [SEP] 处置为0,第二个句子对应位置全1,句尾分隔符 [SEP] 处置为1, [PAD] 处全置0 |
mask_tensor | 对应上文的 attention_mask,用来界定注意力机制范围。1表示让 BERT 关注该位置,0代表是 [PAD] 不用关注。即 [PAD]处为0,其余位置为1 |
在实际应用时,给定一段文本,我们只需要得到这段文本对应的3个 tensors,将其传入 BERT 模型即可,这就是 BERT 模型输入端的设置。举个例子
# 单句子任务 sentence = "I am fine." SEP, PAD, CLS = '[SEP]', '[PAD]', '[CLS]' pad_size = 20 # 切记为句子补上开头的 [CLS] 及 结尾的 [SEP],如果有padding操作,则需补上相应长度的 [PAD] # 格式为 [CLS] + 句子 + [SEP] + [PAD] * N token = [CLS] + config.tokenizer.tokenize(sentence) + [SEP] length = len(token) token += [PAD] * (pad_size - length) tokens_tensor = config.tokenizer.convert_tokens_to_ids(token) # 用 tokenizer 转化,传递给 input_ids segments_tensor = [0] * pad_size # 单句子任务可以不设置此tensor, token_type_ids 默认为全0,传递给 token_type_ids mask_tensor = [1] * length + [0] * (pad_size - length) # [PAD] 处全置0,其余位置置1,传递给 attention_mask # 将以上3个 tensor 作为输入传递给 BERT 模型 _, pooled = self.bert(input_ids=tokens_tensor, token_type_ids=segments_tensor, attention_mask=mask_tensor, output_all_encoded_layers=False) # 或者不设置 segments_tensor _, pooled = self.bert(input_ids=tokens_tensor, attention_mask=mask_tensor, output_all_encoded_layers=False)
# 句子对任务 sentence_A = "I am fine." sentence_B = "Thank you." SEP, PAD, CLS = '[SEP]', '[PAD]', '[CLS]' pad_size = 20 # 切记补上开头的 [CLS], 句子分隔处的 [SEP], 句末 [SEP],如果有padding操作,则需补上相应长度的 [PAD] # 格式为 [CLS] + 句子A + [SEP] + 句子B + [SEP] + [PAD] * N token_A = config.tokenizer.tokenize(sentence_A) token_B = config.tokenizer.tokenize(sentence_B) len_A, len_B = len(token_A), len(token_B) token = [CLS] + token_A + [SEP] + token_B + [SEP] length = len(token) token += [PAD] * (pad_size - length) token_sensor = config.tokenizer.convert_tokens_to_ids(token) # 用 tokenizer 转化,传递给 input_ids segments_tensor = [0] * (len_A + 2) + [1] * (len_B + 1) + [0] * (pad_size - length) # 句子对任务需要设置此tensor, 传递给 token_type_ids mask_tensor = [1] * length + [0] * (pad_size - length) # [PAD] 处全置0,其余位置置1,传递给 attention_mask # 将以上3个 tensor 作为输入传递给 BERT 模型 _, pooled = self.bert(input_ids=tokens_tensor, token_type_ids=segments_tensor, attention_mask=mask_tensor, output_all_encoded_layers=False)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。