LLM通常系列

  • 电脑网络维修
  • 2024-11-14

通过了数据搜集、挑选、去重,马上就可以开局训练试验了。然而在试验之前,咱们还须要先失掉一个言语模型的基石:分词器(Tokenizer)。Tokenizer 的作用是对一条文本数据启动切分、词表映射,失掉这条文本的token序列。

用开源 Tokenizer 还是自己训练

Tokenizer可以自己训练,也可以从目前开源的模型中扒一个来用,用开源Tokenizer有几个点须要着重关注:

有开源tokenizer,训练自己的tokenizer意义何在?用自己的数据训练的 tokenizer,在同词表大小的状况下,会比开源tokenizer有更高的紧缩率(也不会高太多),可以必定水平降落训练和推理老本。另外更客观一点的要素是,训tokenizer是个很基础的上班,训不训必定水平上反映了团队的技术栈能否片面。还有一点须要留意的是,不同紧缩率的tokenizer训练的模型loss或许有差异,然而性能不会有太大差异。

经典的分词器有WordPiece 、subword-nmt、Unigram等等,然而这些并不是本文的重点,本文关键说目前最盛行的两种tokenizer:BPE和BBPE。

BPE(Byte Pair Encoding)

BPE是目前大模型干流的两种分词法之一,训练环节总结成一句话就是:迭代兼并最高频的token对,直到抵达预设词表大小下限。举个详细的例子来说,假定我要训练一个词表大小是12的tokenizer,训练语料就是上方这句话:

“淡水潮潮潮潮潮潮落,浮云长长长长长长长消”

1、 这句话首先会按字拆分红:海 水 潮 潮 潮 潮 潮 潮 落 , 浮 云 长 长 长 长 长 长 长 消。

我没数错的话算上逗号应该是总共有9个不重复的字。这些字会被当作初始token,参与词表。如今咱们离指标词表大小还差12-9=3个token,上方开局迭代兼并。

2、 统计曾经参与词表的一切token两两组合在训练语料中出现的次数。

这里有两点留意,首先是“”,也就是说每次迭代参与新token后,下一次性统计两两组合要算上这个新token。其次是“一切token两两组合”,也就是既要统计A token与B token的组合,也要统计A token与自身的组合。比如上方这个句子,咱们要统计“淡水”、“水潮”、“潮潮”、”潮落“....这些一切两两组合出现的次数。

3、 取两两组合中出现次数最高的那一个,作为新token参与词表,同时记载下这个token的分解门路。

比如上方“潮潮”和“长长”是出现次数最高的组合,都出现了5次,那么咱们取更早出现的“潮潮”作为本无所谓参与词表的新token,同时记载下”潮“+”潮“=”潮潮“。如今词表大小为10。

4、 假设词表没有到达设定的下限12,那么就迭代口头2-3步。

再一次性统计两两组合出现次数,这一次性最多的就是刚才并列第一的“长长”。当然也不要遗记上一步刚参与的“潮潮”这个token,他可以和前面的token组成“水潮潮”,也可以和前面的token组成“潮潮潮”,不过次数都不如“长长”。所以这一次性参与词表的是“长长”。

再迭代一次性,再统计组合,此时次数最多的是“潮潮”+“潮” 组成的“潮潮潮”,以及“长长”+“长”组成的“长长长”,区分出现4次。依照之前的准则,取次数最多且更靠前的“潮潮潮”参与词表,此时词表大小为12,训练中止,咱们曾经失掉了大小为12,在“淡水潮潮潮潮潮潮落,浮云长长长长长长长消”上训练的分词器。

BPE的训练环节还是很便捷很好了解的,然而还是有一些须要留意的中央。 上方的解释中有两个我刻意谨严表白的点,一个是「取次数最多且更靠前的“潮潮潮”参与词表」,另一个是「“潮潮”+“潮” 组成的“潮潮潮”,以及“长长”+“长”组成的“长长长”」。前者想说明token参与词表的顺序是有先后的,是有优先级的,后者说明token的分解门路模式须要严厉遵照,扭转词表或许造成失误的分解门路。

