GPT-2 Tokenizer 效率观察

标签: AI GPT GPT-2 Tokenizer | 发表时间:2023-03-27 23:46 | 作者:Solrex
出处:https://yangwenbo.com

对基于 Transformer 结构的 LLM (大语言模型)来说,模型的输入输出都是 Token(词元)。一段输入文本,首先要经过 Tokenizer(分词器)切分成 Token 再输入给模型。

不同的 Tokenizer 会把文本按不同的边界切分,那一段文本到底会被切成几个 Token 就体现了 Tokenizer 本身的效率,这本身也是信息论的讨论范畴。不过今天不做理论分析,也不介绍 Tokenizer 的训练算法,就看下 GPT-2 和 GPT-3 Tokenizer 的实际分词效率(GPT-2 和 GPT-3 使用的是同样的 Tokenizer)。

用 GPT-2 Tokenizer 编码一段中文

  from transformers import GPT2Tokenizer

tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
input_str = '不同的 Tokenizer 会把文本按不同的边界切分,那一段文本到底会被切成几个 Token 就体现了 Tokenizer 本身的效率,这本身也是信息论的讨论范畴。'
tokenids = tokenizer(input_str)['input_ids']
raw_tokens = tokenizer.convert_ids_to_tokens(tokenids)
token_strs = [tokenizer.convert_tokens_to_string([token]) for token in raw_tokens]
print(len(input_str), len(tokenids), tokenids, token_strs)
  82 121 [38834, 28938, 234, 21410, 29130, 7509, 220, 27670, 248, 162, 232, 232, 23877, 229, 17312, 105, 162, 234, 231, 38834, 28938, 234, 21410, 164, 122, 117, 45911, 234, 26344, 229, 26344, 228, 171, 120, 234, 165, 224, 96, 31660, 162, 106, 113, 23877, 229, 17312, 105, 26344, 108, 41753, 243, 27670, 248, 164, 95, 104, 26344, 229, 22755, 238, 49035, 254, 10310, 103, 29130, 10263, 108, 109, 19526, 241, 163, 236, 108, 12859, 228, 29130, 7509, 42164, 105, 164, 118, 104, 21410, 46763, 230, 163, 236, 229, 171, 120, 234, 32573, 247, 17312, 105, 164, 118, 104, 20046, 253, 42468, 46479, 94, 162, 223, 107, 164, 106, 118, 21410, 164, 106, 101, 164, 106, 118, 164, 234, 225, 45911, 112, 16764] ['不', '�', '�', '的', ' Token', 'izer', ' ', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '不', '�', '�', '的', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '一', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', ' Token', ' �', '�', '�', '�', '�', '�', '�', '�', '�', '�', ' Token', 'izer', ' �', '�', '�', '�', '�', '的', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '是', '�', '�', '�', '�', '�', '�', '�', '�', '的', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', '。']

输入的中英文夹杂的字符串长度为 82 个字符,其中有 6 个空格,23 个英文字符(3个单词),3个标点符号,50 个汉字字符。最终编码出来的 tokenids 长度是 121 个 Token,仔细检查可以看到,大部分汉字被编码成两个 Token,英文则是按照 subword 级别进行了编码。由此可见, GPT-2 Tokenizer 编码中文的效率是很低的

GPT-2 Tokenizer 词典中包含中文的 Token 数量

  import re
tokens = [tokenizer.convert_tokens_to_string([key]) for key in tokenizer.get_vocab()]
cn_tokens = [t for t in tokens if re.search(u'[\u4e00-\u9fff]', t)]
cn_tokens.sort(key=len, reverse=True)
print(len(tokens), len(cn_tokens), cn_tokens)
  50257 51 [' 裏覚醒', ' 裏�', '��士', '龍喚士', ' 裏�', '龍契士', '��極', ' 裏', '龍�', '�醒', '覚醒', 'の魔', '�士', '龍�', ' 神', '龍', '神', '士', '魔', '的', '人', '天', '王', '一', '大', '装', '田', '子', '戦', '生', '者', '不', '姫', '中', '上', '闘', '是', '女', '方', '作', '黒', '之', '使', '光', '代', '版', '三', '五', '武', '将', '機']

