NLP(五十二)在BERT模型中添加自己的词汇
不论是Tensorflow版本或者PyTorch版本的NLP预训练模型,我们都会在模型文件中看到vocab.txt
文件,这个文件就是该预训练模型的词汇表。通常,模型本身都会自带词汇表文件,这是在模型预训练的时候训练得到的词汇表,具有代表性,一般不可随意更改。同时vocab.txt
文件中也保留了一定数量的未使用(unuserd)词汇,用于添加新词。
本文将介绍如何在BERT模型中添加自己的词汇,其它预训练模型原理相同。
我们将通过三个常见的模块来介绍,分别是keras-bert
,transformers
,tokenizer
。其中keras-bert
是Keras框架实现的模块,transformers
主要是PyTorch实现的模块,也可用于TensorFlow2.0版本以上,tokenizer
是一个专门用于切分词(tokenize)的模块。
通常,往预训练模型中添加新词有两种实现方式,如下:
- 直接在词汇表vocab.txt中替换[unused]
- 通过重构词汇矩阵来增加新词
keras-bert
在keras-bert
模块中,首先观察不添加新词时的切分词结果。我们以特殊标识jjj
为例,代码如下:
1 |
|
输出结果如下:
1 |
|
可以看到,如果直接按照原有模型词汇表,则不会将特殊标识jjj
作为整体切分,而是按照现有切分逻辑进行切分。
我们将模型词汇表文件中的[unused1]
替换成jjj
,则切分结果如下:
1 |
|
或者不修改vocab.txt
,在上述代码中将token_dict中将key[unused1]
替换成jjj
,比如:token_dict['jjj'] = token_dict.pop('[unused1]')
。
bert4keras
模块添加新词同理。
transformers
transformers
模块添加新词也是上述两种方式,在词汇表vocab.txt中替换[unused]这种方式不再赘述,介绍如何通过重构词汇矩阵来增加新词,代码如下:
1 |
|
输出结果结果如下:
1 |
|
需要注意的是,加载的模型需要略作调整,如下:
1 |
|
tokenizer
tokenizer
模块添加新词也是上述两种方式,在词汇表vocab.txt中替换[unused]这种方式不再赘述,介绍如何通过重构词汇矩阵来增加新词,代码如下:
1 |
|
输出结果如下:
1 |
|
问题探讨
上述方式对于一般的新词,均可起效。但对于另一类特殊的新词,比如<e>
,</e>
等,需要另加分析,我们以tokenizer
模块进行分析,如下:
1 |
|
我们在词汇表vocab.txt中替换[unused],但不会起效,输出结果如下:
1 |
|
但add_special_tokens
会起效,原因为<
,e
,>
和<e>
均存在于vocab.txt
,但前三者的优先级高于<e>
,而add_special_tokens
会起效,却会使得词汇表大小增大,从而需另外调整模型size。
但是,如果同时在词汇表vocab.txt中替换[unused],同时add_special_tokens
,则新增词会起效,同时词汇表大小不变。
总结
本文介绍如何在BERT模型中添加自己的词汇,其它预训练模型原理相同。同时,tokenizer
也是一个不错的切分词的模块,建议读者有空可以尝试~
欢迎关注我的知识星球“自然语言处理奇幻之旅”,笔者正在努力构建自己的技术社区。