Tokenize与新词发现

引子

问题1: 为什么大语言模型做不好反转单词, 以及数数类的简单任务?

(gpt-35-turbo测试结果)

> Take the letters in lollipop and reverse them
The reversed letters of "lollipop" are "pilpolol".
> How many characters are there in word abacadabra?
There are 11 characters in the word "abacadabra"
> How many characters are there in this sentence?
There are 35 characters in "How many characters are there in this sentence?" including spaces.
> How many words are there in this sentence?
There are nine words in this sentence.
> How many spaces are there in this sentence?
There are six spaces in this sentence.
> How many 'a' are there in this sentence?
There are 3 occurrences of the letter 'a' in the sentence.

问题2: 语言模型都按照问答文本的token计费, 如何测算?

https://platform.openai.com/tokenizer

English: 1 token ~ 3/4 word OR 4 characters

tokenization

目的

变换过程 (embedding layer): 字表宽x文本长 -> 词表宽x编码长

考量点:

这里先针对英文展开讨论

word-level tokenization / 空格+符号分词, 生成词表过大

过大词表问题: 模型输入内存空间太大, 计算复杂度上升, 词于词之间的关联表征信息丢失了, 如英文里面单复数, 时态等

character-level tokenization / 词表=字表, 文本长度即编码长度

过小词表问题: 对模型来说学习太困难了, 自己独立再学习总结出来组成词的概念. 空格, 符号等本身就是对于人类阅读时的注意力标号信息.

英文词有时态/词根等领域知识 (语法), 可以提前抽取出来, 如-ization本身表明的名词化, -ed / -ing表明时态, -s表明单复数, -ly表明状态等. 这些单独抽出来作为词元, 能够忠实保留元信息.

subword tokenization / 折中办法: 对于词进一步分割以减少词表大小:

tokenization训练

BPE (Byte Pair Encoding) for GPT

例子: “cat hat bat” -> {cat: 1, hat: 1, bat: 1} -> {c: 1, h: 1, b: 1, at: 3}

词表大小 = 字表大小+合并次数

DEMO TIME

GPT词表观察:

WordPiece for BERT

流程同BPE, 但是合并标准不是看频次, 而是看共现概率

argmax(freq(ab)) VS argmax(freq(ab)/freq(a)*freq(b))

由于编码时对空格会预处理掉, 因此词表里面需要区分后缀子词 ing/##ing

问题:

  1. 上面的”因此”如何理解?
  2. BERT编码能还原回原文本么?
  3. 如何看待这里BERT和GPT的编码选择区别?
    • 一个是encoder-only, 一个是encoder-decoder模式, 自然需要考虑可还原性

最优tokenization?

上述是两阶段的贪心算法, 先长序列切成长度可控的短序列, 然后每次取一个最大的.

在给定词表大小限定条件下, 最优的基于词表的tokenization算法? 对于每个样本的所有切法, 找到导致整体编码长度最短词表.

和通用压缩问题区别: 压缩还需要考虑每个token编码后长度, 这里不用考虑, 等长对待.

tokenization推断及优化

推断目标: 对于所有词表切法中, 返回最短的 (DP算法, 同有权重词表分词, 返回权重和最大的)

推断的加速手段? 用rust/上并行/针对编码词表规则的特化/牺牲一点结果最优性以优化速度

最短是否等价于扫一遍当前位置找最长的 (longest-match-first strategy)? 否, 但是这种速度最快, 实际应用时值得考虑, 如前向后向两次取较短者, 先切割然后每段单独细分, 等.

正对BPE词表生成方式的特化: 对文本跑一遍合并过程更简单, 前提需要求合并路径词都得存下不能丢弃

https://github.com/openai/tiktoken/blob/main/tiktoken/_educational.py

针对一定会切开的地方, 如空格符号等, 提前分割后, 并行编码.

值得玩味的点:

解码过程, 相对就很简单: 词表一个个找出来拼接即可

不做tokenization?

tokenization编码/解码(encode/decode)环节相当于人类和模型交互的翻译. 对于LLM非常基础重要, tokenization方式相当于提前纳入了人为假设/偏见, 严重限制了LLM的学习能力, 值得各方面针对这个角度的研究.

文本本身有非常高的信号冗余, tokenization被认为是合理的. 文本的tokenization是否应该和人类感知文本对齐? 如何理解人类是接受文本信号的?

图像/音频的tokenization? 图像的tokenization, 由于2维关系, 需要分割打码加上位置信息后传入模型. 音频的tokenization, 也是需要先离散化, 这个离散化过程是否限制了信号的表达?

苦涩的教训: 应尽量减少人为干预

完全基于字节(256)或者位(2)信号训练? 模型自行学习编码器/解码器

主要还是不编码的数据及计算膨胀问题, 算力足够, 相信会有更简单的编码方案的模型.

中文tokenization的粒度问题

字表太大, 决策问题

是否应该扩充词表以减少编码长度?

中文已经足够简练, 博大精深, 就不要再成词编码?

国产模型貌似还是普遍会对中文进行提前分词处理

https://www.volcengine.com/docs/82379/1099320

传统文本特征抽取手段回顾

要学习的特征维度低

中文分词训练回顾

tokenization: 非监督训练, 是确定性的算法过程

分词: 有标号文本的监督训练

难点: 样本质量及质量难题

中文新词发现

非监督分词=tokenization

新词发现: 已有词表, 找出文本中不在词表的有意义词 (OOV)

问题等价, 唯一区别在于是否有先验词表

基于词表/字表逐步进一步合并, 拓充词表

思路其实同上述tokenization训练, 不断合并

  1. 对文本n-gram切, 然后基于词频, 或者进一步TF-IDF等卡阈值提取, 如在词表忽略, 容易提出一些不知所谓的词
  2. 算共现概率 (AKA 邻字信息熵) 卡阈值提取

DEMO TIME

总结

tokenization是为了模型理解, 结果对模型输入负责; 分词一般是为了搜索场景, 结果对人(这个模型)容易理解负责. tokenization为了压缩, 目的输出最短的; 分词是概率上猜一个可能性最高的. 切出来的token对人类来说不带有意义, 分词切出来的结果对人类可以理解有意义的.

人类时很容易按照目的重新自适应tokenize, 比如”How many characters are there in word abacadabra”问题, 重新把关注点从词义细化到数字符. 对于模型而言, 最原始的表征已经丢掉了, 只能靠模型不断学记忆下来.

模型如何做到正确的反转单词? 需理解语义并且记住每个token的对应反转token, 这是很难非监督方式习得的, 除非定向生成一大波训练样本.

Reference

HOME