特地强调这个是由于我看到一些改词表的开源上班其实是有疑问的。举个我看到的实践的例子,有一个地名”乌鲁木齐“,假定词表中蕴含”乌鲁“和”鲁木“两个token。首先说可无法能出现这俩token?齐全或许,假设我的训练语料是上方这样的就会出现这两个token:

乌鲁乌鲁鲁木鲁木齐

这个语料训进去的tokenizer词表大略率是这样的:「乌」「鲁」「木」「齐」「乌鲁」「鲁木」

假设词表里乌鲁这个token在前,分词结果就是 「乌鲁」「 木」「 齐」,假设是鲁木这个token在前,分词结果就是「乌」「鲁木」「齐」。分词结果是不一样的。假设拿到一个训练过的模型,改一改词表顺序,肯能会造成分词结果的不分歧,模型或许齐全没有见过这样的token,造成一些无法了解的怪异生成结果。

再说分解门路,假设我的词表是 「乌」「鲁」「木」「齐」「乌鲁」「木齐」,起初扩增了词表,参与了「乌鲁」+「木」=「乌鲁木」,和「乌鲁木」+「齐」=「乌鲁木齐」两个token,「乌鲁木齐」这个token是分解不进去的,由于「木齐」在「乌鲁木」之前,所以优先分解「木齐」,而不是「乌鲁木」,那么没有「乌鲁木」,人造无法分解「乌鲁木齐」。假设要启动词表删减、扩增,或许两个tokenizer启动兼并,尤其要留意这个疑问。

BBPE(Byte-Level Byte Pair Encoding)

BBPE和BPE大体上是一样的,区别在于BPE把文本看作字符汇合,第一步是依照字符切分取得初始token,BBPE把文本看作是二进制编码,依照8bit切分取得原始token。比如还是上方那句话,会先转成utf8编码:

“淡水潮潮潮潮潮潮落,浮云长长长长长长长消” =>

"\xe6\xb5\xb7\xe6\xb0\xb4\xe6\xbd\xae\xe6\xbd\xae\xe6\xbd\xae\xe6\xbd\xae\xe6\xbd\xae\xe6\xbd\xae\xe8\x90\xbd\x2c..."

而后取每一个2位16进制数作为初始token,也就是「\xe6」「\xb5」「\xb7」...这些。剩下的统计两两组合、分解门路都和BPE是一样的,不过都是在二进制层面去兼并。咱们知道utf8是变长编码,ascii字符在utf8中的编码长度是1,也就是刚好一个2位16进制数。比如我上方句子里的逗号对应的utf8编码是“\x2c”。所以ascii字符必定会作为一个基础字符参与词表,而且也不会被拆分,所以英文单词、数字这种ascii字符组成的词,必定是整数个token示意的。然而汉字的编码长度大局部是3,比如“海”的编码是“\xe6\xb5\xb7”,这就造成汉字在bbpe的词表中并不必定是1个、2个字这种整数个token组成。或许是3/2个token示意一个汉字。

BBPE与BPE的对比

从盛行度来说,BPE是去年、前年大家广泛经常使用的方法,而BBPE是去年底到往年的模型关键经常使用的方法。GPT2经常使用的tokenizer也是BBPE。

从编码的角度,有一些文章说BBPE对比BPE的优势是不存在OOV疑问,字符只需能转utf8,就必定能被BBPE示意,然而实践口头起来并不是,由于大局部BPE的库也支持bytes退步,遇到超出词表范畴的字符,也会退步到二进制示意。这么看上去BBPE剩下的优势就是多语种下、token切分更平均。毕竟一个中文能占3/2个token了。

