大模型中的Tokenizer

news2024/9/22 11:28:30

  在使用GPT 、BERT模型输入词语常常会先进行tokenize 。

  tokenize的目标是把输入的文本流,切分成一个个子串,每个子串相对有完整的语义,便于学习embedding表达和后续模型的使用。

一、粒度

三种粒度:word/subword/char

  • word词,是最自然的语言单元。对于英文等自然语言来说,存在着天然的分隔符,比如说空格,或者是一些标点符号,对词的切分相对容易。但是对于一些东亚文字包括中文来说,就需要某种分词算法才行。顺便说一下,Tokenizers库中,基于规则切分部分,采用了spaCy和Moses两个库。如果基于词来做词汇表,由于长尾现象的存在,这个词汇表可能会超大。像Transformer XL库就用到了一个26.7万个单词的词汇表。这需要极大的embedding matrix才能存得下。embedding matrix是用于查找取用token的embedding vector的。这对于内存或者显存都是极大的挑战。常规的词汇表,一般大小不超过5万。
  • char/字符, 也就是说,我们的词汇表里只有最基本的字符。而一般来讲,字符的数量是少量有限的。这样做的问题是,由于字符数量太小,我们在为每个字符学习嵌入向量的时候,每个向量就容纳了太多的语义在内,学习起来非常困难。
  • subword子词级,它介于字符和单词之间。比如说Transformers可能会被分成Transform和ers两个部分。这个方案平衡了词汇量和语义独立性,是相对较优的方案。它的处理原则是,常用词应该保持原状,生僻词应该拆分成子词以共享token压缩空间

二、 不同tokenize的策略比较

1、word-level

这些分词的方法都是将句子拆分为词,即word-level,这么做的优缺点是:

优点:能够保存较为完整的语义信息

缺点:

1、词汇表会非常大,大的词汇表对应模型需要使用很大的embedding层,这既增加了内存,又增加了时间复杂度。

2、 word-level级别的分词略显粗糙,无法发现更加细节的语义信息,例如模型学到的“old”, “older”, and “oldest”之间的关系无法泛化到“smart”, “smarter”, and “smartest”。

3、word-level级别的分词对于拼写错误等情况的鲁棒性不好

4、 oov问题不好解决

2、char-level

一个简单的方法就是将word-level的分词方法改成 char-level的分词方法,对于英文来说,就是字母界别的,比如 "China"拆分为"C","h","i","n","a",对于中文来说,"中国"拆分为"中","国",

优点:

1、这可以大大降低embedding部分计算的内存和时间复杂度,以英文为例,英文字母总共就26个,中文常用字也就几千个。

2、char-level的文本中蕴含了一些word-level的文本所难以描述的模式,因此一方面出现了可以学习到char-level特征的词向量FastText,另一方面在有监督任务中开始通过浅层CNN、HIghwayNet、RNN等网络引入char-level文本的表示;

缺点:

1、但是这样使得任务的难度大大增加了,毕竟使用字符大大扭曲了词的意义,一个字母或者一个单中文字实际上并没有任何语义意义,单纯使用char-level往往伴随着模型性能的下降;

2、增加了输入的计算压力,原本”I love you“是3个embedding进入后面的cnn、rnn之类的网络结构,而进行char-level拆分之后则变成 8个embedding进入后面的cnn或者rnn之类的网络结构,这样计算起来非常慢;

3、subword-level

subword-level的分词方式遵循的原则是:尽量不分解常用词,而是将不常用词分解为常用的子词

例如,"annoyingly"可能被认为是一个罕见的单词,并且可以分解为"annoying"和"ly"。"annoying"并"ly"作为独立的子词会更频繁地出现,同时,"annoyingly"是由"annoying"和"ly"这两个子词的复合含义构成的复杂含义,这在诸如土耳其语之类的凝集性语言中特别有用,在该语言中,可以通过将子词串在一起来形成(几乎)任意长的复杂词。

