3

参考Huggingface 的 Transformers 库的文档,我遇到了这些函数add_tokens

tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
num_added_toks = tokenizer.add_tokens(['new_tok1', 'my_new-tok2'])
model.resize_token_embeddings(len(tokenizer))

我通过在默认词汇表中添加以前不存在的单词来尝试上述方法。但是,在其他所有条件保持不变的情况下,我注意到使用此更新后的微调分类器的准确性有所下降tokenizer。即使只添加了 10% 的先前缺失的单词,我也能够复制类似的行为。

我的问题

  1. 我错过了什么吗?
  2. 函数是否需要屏蔽标记,而不是整个单词,例如add_tokens:、、、、 '##ah''等?如果是,是否有生成此类掩码令牌的程序?'##red''##ik''##si

任何帮助,将不胜感激。

提前致谢。

4

1 回答 1

3

如果您将标记添加到标记器,您确实使标记器以不同的方式标记文本,但这不是 BERT 训练时使用的标记化,因此您基本上是在向输入添加噪声。词嵌入没有经过训练,网络的其余部分从未在上下文中看到它们。你需要大量数据来教 BERT 处理新添加的单词。

还有一些方法可以计算单个词嵌入,这样它就不会像本文中那样伤害 BERT,但它看起来相当复杂,应该没有任何区别。

BERT 使用基于单词片段的词汇表,因此单词是作为单个标记出现在词汇表中还是被拆分为多个单词片段并不重要。该模型可能在预训练期间看到了拆分词,并且会知道如何处理它。

关于##-prefixed 标记,这些标记只能作为另一个单词的后缀添加。例如,walrus被拆分为['wal', '##rus']并且您需要两个词块都在词汇表中,但不是##walor rus

于 2020-02-05T10:32:28.317 回答