从成功的角度,BPE的tokenizer用sentencepice库的居多,BBPE用huggingface的tokenizers库的居多,然而sentencepice库产出的tokenizer.model实质是一个protobuf文件,可以用protobuf库读出这个tokenizer原始的训练参数,甚至带着训练语料的磁盘门路,不太安保。

训练参数

除了最基本的词表大小外,实践训练的tokenizer还有一些可性能关键参数。我比拟青睐读google的文档,就拿sentencepice的训练参数来引见了,两个库的可性能参数其实差不多,可以类比。

--vocab_size

tokenizer预设的词表大小。最终模型训练的时刻,咱们普通会确保embedding层的shape可以被128整除,这个一方面是为了量化思考,一方面是为了序列并行思考。所以可以在这一步间接设置一个能被128整除的词表大小,也可以这里不设置,等tokenizer训练完了加一些不凡token,补到128的倍数。另外词表大小也选择了紧缩率。

--character_coverage

字符笼罩率。这个示意在最一开局,初始单字token要笼罩训练语料中所有token的百分之多少。假设是1,示意一切token只需出现就参与初始词表,这会造成词表的单字token过多。普通可以设置0.9998、0.9999,示意初始单字token要笼罩训练集字符的99.99%

--max_sentencepiece_length

繁多token最多多少个字符组成,普通设为2、4、6,8或以上就比拟大了,不太介绍,或许会出现低频超长token。

--split_digits

能否做数字的分歧性切分,说白了就是数字和其余token能否可以组分解新token,还是数字必定一个字符一个token不做兼并。早期一些上班以为开了对数学义务无好处,然而从我的试验过去看,是可以关上,但不是必定。数字在人造界是平均散布的,也就是说1、2、3还是111、222、132、863数量其实是差不多的,所以就算不开分歧性切分,这些token也都应该在词表里。只需模型训练充沛,模型是能分辨111和1 1 1是一个物品的。我不时以为不应该对言语模型的泛化抱有太失望的态度,它就只能说出见过的话。所以我不指望在欠训练的模型上,依赖分歧性切分提高数学才干。当然这是现实状况,假设数据集预备的不充沛,不能保障一切这些数字都出如今词表里,可以手动把0-9999参与到词表里,这样既坚持分歧性,又能提高紧缩率。说个题外话,前段期间知乎高端行讨论为什么9.11>9.8,我以为就是token欠训练,又刚好没有泛化过去。为什么没有泛化过去呢?由于真的有9.11大于9.8的时刻。python3.11就大于python3.8

--allow_whitespace_only_pieces

准许多个空格作为一个token,普通是准许,关键是为了排版,比如python的代码排版。当然也可以不开,手动把1-20个空格组成的token参与到词表里。

-user_defined_symbols

这个关键就是为了性能之前说的不凡token,可以预留几百比如<reserved_0> <reserved_1> ...,假设要手动参与数字的分歧切分和延续空格token,也可以在这里加

--byte_fallback

之前说的二进制退步,让BPE当半个BBPE用

--remove_extra_whitespaces

能否删除多余空格,这个普通改为False,不要让tokenizer随意动咱们的空格。

--unk_id 、--bos_id、--eos_id、--pad_id 、 --unk_piece、--bos_piece、--eos_piece、--pad_piece

指定控制字符和ID,这外面如今咱们普通只用pad和eos。在训练的时刻文档或许一个turn的末尾参与一个eos token。须要做padding补齐的时刻拼pad token,也可以间接用eos token当补齐token。不过倡导四个都设置上,也算是致敬一下之前的NLPer

番外篇1:tokenizer与loss

不同tokenizer的紧缩率,每个token的消息量是不同的,这就造成不同tokenizer在同一份数据下训练进去的模型loss不一样。假定不思考训练tokenizer的语料品质差异,那么tokenizer的紧缩率越高,同一个文本分词后发生的token越少,整句话的平均loss就越高。同样紧缩率越低,一句话的loss通常也越低。然而实践推理起来,两种tokenizer训进去的模型成果差异不大,所以更多的还是从效率和老本的角度思考紧缩率的取舍吧。