subword-level的分词方式使模型相对合理的词汇量(不会太多也不会太少),同时能够学习有意义的与上下文无关的表示形式(另外,subword-level的分词方式通过将模型分解成已知的子词,使模型能够处理以前从未见过的词(oov问题得到了很大程度上的缓解)。

三. 常用tokenize算法

最常用的三种tokenize算法:BPE(Byte-Pair Encoding),WordPiece和SentencePiece

3.1 Byte-Pair Encoding (BPE) / Byte-level BPE

 BPE
  • 首先,它依赖于一种预分词器pretokenizer来完成初步的切分。pretokenizer可以是简单基于空格的,也可以是基于规则的;
  • 分词之后,统计每个词出现的频次供后续计算使用。例如,我们统计到了5个词的词频

("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)

  • 建立基础词汇表,包括所有的字符,即:

["b", "g", "h", "n", "p", "s", "u"]

  • 根据规则,我们分别考察2-gram,3-gram的基本字符组合,把高频的ngram组合依次加入到词汇表当中,直到词汇表达到预定大小停止。比如,我们计算出ug/un/hug三种组合出现频次分别为20,16和15,加入到词汇表中。
  • 最终词汇表的大小 = 基础字符词汇表大小 + 合并串的数量,比如像GPT,它的词汇表大小 40478 = 478(基础字符) + 40000(merges)。添加完后,我们词汇表变成:

["b", "g", "h", "n", "p", "s", "u", "ug", "un", "hug"]

实际使用中,如果遇到未知字符用<unk>代表。

以语料:

{'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}

为例,假设我们对原始的文本进行分词之后只有上面4个词,则:

1、对每个词进行词频统计,并且对每个词末尾的字符转化为 末尾字符和</w>两个字符,停止符"</w>"的意义在于表示subword是词后缀。举例来说:"st"字词不加"</w>"可以出现在词首如"st ar",加了"</w>"表明改字词位于词尾,如"wide st</w>",二者意义截然不同。

{'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}

此时我们的词表为

{"l","o",'w',"e","r","</w>","n","s","t","i"}

2、统计每一个连续字节对的出现频率,选择最高频者合并成新的subword

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

最高频连续字节对"e"和"s"出现了6+3=9次,合并成"es"

需要注意的是,"es"生成后会消除"s",因为上述语料中 "s"总和"es"共同出现,但是s除了"es"外就没有其它的字符组合出现了,所以"s"被消除,但是"e"在"lower"中出现过有"er"或"we"这样的组合,所以"e"没有被消除,此时词表变化为

{"l","o",'w',"e","r","</w>","n","es","t","i"}

(补充另外两种情况:

如果es中的e和s都是和es一起出现,除此之外没有单独再出现其它的字符组合,则es一起消除;如果es中的e和s都各自有和其它字符的组合,则e和s都不会被消除,但是多了个新词es)

3、继续上述过程:

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

此时最高频连续字节对"es"和"t"出现了6+3=9次, 合并成"est"。输出:

同理,上一步的词表中"t"被消除,"est"加入此表

......

继续迭代直到达到人工预设的subword词表大小或下一个最高频的字节对出现频率为1。

上述就完成了编码过程,得到了词表,然后要把原始的word-level的分词结果进行相应转化:

1、将此表按照其中token的长度,从长到短排列;

例如排序好之后的词表为:

[“errrr</w>”, “tain</w>”, “moun”, “est</w>”, “high”, “the</w>”, “a</w>”]

2、对原始的word-level的分词结果进行转化,例如原始的语料为:

[“the</w>”, “highest</w>”, “mountain</w>”]

则转化为:

"the</w>" -> ["the</w>"]
"highest</w>" -> ["high", "est</w>"]
"mountain</w>" -> ["moun", "tain</w>"]

这样就完成了BPE的分词了;

Byte-level BPE

BPE的一个问题是,如果遇到了unicode,基本字符集可能会很大。一种处理方法是我们以一个字节为一种“字符”,不管实际字符集用了几个字节来表示一个字符。这样的话,基础字符集的大小就锁定在了256

例如,像GPT-2的词汇表大小为50257 = 256 + <EOS> + 50000 mergers,<EOS>是句子结尾的特殊标记。

3.2 WordPiece

WordPiece,从名字好理解,它是一种子词粒度的tokenize算法subword tokenization algorithm,很多著名的Transformers模型,比如BERT/DistilBERT/Electra都使用了它。

它的原理非常接近BPE,不同之处在于,它在做合并的时候,并不是每次找最高频的组合,而是找能够最大化训练集数据似然的merge,即它每次合并的两个字符串A和B,应该具有最大的 P(AB)P(A)P(B) 值。合并AB之后,所有原来切成A+B两个tokens的就只保留AB一个token,整个训练集上最大似然变化量与 P(AB)P(A)P(B) 成正比。

3.3 Unigram

与BPE或者WordPiece不同,Unigram的算法思想是从一个巨大的词汇表出发,再逐渐删除trim down其中的词汇,直到size满足预定义。

初始的词汇表可以采用所有预分词器分出来的词,再加上所有高频的子串。

每次从词汇表中删除词汇的原则是使预定义的损失最小。训练时,计算loss的公式为:

假设训练文档中的所有词分别为 x1;x2...xN ,而每个词tokenize的方法是一个集合 S(xi) 。当一个词汇表确定时,每个词tokenize的方法集合 S(xi) 就是确定的,而每种方法对应着一个概率p(x)。如果从词汇表中删除部分词,则某些词的tokenize的种类集合就会变少,log(*)中的求和项就会减少,从而增加整体loss。

Unigram算法每次会从词汇表中挑出使得loss增长最小的10%~20%的词汇来删除。

一般Unigram算法会与SentencePiece算法连用。

3.4 SentencePiece

SentencePiece,它是把一个句子看作一个整体,再拆成片段,而没有保留天然的词语的概念。一般地,它把空格space也当作一种特殊字符来处理,再用BPE或者Unigram算法来构造词汇表。

比如,XLNetTokenizer就采用了_来代替空格,解码的时候会再用空格替换回来。

目前,Tokenizers库中,所有使用了SentencePiece的都是与Unigram算法联合使用的,比如ALBERT、XLNet、Marian和T5.

四、切分实例

4.1 BertTokenizer / WordPiece

4.2 T5Tokenizer / SentencePiece 

参考文章

NLP BERT GPT等模型中 tokenizer 类别说明详解-腾讯云开发者社区-腾讯云 (tencent.com)

tokenizers小结 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1696480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能+跨癌种分析,能否解决医学数据样本量小的问题?【医学AI|顶刊速递|05-26】

小罗碎碎念 先说明&#xff0c;目前小罗只是硕士&#xff0c;以下个人观点很有可能不准确&#xff0c;欢迎批评指正&#xff01;&#xff01;小罗虚心听取有益建议&#xff01;&#xff01; 众所周知&#xff0c;医学数据相比于其他领域的数据来说&#xff0c;属于小样本数据。…

Java----Maven详解

前言 Maven是Java项目的构建工具&#xff0c;通过项目对象模型&#xff08;POM&#xff09;管理项目配置信息&#xff0c;自动化构建、测试和部署过程。开发人员可定义项目结构、依赖和构建流程&#xff0c;提高开发效率和质量。本文介绍基本概念和用法&#xff0c;帮助您更好…

ros2编写pcl节点加载pcd文件

初次学习ros2和pcl&#xff0c;尝试在ros2中创建节点&#xff0c;加载pcd文件&#xff0c;并在rviz中进行可视化&#xff0c;记录一下整个过程。 编辑环境 ubuntu20.04 ros2_foxy 创建节点 mkdir -p proj_ws_pcl/src #创建工程文件夹 cd proj_ws_pcl/src #创建源码文件夹 …

社交媒体数据恢复:绿洲

本教程将向您展示如何在绿洲平台上备份和恢复数据&#xff0c;但不涉及推荐任何具体的数据恢复软件。 一、绿洲平台数据备份 为了确保数据的安全&#xff0c;在日常使用过程中&#xff0c;我们需要定期备份绿洲平台上的数据。以下是备份绿洲平台数据的步骤&#xff1a; 登录绿…

opencv进阶 ——(四)图像处理之去高光

去高光步骤&#xff1a; 1、转换成灰度图 2、二值化图像&#xff0c;得到高光区域 3、进行膨胀操作&#xff0c;放大高光区域&#xff0c;以此得到高光蒙版 4、通过illuminationChange函数对高光区域消除高光

Vite + Vue3 部署 GitHub

因为静态资源是可以部署到 GitHub 上&#xff0c;自己顺便学习部署网站 因为我使用的是 Vite 工具&#xff0c;官方有提供相应 Demo 部署静态站点 | Vite 官方中文文档 新建文件夹 .github 然后再建一个文件夹 workflows 新建文件 main.yml 文件 直接使用官方文档 demo #…

携手AI,如何共赢未来?

5/25日参加了一个培训分享会&#xff0c;由博奥研究院、武汉博奕咨询和华工科技联合举办&#xff0c;主题是“携手Ai&#xff0c;共赢未来”。 抱着跟书友线下交流的心态我参与了&#xff0c;参与前我对博奥做了基础了解&#xff0c;他们跟工信部考试和教育中心有合作&#x…

区间预测 | Matlab实现DNN-KDE深度神经网络结合核密度估计多置信区间多变量回归区间预测

区间预测 | Matlab实现DNN-KDE深度神经网络结合核密度估计多置信区间多变量回归区间预测 目录 区间预测 | Matlab实现DNN-KDE深度神经网络结合核密度估计多置信区间多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现DNN-KDE深度神经网络结合…

Textual for Mac:轻量级IRC客户端

在寻找一款高效、轻量级的IRC客户端时&#xff0c;Textual for Mac无疑是你的不二之选。它集成了众多现代技术&#xff0c;如本机IPv6、最新的IRCv3规范&#xff0c;以及客户端证书身份验证&#xff0c;让你的聊天体验更加顺畅和安全。 Textual for Mac v7.2.2免激活版下载 Tex…

Soybean Admin:一款高效、现代化的后台管理模板探索

随着前端技术的快速发展&#xff0c;越来越多的开发者开始寻求使用最新技术栈来构建高效、用户友好的后台管理系统。Soybean Admin作为一款基于Vue3、Vite5、TypeScript、Pinia、NaiveUI和UnoCSS等前沿技术的后台管理模板&#xff0c;为我们提供了一个全新的解决方案。本文将深…

SWM320系列应用

一、Swm320系列 SPI 应用 现象&#xff1a;应用SWM320的SPI1的模式0作为从机&#xff0c;整体产品硬件平台同步上电&#xff0c;从机的SPI无法正常工作&#xff0c;进不了中断&#xff0c;手工复位一次或连接SWD调试就正常了&#xff0c;这样的情况应该怎么解决&#xff1f;其…

Next.js里app和pages文件夹的区别

最近开始学 Next.js&#xff0c;因为纯自学&#xff0c;有时候网上找到的学习资料都是几年前的&#xff0c;难免会有点 outdated&#xff0c;因此当自己创建的项目结构和视频里呈现的结构不一致时&#xff0c;难免会有点困惑。 例如&#xff0c;今天遇到的第一个问题就是&…

企业如何正确地利用LLM大模型?

大型语言模型 (LLM) 不值得信任。就是这样。 考虑到它们先进的 AI 能力以及当今强大的基础模型的普遍知识&#xff0c;这似乎是一件令人惊讶的事情。然而&#xff0c;问题的关键在于 LLM 无法解释其输出。你不能信任 LLM 的结果&#xff0c;不是因为它不准确&#xff0c;而是因…

(南京观海微电子)——MCU屏介绍

MCU-LCD屏与RGB-LCD屏主要区别在于显存的位置&#xff1a; RGB-LCD的显存是由系统内存充当的&#xff0c;因此其大小只受限于系统内存的大小&#xff0c;这样RGB-LCD可以做出较大尺寸&#xff0c;像现在4.3只能算入门级&#xff0c;而MID中7、10的屏都开始大量使用。 MCU-L…

window好用的网速工具

这是一个用于显示当前网速、CPU及内存利用率的桌面悬浮窗软件&#xff0c;并支持任务栏显示&#xff0c;支持更换皮肤。 github链接如下 https://github.com/zhongyang219/TrafficMonitor?tabreadme-ov-file

Spring MVC+mybatis 项目入门:旅游网(一)项目创建与准备

个人博客&#xff1a;Spring MVCmybatis 项目入门:旅游网&#xff08;一&#xff09;项目创建与准备 | iwtss blog 先看这个&#xff01; 这是18年的文章&#xff0c;回收站里恢复的&#xff0c;现阶段看基本是没有参考意义的&#xff0c;技术老旧脱离时代&#xff08;2024年辣…

解密Spring Boot Starter与自动配置:探秘神奇的背后

starter可以理解为Spring Boot中的一站式集成启动器&#xff0c;包含了一系列可以集成到应用中的依赖项&#xff0c;可以快递集成spring组件及其框架&#xff0c;而不需要到处找示例代码。 一、为什么要用starter&#xff1f; 在springboot还没有出来之前&#xff0c;我们使用…