词元化是数据处理的最重要的一个步骤,旨在将原始文本分割成可识别和建模的词元序列。对于传统的自然语言处理研究,主要使用基于词汇的分词方法,但这种方法可能存在由分词结果差异而导致后续训练的问题,以及对于相同的输入,产生不同的输出,导致生成包含海量的低频词的庞大词表,还可能存在OOV(未登录词)等问题,因此,一些语言模型开始采用字符作为最小的分词单位。最近,子词分词器被广泛应用于基于Transformer的语言模型中,包括三种最为常见的方法:BPE分词、Wordpiece分词以及Unigram分词三种方法。以下将详细介绍三种代表性的词元化方法。
一、BPE分词
BPE算法从一组基本符号开始,迭代的寻找两个相邻词元,并把它们替换成为新的词元,这一过程称为合并。合并的选择标准是计算两个连续词元的共现频率,简单来说,也就是每次迭代中,最频繁出现在一起的一对词元会被选择合并。合并过程将一直持续到达到预定义的词表的大小。BPE算法代码示例如下:
import re
from collections import Counter
def extract_frequencies(sequence):
"""
给定一个字符串,计算字符串中的单词出现的频率,并返回词表(一个词到频率的映射字典)。
"""
token_counter = Counter()
for item in sequence:
tokens = ' '.join(list(item)) + ' </w>'
token_counter[tokens] += 1
return token_counter
def frequency_of_pairs(frequencies):
"""
给定一个词频字典,返回一个从字符对到频率的映射字典。
"""
pairs_count = Counter()
for token, count in frequencies.items():
chars = token.split()
for i in range(len(chars) - 1):
pair = (chars[i], chars[i+1])
pairs_count[pair] += count
return pairs_count
def merge_vocab(merge_pair, vocab):
"""
给定一对相邻词元和一个词频字典,将相邻词元合并为新的词元,并返回新的词表。
"""
re_pattern = re.escape(' '.join(merge_pair))
pattern = re.compile(r'(?<!\S)' + re_pattern + r'(?!\S)')
updated_tokens = {pattern.sub(''.join(merge_pair), token): freq for token, freq in vocab.items()}
return updated_tokens
def encode_with_bpe(texts, iterations):
"""
给定待分词的数据以及最大合并次数,返回合并后的词表。
"""
vocab_map = extract_frequencies(texts)
for _ in range(iterations):
pair_freqs = frequency_of_pairs(vocab_map)
if not pair_freqs:
break
most_common_pair = pair_freqs.most_common(1)[0][0]
vocab_map = merge_vocab(most_common_pair, vocab_map)
return vocab_map
num_merges = 1000
bpe_pairs = encode_with_bpe(data, num_merges)
字节级别的BPE是对原BPE的一种优化方法。它不使用字符作为最基本的符号,使用字节作为最基本的合并操作符号,因此,实现了更细粒度的分割,解决了未登录词的问题。采用这种词元化方法的代表性语言模型有GPT-2、BART、以及LLAMA。具体来说,如果将所有 Unicode 字符都视为基本字符,那么包含所有可能基本字符的基本词表会非常庞大(例如将中文的每个汉字当作一个基本字符)。而将字节作为基 本词表可以设置基本词库的大小为 256,同时确保每个基本字符都包含在词汇中。 例如,GPT-2 的词表大小为 50,257 ,包括 256 个字节的基本词元、一个特殊的文末词元以及通过 50,000 次合并学习到的词元。
二、WordPiece分词
WordPiece 分词和 BPE 分词的想法非常相似,都 是通过迭代合并连续的词元,但是合并的选择标准略有不同。在合并前,WordPiece分词算法会首先训练一个语言模型,并用这个语言模型对所有可能的词元对进行 评分。然后,在每次合并时,它都会选择使得训练数据的似然性增加最多的词元对。
三、Unigram分词
与前两种分词方式不同,Unigram分词方式是从语料库中的一组足够大的字符串或词元初始集合开始,迭代的删除其中的词元,直到达到预期的词表大小位置。它假设从当前词表删除某个词元,并计算训练语料的似然增加情况,以此来作为选择标准。这个步骤是通过一个训练好的一元语言模型来进行的。采用这种分词方法的代表性模型包括 T5 和 mBART