根据我的评论,我假设您使用预先训练的检查点,即使只是为了“避免 [学习] 新的标记器”。
此外,该解决方案适用于 PyTorch,它可能更适合此类更改。我还没有检查过 Tensorflow(在你的一个引用中提到过),所以不能保证它可以跨平台工作。
为了解决您的问题,让我们将其分为两个子问题:
- 将新标记添加到标记器中,并且
- 相应地重新调整模型的令牌嵌入矩阵的大小。
第一个实际上可以通过使用.add_tokens() 非常简单地实现。我引用了慢速分词器的实现(因为它是在 Python 中),但据我所知,这也适用于更快的基于 Rust 的分词器。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
# Will return an integer corresponding to the number of added tokens
# The input could also be a list of strings instead of a single string
num_new_tokens = tokenizer.add_tokens("dennlinger")
您可以通过查看编码的输入 id 来快速验证这是否有效:
print(tokenizer("This is dennlinger."))
# 'input_ids': [101, 2023, 2003, 30522, 1012, 102]
索引30522 现在与我的用户名对应的新令牌,所以我们可以检查第一部分。但是,如果我们查看.add_tokens() 的函数文档字符串,它也会说:
注意,当向词汇表添加新标记时,您应该确保还调整模型的标记嵌入矩阵的大小,使其嵌入矩阵与标记器匹配。
为此,请使用PreTrainedModel.resize_token_embeddings 方法。
看this particular function,描述有点混乱,但是我们可以得到一个正确调整大小的矩阵(新令牌的权重随机初始化),只需传递之前的模型大小,加上新令牌的数量:
from transformers import AutoModel
model = AutoModel.from_pretrained("distilbert-base-uncased")
model.resize_token_embeddings(model.config.vocab_size + num_new_tokens)
# Test that everything worked correctly
model(**tokenizer("This is dennlinger", return_tensors="pt"))
编辑:值得注意的是,.resize_token_embeddings() 还负责处理任何相关的权重;这意味着,如果您正在进行预训练,它还将调整语言建模头的大小(应该具有相同数量的标记),或修复可能受标记数量增加影响的绑定权重。