再引申一下,从这一点上不由让咱们升起一个纳闷,loss能代表模型性能吗?答案是不行。其实同loss不同tokenizer、同loss不同参数量的模型性能都不一样。这个详细可以等写到scaling law拟合、模型性能预测或许continue pretraining的时刻再讨论。

番外篇2:看一看实在的tokenizer

再拿qwen2的tokenizer举例,qwen2的tokenizer时BBPE,关键文件有这么几个:

merges.txt就是保管分解门路的文件,外面看上去会有一些像乱码的物品:

这些其实是转义后的控制字符。前面也说了BBPE的初始token是2位16进制数。假设间接存这些二进制字符,或许被翻译成ascii码中的控制字符,比如换行制表符之类的,所以这里坐了下转义。

vocab.json是每次token的映射id,tokenizer_config.json外面可以性能一下控制字符。tokenizer训练完之后假构想加不凡字符,也可以在这里性能。

番外篇3:词表增减疑问

词表的修正最好出当初模型训练之前,包括tokenizer兼并、参与不凡token、自定义token等等,这其中还尤其要留意参与词表。言语模型训练的时刻,计算logits时是hidden_states和一切token的logits_weight的乘积,softmax也是一切token的归一,删除词表相当于减小归一化的分母,会造成最后sample时的概率出现变动。参与token则跟要小心,假设参与的token未经训练,或许造成归一化后乱掉。假设参与的token初始化的不好,比如反常token是1e-2,新参与的token是1e-23量级,rms norm会回传给embedding层一个大略在1e21量级的梯度。这个时刻假设你开了梯度裁切,在求梯度的模长的时刻1e21求平方间接变成inf,再归一化其余token,一切token梯度都会变成0,这样你不太看得进去报错,然而embedding实践一点没训。

再有就是前文强调过的,留意解决分解门路和token顺序的抵触疑问。

本文转载自​​,作者:​​

  • 关注微信

本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载联系作者并注明出处:https://duobeib.com/diannaowangluoweixiu/5460.html

猜你喜欢

热门标签

洗手盆如何疏浚梗塞 洗手盆为何梗塞 iPhone提价霸占4G市场等于原价8折 明码箱怎样设置明码锁 苏泊尔电饭锅保修多久 长城画龙G8253YN彩电输入指令画面变暗疑问检修 彩星彩电解除童锁方法大全 三星笔记本培修点上海 液晶显示器花屏培修视频 燃气热水器不热水要素 热水器不上班经常出现3种处置方法 无氟空调跟有氟空调有什么区别 norltz燃气热水器售后电话 大连站和大连北站哪个离周水子机场近 热水器显示屏亮显示温度不加热 铁猫牌保险箱高效开锁技巧 科技助力安保无忧 创维8R80 汽修 a1265和c3182是什么管 为什么电热水器不能即热 标致空调为什么不冷 神舟培修笔记本培修 dell1420内存更新 青岛自来水公司培修热线电话 包头美的洗衣机全国各市售后服务预定热线号码2024年修缮点降级 创维42k08rd更新 空调为什么运转异响 热水器为何会漏水 该如何处置 什么是可以自己处置的 重庆华帝售后电话 波轮洗衣机荡涤价格 鼎新热水器 留意了!不是水平疑问! 马桶产生了这5个现象 方便 极速 邢台空调移机电话上门服务 扬子空调缺点代码e4是什么疑问 宏基4736zG可以装置W11吗 奥克斯空调培修官方 为什么突然空调滴水很多 乐视s40air刷机包 未联络视的提高方向 官网培修 格力空调售后电话 皇明太阳能电话 看尚X55液晶电视进入工厂形式和软件更新方法 燃气热水器缺点代码

热门资讯

关注我们

微信公众号