对 GPT-2 Tokenizer 词典中的 Token 进行分析,可以看到: 在数量为 50257 大小的词典中,只有 51 个 Token 包含常见的中文字符。上一节中出现的“是”、“的”、“不”也在其中,但是大家随便一想就能想到的,常见的“你”、“我”、“他”并不在内。这些数据印证了它对中文分词的效率低下。

GPT-2 Tokenizer 词典中包含英文的 Token 数量

  en_tokens = [t for t in tokens if re.search(u'[A-Za-z]', t)]
en_tokens.sort(key=len, reverse=True)
print(len(en_tokens), en_tokens[:10])
  46949 ['rawdownloadcloneembedreportprint', 'BuyableInstoreAndOnline', 'cloneembedreportprint', ' RandomRedditorWithNo', ' telecommunications', ' disproportionately', ' guiActiveUnfocused', 'channelAvailability', ' Telecommunications', ' externalToEVAOnly']

但是针对英文字符进行统计,可以看到 在数量为 50257 大小的词典中,有 46949 个 Token 包含 26 个英文字母。由于数量太多,这里仅输出了长度排前 10 的英文 Token。

从 Tokenizer 词典中不同语言字符的分布,我们可以验证 GPT-3 论文 “ Language Models are Few-Shot Learners” 中提到的这句话:

... This could be a weakness due to reusing the byte-level BPE tokenizer of GPT-2 which was developed for an almost entirely English training dataset.

GPT-2 Tokenizer 词典中最长的 Token 是什么

  tokens.sort(key=len, reverse=True)
print(len(tokens), tokens[:10])
  50257 [' =================================================================', ' ----------------------------------------------------------------', '----------------------------------------------------------------', '................................................................', '================================================================', '________________________________________________________________', 'ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂ', '--------------------------------------------------------', '------------------------------------------------', ' =================================']

可以看到,最长的 Token 居然是一些连续的标记,看起来像是论坛上的分割线。在“Natural Language Processing with Transformers” 一书中说,这可能是由于 GPT-2 的词典是用以 Reddit 为核心的语料训练的。

Codex Tokenizer 提升代码处理效率的 Trick

上面讲到 Tokenizer 效率对最终生成 Token 序列大小的影响,如果只关注最终的模型效果,可能并不在意中间过程的效率问题。

但从一个小点可以看到 OpenAI 还是很重视 Tokenizer 效率的。在训练 Codex 时,它在 50257 的词典之外新增了 23 个 Token,分别编码了:[2个连续空格, 3个连续空格, ..., 23个连续空格]。

大家都知道,代码中有很多锁进和对齐,如果每个空格都编码成一个 Token,训练和推理的效率就会极低;如果像常规语言模型那样忽视更多连续的空格,又会导致生成的代码不可读,甚至对 Python 这样的语言来说代码完全不可理解。所以 OpenAI 专门修改了 Tokenizer 的词典,提升了对连续空格的编码效率。

在中文数据集上训练的 Tokenizer 表现如何?

同样使用第一节的代码,我们换一个在中文数据集上训练的 Tokenizer,效果会如何呢?我随便在 HuggingFace 上找了一个模型 HuiHuang/gpt3-base-zh,使用它的 Tokenizer 对那段话进行重新分词。

  from transformers import BertTokenizerFast

