Byte-Pair Encoding for Tokenization
应用场景
- 自然语言处理
- 针对(尤其是英文)corpus建立vocab
- 将语素等subwords作为token
- 可能存在很多前后缀组合产生的unkown words
算法流程
参见《Speech and Language Processing》第三版.
P20 Figure2.13
笨拙的代码实现
"""
每一轮合并2个vocab中的token
@:return new vocab
@:param origin corpus, origin vocab, 合并的轮数
"""
def byte_pair_encoding(ori_corpus,ori_vocab,merge_k):
corpus = open(ori_corpus,'r')
vocab = open(ori_vocab,'r')
vc = vocab.readline().strip().split(', ')
ori_cs=[]
for line in corpus.readlines():
splits = line.strip().split(' ')
ori_cs.append([int(splits[0]),splits[1].split(' ')])
if splits[1] not in vc:
vc.append(splits[1].replace(" ",""))
for i in range(merge_k):
vc = nearest(ori_cs,vc)
return vc
"""
正反合并,找频数最大的
"""
def nearest(corpus,vocab):
pairs = {}
new_vocab = vocab
print(vocab)
for i in range(len(corpus)):
for j in range(i+1,len(corpus)):
pt = 0
toi = corpus[i][1][pt]
toj = corpus[j][1][pt]
while toi == toj:
if toi not in vocab:
if toi not in pairs.keys():
pairs[toi] = corpus[i][0] + corpus[j][0]
else:
pairs[toi] += corpus[j][0]
break
else:
pt += 1
if pt == len(corpus[i][1]) or pt == len(corpus[j][1]):
break
toi += corpus[i][1][pt]
toj += corpus[j][1][pt]
## 反向
for i in range(len(corpus)):
for j in range(i+1,len(corpus)):
pt1 = len(corpus[i][1])-1
pt2 = len(corpus[j][1])-1
toi = corpus[i][1][pt1]
toj = corpus[j][1][pt2]
while toi == toj:
if toi not in vocab:
if toi not in pairs.keys():
pairs[toi] = corpus[i][0] + corpus[j][0]
else:
pairs[toi] += corpus[j][0]
break
else:
pt1 -= 1
pt2 -= 1
if pt1 == 0 or pt2 == 0:
break
toi = corpus[i][1][pt1] + toi
toj = corpus[j][1][pt2] + toj
pairs = sorted(pairs.items(),key=lambda d:d[1],reverse=True)
print(pairs)
new_vocab.append(pairs[0][0])
return new_vocab
if __name__ == '__main__':
vocab = byte_pair_encoding('ori_corpus.txt','ori_vocab.txt',7)
print(vocab)
算法的效果
一旦学到了词汇表:
- 首先我们把每个测试句子的词分割成字符
- 然后我们会应用第一条规则:将测试语料库中的 ‘e r’ 替换为 ‘er’,
- 然后应用 第二条规则:将测试语料库中的 ‘er _’ 替换为 ‘er_’,以此类推。
- 到最后,如果测试语料库中包含 'n e w e r _'这个词,它将被分为一个完整的词。
- 但是,一个未登录词(unkown words),如 ‘lower_’,将被分成两个 token:‘low’ ‘er_’。
附: 语料库和词表格式
ori_corpus.txt
5 l o w _
2 l o w e s t _
6 n e w e r _
3 w i d e r _
2 n e w _
ori_vocab.txt
_, d, e, i, l, n, o, r, s, t, w