当前位置:   article > 正文

深度学习系列28:BPE分词模型_bpe 模型

bpe 模型

这个是当前英文分词的标准方法了。

1. 简介

在NLP模型中,输入通常是一个句子,例如I went to New York last week.。传统做法:空格分隔,例如[‘i’, ‘went’, ‘to’, ‘New’, ‘York’, ‘last’, ‘week’]。
BPE算法通过训练,能够把[‘loved’, ‘loving’, ‘loves’]拆分成[“lov”, “ed”, “ing”, “es”]几个部分,这样可以把词的本身的意思和时态分开,有效的减少了此表的数量。算法流程如下:

1)设定最大subwords个数
2)将所有单词拆分为单个字符,并且在最后添加一个停止符,同时标记处该单词出现的次数。例如,"low"这个单词出现了5次,那么它将会被处理为{‘l o w ’: 5}
3)统计每一个连续字节对的出现频率,选择最高频者合成新的subword
4)重复第3步直到达到第1步设定的subwords词表大小或下一个最高频的字节对出现频率为1

2. 例子

{‘l o w ’: 5, ‘l o w e r ’: 2, ‘n e w e s t ’: 6, ‘w i d e s t ’: 3}

出现最频繁的字节对是e和s,共出现了 6+3 = 9次,因此将它们合并

{‘l o w ’: 5, ‘l o w e r ’: 2, ‘n e w es t ’: 6, ‘w i d es t ’: 3}

出现最频繁的字节对是es和t,共出现了6+3=9次,所以将它们合并

{‘l o w ’: 5, ‘l o w e r ’: 2, ‘n e w est ’: 6, ‘w i d est ’: 3}

出现最频繁的字节对是est和,共出现了6+3=9次,因此将它们合并

{‘l o w ’: 5, ‘l o w e r ’: 2, ‘n e w est’: 6, ‘w i d est’: 3}

出现最频繁的字节对是l和o,共出现了5+2 = 7 次,因此将它们合并

{‘lo w ’: 5, ‘lo w e r ’: 2, ‘n e w est’: 6, ‘w i d est’: 3}

3. 简单的实现

import re, collections

# 生成初始词汇字典
def get_vocab(filename):
    vocab = collections.defaultdict(int)
    with open(filename, 'r', encoding='utf-8') as fhand:
        for line in fhand:
            words = line.strip().split()
            for word in words:
                vocab[' '.join(list(word)) + ' </w>'] += 1
    return vocab

# 获取所有字节对的频率(找出最大的进行合并)
def get_stats(vocab):
    pairs = collections.defaultdict(int)
    for word, freq in vocab.items():
        symbols = word.split()
        for i in range(len(symbols)-1):
            pairs[symbols[i],symbols[i+1]] += freq
    return pairs

def merge_vocab(pair, v_in):
    v_out = {}
    bigram = re.escape(' '.join(pair))
    p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')
    for word in v_in:
        w_out = p.sub(''.join(pair), word)
        v_out[w_out] = v_in[word]
    return v_out

def get_tokens(vocab):
    tokens = collections.defaultdict(int)
    for word, freq in vocab.items():
        word_tokens = word.split()
        for token in word_tokens:
            tokens[token] += freq
    return tokens

vocab = {'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3}

# Get free book from Gutenberg
# wget http://www.gutenberg.org/cache/epub/16457/pg16457.txt
# vocab = get_vocab('pg16457.txt')

print('==========')
print('Tokens Before BPE')
tokens = get_tokens(vocab)
print('Tokens: {}'.format(tokens))
print('Number of tokens: {}'.format(len(tokens)))
print('==========')

num_merges = 5
for i in range(num_merges):
    pairs = get_stats(vocab)
    if not pairs:
        break
    best = max(pairs, key=pairs.get)
    vocab = merge_vocab(best, vocab)
    print('Iter: {}'.format(i))
    print('Best pair: {}'.format(best))
    tokens = get_tokens(vocab)
    print('Tokens: {}'.format(tokens))
    print('Number of tokens: {}'.format(len(tokens)))
    print('==========')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

4. 编码和解码

在之前的算法中,我们已经得到了 subword 的词表,对该词表按照字符个数由多到少排序。编码时,对于每个单词,遍历排好序的子词词表寻找是否有 token 是当前单词的子字符串,如果有,则该 token 是表示单词的 tokens 之一

我们从最长的token迭代到最短的token,尝试将每个单词中的子字符串替换为token。最终,我们将迭代所有的tokens,并将所有子字符串替换为tokens。 如果仍然有子字符串没被替换但所有token都已迭代完毕,则将剩余的子词替换为特殊token,如

例如

# 给定单词序列
["the</w>", "highest</w>", "mountain</w>"]

# 排好序的subword表
# 长度 6         5           4        4         4       4          2
["errrr</w>", "tain</w>", "moun", "est</w>", "high", "the</w>", "a</w>"]

# 迭代结果
"the</w>" -> ["the</w>"]
"highest</w>" -> ["high", "est</w>"]
"mountain</w>" -> ["moun", "tain</w>"]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

解码
将所有的tokens拼在一起即可,例如

# 编码序列
["the</w>", "high", "est</w>", "moun", "tain</w>"]

# 解码序列
"the</w> highest</w> mountain</w>"
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/615632
推荐阅读
相关标签
  

闽ICP备14008679号