背景
在使用其他组织或个人发布的RoBERTa预训练模型时,一般除了模型文件之外还会有merges.txt
和vocab.json
。相比于BERT只需要一个vocab.txt
,为何RoBRETa需要2个?作用是什么?
PS:这里使用的是huggingface/transformers 下的 RoBRTa-base版模型。
说明
Bert采用的是字符级别的BPE编码,直接生成词表文件。Roberta采用的是**byte level的BPE(BBPE)**编码,预训练结果中的merges.txt
中存储了BBPE过程中merge得到的所有token,可以简单理解成就是字典。vocab.json
则是一个字典中基本单元到索引的映射。转换的过程是,根据merges.txt
将输入的文本tokenize化,再根据vocab.json
中的字典映射到对应的索id。
其中merges.txt
存放的是训练tokenizer阶段所得到的合并词表结果。看下merges.txt
的前6行信息:
#version: 0.2
Ġ t
Ġ a
h e
i n
r e
第2行的Ġ t
表示BPE合并词典的过程,第一轮迭代中最高频的字符是t
,且在该t
字符前面是空格,这里的Ġ
表示空格。换句话说,在第一轮迭代中,最高频的是单词首字符的t
,而不是其他位置的t
。这里的Ġ
表示空格,其背后含义是单词的起始,用以区分边界。进一步查看vocab.json
中的内容,可以看出"Ġt": 326
,即Ġt
的索引id是326。另外,由于是该文件中的每一行都是通过合并而成,所以在一行中保留了空格,以明示2个合并源。
比如对文本:"What's up with the tokenizer? t asks"
进行tokenization,结果如下:
tokenizer.tokenize: ['What', "'s", 'Ġup', 'Ġwith', 'Ġthe', 'Ġtoken', 'izer', '?', 'Ġt', 'Ġasks']
convert_tokens_to_ids: [2264, 18, 62, 19, 5, 19233, 6315, 116, 326, 6990]
可以看出,字符t
对应的tokenize结果是Ġt
,Ġt
对应的id是326。这与预期符合。
再看下merges.txt
中的h e
这一行。这说明,BPE第2轮迭代中h
和e
是最高频的,所以将2者合并。需要特别注意的是:这里的h
前面没有空格,这说明这里的h
不是一个单词的开头,也就不存在空格。换句话说,这里的h
存在于某些单词中间位置。进一步在vocab.json
中查找he
所对应的索引id为:"he": 700
。
当输入文本为:What's up with the tokenizer? he asks lhe question
时(PS:这里为了构建’he’的编码,杜撰了lhe
这个单词),tokenization结果如下:
tokenizer.tokenize: ['What', "'s", 'Ġup', 'Ġwith', 'Ġthe', 'Ġtoken', 'izer', '?', 'Ġhe', 'Ġasks', 'Ġl', 'he', 'Ġquestion']
convert_tokens_to_ids: [2264, 18, 62, 19, 5, 19233, 6315, 116, 37, 6990, 784, 700, 864]
可以看出,将lhe
这个单词分割成'Ġl'
和'he'
2部分,其中he
在词典中对应的索引id为700。