Bert是NLP常用的特征提取模型,但其预训练的时候通常规定了词语字典,例如中文Bert模型里缺少英文单词,英文Bert里缺少中文字词。这里归纳如何使用预训练Bert模型处理其训练数据中不包含的词汇。
Bert的输入
众所周知Bert的输入是input_ids,也就是每个分词对应在词汇字典里的id,通常规定在vocab.txt里面。也有任务是自己规定字典,例如中文tts模型里finetune的bert就是一个包含拼音音素的字典。
因此,添加自定义词汇的第一步就是向字典里添加自己的词汇及其id,视情况直接在vocab.txt或在自定义字典里添加。
更改Embeddig层的尺寸
虽然Bert的输入只包含字典中的部分词汇,但实际上它们会在Embedding层被映射为一个one_hot向量传入到Bert中,这个one_hot向量的长度就是字典中的词汇数量。
这是一个Embedding层的声明例子:
self.embbedding = torch.nn.Embedding(n_vocab, hidden_channels)
因此,当上一步向字典里添加新词汇时,需要将Embedding层的输入更改为新的词汇数量。
初始化Embedding层参数
更改Embedding层尺寸会导致加载不上预训练的Bert模型参数,这里可以只加载模型其他部分,然后重新初始化Ebedding层的参数。
例如,当网络中的层名为Embedding时,用一个均匀分布初始化它,其他层依旧加载预训练参数。
for k, v in model.state_dict.items():
if k == 'embedding.weight':
new_state_dict[k] = torch.nn.Parameter(torch.rand(new_n_vocab,hidden_channels))
continue
new_state_dict[k] = saved_state_dict[k]
model.load_state_dict(new_state_dict)