BERT模型的使用

BERT模型的使用

BERT 的具体介绍,我就略过了,一是网上可以找到很多资料,二是我也只是刚使用了下 BERT,很多细节还不清楚,就不乱说话误导人了。老实说,最开始查资料,找相关工程时,看的头大,不知从何入手。现在总结下我认为的上手BERT的合适流程。

  1. 了解 BERT 的本质。简单说,BERT 提供了更好的词向量表示,是一个加强版的 Word2Vec,我们只需要在自己的数据集上针对特定任务再进行 fine-tuning 就可以取得不错的效果。至于BERT是如何训练的,以及内部各个参数的含义,我认为可以之后再研究。
  2. 了解 BERT 的输入编码格式。这一块是困扰我最久的地方,因为在针对不同的下游任务时,需要对 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)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值