为什么要分词
分词是将输入的文本分割成一个个相对完整且独立的“词元”(token),以便后续任务(例如学习词嵌入embedding或作为高级模型的输入)能够更高效地处理文本数据。简单来说,分词是为了让机器更好地理解和处理语言,就像我们把句子拆分成单词一样,让机器能够逐个理解和分析。
分词的三种粒度
-
词粒度(word)
英文中,单词之间有空格自然分隔,而中文则可以通过工具(如jieba分词)来实现。 参考jieba分词详解
优点:保留了词的边界和完整含义。
缺点:- 词表可能非常庞大(长尾效应),因为存在大量稀有词。这不仅增加了存储和训练成本,还可能导致模型难以学习这些稀有词。
- 存在OOV(Out of Vocabulary,词汇表外)问题,即对于词表中不存在的词,模型无法处理。
- 无法处理单词的形态变化和词缀关系。例如,同一个词的不同形态(如“run”和“running”)语义相近,但会被当作不同的单词处理,这不仅增加了训练成本,还无法捕捉它们之间的关系。
-
字符粒度(char)
将文本拆分成单个字符(如英文字母或汉字)。
优点:词表非常小,例如26个英文字母可以组合出所有英文单词,5000多个常用汉字也能覆盖大部分中文词汇。
缺点:- 无法承载丰富的语义。例如,“apple”这个词拆分成字符后,失去了整体含义。
- 序列长度会显著增加,每个字母代表一个向量,从而增加计算成本。
-
子词粒度(subword)
子词粒度介于字符和单词之间,其核心思想是:常用词保持完整,而生僻词则拆分成子词,以共享token空间,从而压缩词表大小。 例如,对于一个生僻词“unbelievable”,它可以被拆分成“un-”、“believ-”和“-able”这样的子词,这些子词在词表中出现的频率可能更高,从而避免了整个单词因未出现在词表中而无法处理的情况。
假设我们有一个简单的词汇表,包含以下单词:
常用词:["happy", "unhappy", "play", "playing"]
生僻词:["unbelievable", "disappointment"]
如果使用单词粒度分词,词表会包含所有单词,但遇到未出现在词表中的词(如“unbelievable”)时,就会出现OOV问题。
如果使用子词粒度分词,我们可以将词汇表中的单词拆分成子词:
"happy" → ["hap", "py"]
"unhappy" → ["un", "hap", "py"]
"play" → ["play"]
"playing" → ["play", "ing"]
"unbelievable" → ["un", "believ", "able"]
"disappointment" → ["dis", "appoint", "ment"]
通过这种方式,即使“unbelievable”不在原始词表中,我们也可以通过子词["un", "believ", "able"]来表示它,从而解决了OOV问题。
优点:
- 能较好地平衡词表大小和语义表达能力。例如,OOV问题可以通过子词组合解决。
目前有三种主流的子词分词算法,它们的具体实现方式略有不同,但核心目标都是通过子词来平衡词表大小和语义表达能力:
BPE(Byte Pair Encoding)
BPE通过统计字符对的频率,逐步合并最频繁的字符对,从而生成子词。例如,对于单词"happy"和"unhappy",BPE可能会先合并"ha"和"ap",最终生成子词[“hap”, “py”]和[“un”, “hap”, “py”]。
WordPiece
WordPiece与BPE类似,但在选择合并的字符对时,它会考虑生成子词的概率。例如,如果"un"和"believ"经常一起出现,WordPiece会优先合并它们,从而生成更符合语言习惯的子词。
Unigram Language Model
Unigram模型通过训练一个语言模型来预测子词的概率分布。它会根据子词在语料中的出现频率和上下文关系,动态生成子词。这种方法更灵活,能够更好地捕捉语言的复杂性。
分词的实例
Tiktokenizer(https://tiktokenizer.vercel.app/)是一个可以可视化分词结果的网站。它展示了不同分词方法的分词效果,使用GPT-2和GPT-4o的分词器对中文、英文、数字和代码进行分词。可以看到,GPT-4o的分词器词汇表更大,相同内容的token总数更少,每个token包含的语义也更连贯。
提升分词效果的意义
分词是大语言模型(LLM)的核心问题之一,它直接影响模型对输入文本的理解和处理能力。分词的目的是将文本分割成一个个“词元”(token),以便模型能够高效地学习和生成语言。然而,分词方式的选择和实现会引入一系列问题,这些问题可能导致模型在某些任务上表现不佳,甚至出现看似奇怪的现象。
例如,分词方式可能导致模型无法正确理解单词的完整结构,从而影响拼写能力;分词后,模型可能无法直接处理原始字符串,导致无法完成简单的字符串操作(如反转字符串)。此外,分词方式如果不适合某些语言的结构(如日语),模型在这些语言上的表现就会较差。类似地,分词可能导致模型难以理解数字和运算符之间的关系,从而不擅长处理简单算术问题。
在处理编程语言时,分词方式也可能无法很好地适应代码的结构,例如GPT-2在处理Python代码时会遇到很多麻烦。此外,分词器对特殊标记(如<|endoftext|>
)的处理可能导致模型在遇到这些标记时突然停止生成文本。分词器对空格的处理方式也可能导致一些奇怪的警告,例如尾部空格问题。对于复合词(如“SolidGoldMagikarp”),分词方式可能无法正确理解其结构,从而导致生成错误。
此外,分词器对不同格式(如YAML和JSON)的处理方式不同,可能导致模型在处理这些格式时表现不一致。最重要的是,分词方式限制了模型对语言的完整理解,使得大语言模型无法真正实现端到端的语言建模。
总之,分词问题可能是许多困扰大语言模型用户的“痛苦根源”。这是因为分词方式不仅决定了模型如何理解输入文本,还影响了模型的生成能力和适应性。因此,优化分词策略和算法对于提升大语言模型的性能至关重要。