从Huggingface引用很棒的Transformers库的documentation,我遇到了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%,我也能够复制类似的行为。
我的问题
add_tokens
函数而不是整个单词,它们期望使用掩码标记,例如:'##ah'
,'##red'
,'##ik'
,'##si
'等。 ?如果是,是否有生成此类屏蔽令牌的程序?任何帮助将不胜感激。
谢谢。
答案 0 :(得分:1)
如果将标记添加到标记生成器,则确实会使标记生成器以不同的方式标记文本标记,但这不是BERT训练的标记标记,因此基本上是在输入中添加噪音。嵌入一词没有经过训练,网络的其余部分从未在上下文中看到它们。您将需要大量数据来教BERT处理新添加的单词。
还有一些方法可以计算单个单词的嵌入,这样不会像this paper中那样伤害BERT,但是看起来很复杂,应该不会有任何区别。
BERT使用基于单词的词汇,因此单词是否作为单个标记出现在词汇中或拆分成多个单词并不重要。该模型可能在预训练期间看到了拆分词,并且会知道该怎么做。
对于带有##
前缀的标记,这些标记只能作为另一个单词的后缀。例如,walrus
被分成['wal', '##rus']
,而您需要两个单词都在词汇表中,而不是##wal
或rus
。