tokenizer = BertTokenizerFast.from_pretrained("HuiHuang/gpt3-base-zh")
input_str = '不同的 Tokenizer 会把文本按不同的边界切分,那一段文本到底会被切成几个 Token 就体现了 Tokenizer 本身的效率,这本身也是信息论的讨论范畴。'
tokenids = tokenizer(input_str)['input_ids']
raw_tokens = tokenizer.convert_ids_to_tokens(tokenids)
token_strs = [tokenizer.convert_tokens_to_string([token]) for token in raw_tokens]
print(len(input_str), len(tokenids), tokenids, token_strs)
  82 65 [2, 215, 1750, 10574, 22090, 24330, 23635, 21748, 484, 5460, 6225, 6646, 5587, 215, 1750, 10574, 17027, 10262, 1233, 1232, 21124, 17261, 202, 7807, 6225, 6646, 1274, 4447, 484, 15221, 1233, 5338, 1194, 244, 22090, 24330, 3835, 541, 9850, 336, 22090, 24330, 23635, 21748, 6646, 16757, 10574, 6162, 9809, 21124, 17059, 6646, 16757, 297, 6393, 683, 4921, 16004, 10574, 15986, 16004, 13773, 10302, 160, 3] ['[CLS]', '不', '同', '的', 'to', '##ken', '##ize', '##r', '会', '把', '文', '本', '按', '不', '同', '的', '边', '界', '切', '分', ',', '那', '一', '段', '文', '本', '到', '底', '会', '被', '切', '成', '几', '个', 'to', '##ken', '就', '体', '现', '了', 'to', '##ken', '##ize', '##r', '本', '身', '的', '效', '率', ',', '这', '本', '身', '也', '是', '信', '息', '论', '的', '讨', '论', '范', '畴', '。', '[SEP]']

可以看到,82 个字符的输入被分成了 63 个 Token(除去[CLS]和[SEP]),比 GPT-2 Tokenizer 的分词数量 121 几乎少了一半。这就是 Tokenizer 训练数据集对分词效率的影响。

Tokenizer 的效率意味着什么

在以前,Tokenizer 的效率只是算法工程师们关注的话题。但是现在,LLM 逐渐成为云服务,Token 成为 API 调用的基本收费单元。例如:OpenAI gpt-3.5-turbo 的收费标准是 $0.002/1K tokens。

在这种情况下,Tokenizer 的效率就意味着成本。这意味着使用中文调用 OpenAI 的 chatGPT API,假设单 Token 成本一样的话,每次调用的实际成本可能是调用国内类似 chatGPT 云服务的 2 倍以上。

The post GPT-2 Tokenizer 效率观察 first appeared on 边际效应.

相关 [gpt tokenizer 观察] 推荐:

GPT-2 Tokenizer 效率观察

- - Solrex Shuffling
对基于 Transformer 结构的 LLM (大语言模型)来说,模型的输入输出都是 Token(词元). 一段输入文本,首先要经过 Tokenizer(分词器)切分成 Token 再输入给模型. 不同的 Tokenizer 会把文本按不同的边界切分,那一段文本到底会被切成几个 Token 就体现了 Tokenizer 本身的效率,这本身也是信息论的讨论范畴.

免费可商用开源GPT模型问世,50G权重直接下载,性能不输GPT-3

- - 量子位
量子位 | 公众号 QbitAI. 真·开源GPT模型,终于来了. 参数量级130亿,大小比肩最近Meta开放的LLaMA-13B,但从数据集、模型权重到计算优化训练, 全部开源. 没错,虽然就GPT-3而言,之前DeepMind、Meta等组织陆陆续续开源过几个模型,不过基本都是半遮半掩. 尤其最接近GPT-3的Meta OPT模型,不仅权重只开放给研究者,而且不可商用:.

[译] GPT 是如何工作的:200 行 Python 代码实现一个极简 GPT(2023)

- - ArthurChiao's Blog
本文整理和翻译自 2023 年 Andrej Karpathy 的 twitter 和一篇文章: GPT as a finite-state markov chain. Andrej Karpathy 博士 2015 毕业于斯坦福,之后先在 OpenAI 待了两年,是 OpenAI 的创始成员和研究科学家,2017 年加入 Tesla,带领 Tesla Autopilot 团队, 2022 年离职后在 Youtube 上科普人工智能相关技术,2023 年重新回归 OpenAI.

