美文网首页
Bert如何使用预留的[unused*]

Bert如何使用预留的[unused*]

作者: WritingHere | 来源:发表于2022-03-17 15:20 被阅读0次

背景

  • 在使用Bert进行文本分析的过程中,我们需要用BERT自带的分词器(Tokenizer)来对文本序列进行分词(Tokenize),其基本原理是基于BERT自带的词典文件vocab.txt进行词汇匹配,从而得到文本序列的分词结果。
    使用Tokenizer分词
  • 然而,词典的规模毕竟有限,当遇到vocab.txt中不存在的字符时,分词器会将该字符拆分,或者干脆标记为[UNK],也就是未知词汇。在通常情况下这样处理是没有问题的,但是,如果我们需要进行一些特殊操作的时候,将未登录词识别为[UNK]就不满足我们的需求了。
  • 例如,在做关系抽取时,我们需要将实体的前后打上实体类型的标签<LOC> London <LOC> is a...,然后输入编码器。如果我们依然使用默认的分词器,那么显然没有<LOC>这个字符,就会基于word piece进行拆分,这样我们就不能用<LOC>来标记地点实体了,将会严重影响关系抽取的效果。
    特殊标记被拆分
  • 再比如,对于一些不在vocab.txt中的emoji, 分词器会将其识别为[UNK]。一般情况下没有问题,但是假如我们需要对社交媒体发言中的Emoji进行分析,就不能忽视不同Emoji之间的区别,这时将他们都识别为[UNK]是不合理的。
    Emoji未识别
    因此,我们需要探索一种方法,让BERT的分词器可以识别不在词典vocab.txt中的词汇,避免将其识别为[UNK]

方案1. 替换vocab.txt ★★☆☆☆

经过观察我们发现,vocab.txt的前面几行是[unusedx]。顾名思义,这种字符是没有用的,只是用来占位置的,他们在Bert Embedding层的权重是随机初始化的。那么,我们将[unused]替换为词典中没有的特殊字符,就可以让分词器识别出自定义的特殊字符了,这些特殊字符的初始权重也沿用了对应位置[unused]符号的权重,即也是随机初始化的。

根据这篇博客的内容Bert预留[unused*],直接将我们需要增加的token替换vocab.txt中原来的[unused]的对应行即可。如图所示,我们将[unused]替换为原本词典中不存在的几个表情符和特殊汉字。

vocab.txt的前几行 替换前-替换后
  • 替换后的分词情况
    我们发现,替换后,已经可以识别出某些emoji。但是,对于两个emoji连续出现的情况,还是无能为力。例如,下图两个🙏的emoji,就识别为[UNK]。说明这种方法是有一定缺陷的。
    该表词表

2. 增加special_token ★★☆☆☆

在某论坛上出现这样一个提问,Special tokens not tokenized properly #12168How to use my own additional vocabulary dictionary? #396和我们的诉求比较一致,下面给了一些讨论,大家有兴趣可以看看。总之结论跟huggingface官方论坛给出的关于add_token的方法比较类似,即用special token的方法,下面直接贴出:

# Let's see how to increase the vocabulary of Bert model and tokenizer
tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased")
model = BertModel.from_pretrained("bert-base-uncased")

num_added_toks = tokenizer.add_tokens(["new_tok1", "my_new-tok2"])
print("We have added", num_added_toks, "tokens")
# Notice: resize_token_embeddings expect to receive the full size of the new vocabulary, i.e., the length of the tokenizer.
model.resize_token_embeddings(len(tokenizer))

感兴趣的可以运行一下,这里直接说结论

  1. ✔这种方法可以识别出句子中的特殊token
  2. ✖这种方法会增加词表大小
  3. ✖因为改了词表大小,所以需要重置模型权重,如上面代码最后一行所示。
    由于重置模型权重不能保证原单词的权重中不变,新增单词的权重随机初始化,因此这种方法实际操作中不推荐

3. 推荐方法★★★★★

最好的方法当然是两者的结合

  1. 在vocab.txt中用新增字符替换掉对应行的[unused*]
  2. 在tokenizer中增加special token,实现方法如下图所示:
设置spedial_token

这样就可以实现如下诉求:

  1. 不改变词表大小
  2. 可以识别出特殊token
  3. 不用resize模型的预训练权重,之前的token权重可以保留,新增的token权重随机初始化。

参考资料

  1. Bert预留[unused*],链接:https://zhuanlan.zhihu.com/p/378774885
  2. huggingface的add_token函数,链接:https://huggingface.co/docs/transformers/internal/tokenization_utils#transformers.SpecialTokensMixin.add_tokens

相关文章

  • Bert如何使用预留的[unused*]

    背景 在使用Bert进行文本分析的过程中,我们需要用BERT自带的分词器(Tokenizer)来对文本序列进行分词...

  • Bert使用随笔

    Bert使用 使用Bert模型 其中bert_config是BertConfig类,bert内部是从json配置文...

  • Bert PyTorch 实现

    本文主要介绍如何使用PyTroch复现BERT。在此之前可以先阅读文章BERT详解(附带ELMo、GPT 介绍[h...

  • BERT使用心得经验分享

    使用Bert有一段时间了,在项目中确实也能带来提升,这里总结下bert的使用心得。 1,资源的使用 Bert在训练...

  • tensorflow.python.framework.erro

    使用Bert生成句向量,使用github上的bert-utils项目使用方式为 报以下信息错误: 看到github...

  • BERT微调模型

    使用BERT和Pytorch构建BERT微调模型,当然这里使用Pytorch的原因是用来比赛是比较方便的。 部分代...

  • bert的使用

    1.预测词很容易实现,预测定理性的词语效果比较好,预测句子中间的词语效果比较好。当预测其他领域的语句和句子末尾的词...

  • 知识点

    在objc中标记一个对象为被使用到使用 #program unused(参数名称)

  • 使用BERT进行fine-tuning

    Github上BERT的README里面已经给出了相当详细的使用说明,GOOGLE BERT地址。Fine-tun...

  • (九)再谈embedding——bert详解(实战)下

    前面两篇分别梳理了下BERT的原理和BERT的训练,接着前面的内容,梳理下BERT是如何在下游任务上运用的。 ...

网友评论

      本文标题:Bert如何使用预留的[unused*]

      本文链接:https://www.haomeiwen.com/subject/svvvdrtx.html