GPT-4重磅发布,你需要知道的10件事

- - 广告网 - 行业观察
本文由全元宇宙Allmetaverse主理人郑秋实出品. 2023年3月14日,OpenAI正式发布全新大型多模态模型GPT-4. OpenAI在以ChatGPT震撼全球的短短几个月之后,火速上线新一代里程碑GPT-4. 相较于上一代的ChatGPT和GPT-3.5, GPT-4到底带来了哪些更新,本文将为你快速盘点:.

OpenAI 发布 GPT-4,有哪些技术上的优化或突破?

- - 知乎每日精选
在这个历史性的时刻,回答个问题,留下自己作为历史见证人的足迹. GPT4的技术报告里很明确地指出了三个新的方向:. 第一,LLM最前沿研究的封闭化或小圈子化. 技术报告里说了,出于竞争以及安全等方面的考虑,未公布模型规模等技术细节. 从GPT 2.0的开源,到GPT 3.0的只有论文,再到ChatGPT连论文也没有,直到GPT 4.0的技术报告更像效果评测报告.

和AI结对编程!OpenAI与GitHub联手推出AI代码生成工具,比GPT-3更强大

- - 雷锋网
昨日,微软与OpenAI共同推出了一款AI编程工具GitHub Copilot,这款工具基于GitHub及其他网站的源代码,可根据上文提示为程序员自动编写下文代码. GitHub 的首席执行官 Nat Friedman 介绍说,GitHub Copilot是结对编程的虚拟版本. 结对编程是一种常见的敏捷软件开发技术——即两个开发人员在同一个项目上并肩协作,轮流编写代码并检查合作伙伴的输出.

无开发经验如何借助GPT-4开发一个 3D 太空赛跑游戏

- -
有人借助GPT-4,在没有JavaScript二胡3D游戏编程经验的情况下,一点点做除了一个 3D 太空赛跑游戏. 他首先问GPT-4该如何制作游戏,它建议使用BabylonJS,以及HTML和CSS. 然后作者描述了他的具体要求:. 1.游戏将采用与原版天空之城相同的摄像头,玩家从飞船后面看到轨道,而飞船则出现在他们面前.

面向GPT-4编程的时代来了:Github Copilot大升级,首次集成聊天功能

- - 机器之心
从今天开始,面向 GPT-4 编程. 面向 GPT-4 编程,程序员们终于等到了这一天. 作为 Copilot 代码补全工具的升级,GitHub 刚刚宣布了 Copilot X 计划,正式接入 GPT-4,并放出了一系列全新功能. Copilot X 搭建了一种以代码为中心的聊天模式. 升级后的 Copilot 在整个开发生命周期中均可应用,而不仅仅是代码补全.

做完GPT-4完整测评,微软爆火论文称初版AGI就快来了

- - 领研 | 论文「」
图片来源: Unsplash. GPT-4 的能力什么档次. 1956 年,在达特茅斯学院召开的一个研讨会上,人工智能这一概念正式被提出. 之后这个词一直挑战着心理学家、哲学家和计算机科学家,因为它太难被定义了. 1994 年,52 名心理学家联合发文试图捕捉它的本质. 随着时间的推移,研究者开始将注意力转移到特定领域的 AI 系统,如 2016 年 AlphaGo 挑战韩国冠军棋手大获全胜.

国产大模型推理能力已超GPT-3.5!冲进OpenAI评测榜第一梯队

- - 量子位
量子位 | 公众号 QbitAI. OpenAI开源的数学数据集,中国厂商新成绩一举冲到最前列. 就在9月16日,国产大模型在权威推理评测集GSM8K中,首次达到了80%正确率,大幅领先GPT-3.5(57.1%)和LLaMA2-70B(56.8%). 而且这家厂商在大模型榜单上刷新全球纪录,已经不是第一次了.