【大模型实战篇】大模型分词算法BPE(Byte-Pair Encoding tokenization)及代码示例
词元化是针对自然语言处理任务的数据预处理中一个重要步骤,目的是将原始文本切分成模型可以识别和处理的词元序列。在大模型训练任务中,就是作为大模型的输入。传统的自然语言处理方法,如基于条件随机场的序列标注,主要采用基于词汇的分词方式,这与我们人类的语言认知更为契合。但是,这种分词方法在中文等语言中,可能会导致对同一输入产生不同的分词结果,从而生成包含大量低频词的庞大词表,并可能出现未登录词(OOV)的问题。因此,一些语言模型开始使用字符作为最小单位进行分词,例如,ELMo 使用了 CNN 词编码器。近年来,子词分词器在基于 Transformer 的语言模型中得到了广泛应用,常见的方法包括 BPE 分词、WordPiece 分词和 Unigram 分词,接下来我们将参考huggingface的材料【1】来分析这几类分词器,并展示每种模型使用的标记器类型的示例。本文首先对BPE进行分享。
1. 原理讲解
字节对编码(BPE, Byte-Pair Encoding tokenization)【2】最初是作为一种文本压缩算法开发的,随后被OpenAI用于预训练GPT模型时的分词。许多Transformer模型都使用了该算法,包括GPT、GPT-2、RoBERTa、BART和DeBERTa。BPE 算法从一组基本符号(如字母和边界字符)开始,迭代地寻找语料库中的两个相邻词元,并将它们替换为新的词元,这一过程被称为合并。合并的选择标准是计算两个连续词元的共现频率,也就是每次迭代中,最频繁出现的一对词元会被选择与合并。合并过程将一直持续达到预定义的词表大小【3】。
BPE训练开始于计算语料库中使用的唯一词汇集(在完成标准化和预分词步骤后),然后通过获取写这些词所用的所有符号来构建词汇表。举个非常简单的例子,假设我们的语料库使用了以下五个词:
"hug", "pug", "pun", "bun", "hugs"
基础词汇表将是["b", "g", "h", "n", "p", "s", "u"]。在实际情况下,该基础词汇表至少会包含所有ASCII字符,并可能包括一些Unicode字符。如果一个例子使用了在训练语料库中不存在的字符,该字符将被转换为未知标记。许多NLP模型在分析包含表情符号的内容时表现不佳的原因可能这个就是其中一种。
GPT-2和RoBERTa的分词器(相似性较高)有一种方法来处理这个问题:它们将词视为由字节组成,而不是Unicode字符。这样基础词汇表的大小就很小(256),但字符仍会被包含在内,而不会被转换为未知标记。这个技巧称为字节级BPE。 字节级别的 BPE(Byte-level BPE, B-BPE)是 BPE 算法的一种扩展,它将字节视为合并操作的基本符号,从而实现更精细的分割,并解决了未登录词的问题。代表性语言模型如 GPT-2、BART 和 LLaMA 都采用了这种分词方法。具体而言,如果将所有 Unicode 字符视为基本字符,基本词表的规模会非常庞大(例如,每个汉字都作为一个基本字符)。而使用字节作为基本字符,可以将词汇表的大小限制在 256,同时确保所有基本字符都包含在内。以 GPT-2 为例,其词表大小为 50,257,包含 256 个字节的基本词元、一个特殊的文末词元,以及通过 50,000 次合并学习到的词元。通过一些处理标点符号的附加规则,GPT-2 的分词器能够有效进行分词,而无需使用 “<UNK>” 符号。
在获得这个基础词汇表后,通过学习合并规则(将现有词汇表中的两个元素合并为一个新元素的规则)添加新标记,直到达到所需的词汇大小。因此,最开始这些合并将创建两个字符的标记,随着训练的进行,合并会生成更长的子词。在分词器训练的任何步骤中,BPE算法都会寻找最常见的现有标记对。最常见的那一对将被合并,然后重复下一步。
回到之前的例子,假设这些词的频率如下:
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)
这意味着“hug”在语料库中出现了10次,“pug”5次,“pun”12次,“bun”4次,“hugs”5次。我们通过将每个词拆分为字符(构成我们初始词汇表的字符)开始训练,这样我们就可以将每个词视为标记的列表:
("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)
然后查看标记对。标记对("h", "u")出现在“hug”和“hugs”中,因此在语料库中总共出现15次。但这不是最常见的标记对:最常见的对是("u", "g"),出现在“hug”、“pug”和“hugs”中,在词汇表中总共出现20次。因此,分词器学到的第一个合并规则是("u", "g") -> "ug",这意味着“ug”将被添加到词汇表中,并且在语料库中的所有词中都应合并该对。在这个阶段结束时,词汇表和语料库如下所示:
词汇表: ["b", "g", "h", "n", "p", "s", "u", "ug"]
语料库: ("h" "ug", 10), ("p" "ug", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "ug" "s", 5)
现在有一些结果是超过两个字符的标记对:例如,标记对("h", "ug")(在语料库中出现15次)。然而,此时最常见的对是("u", "n"),在语料库中出现16次,因此第二个学习的合并规则是("u", "n") -> "un"。将其添加到词汇表并合并所有现有的出现结果如下:
词汇表: ["b", "g", "h", "n", "p", "s", "u", "ug", "un"]
语料库: ("h" "ug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("h" "ug" "s", 5)
现在最常见的对是("h", "ug"),所以我们学习合并规则("h", "ug") -> "hug",这给我们带来了第一个三字符的标记。合并后,语料库如下:
词汇表: ["b", "g", "h", "n", "p", "s", "u", "ug", "un", "hug"]
语料库: ("hug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("hug" "s", 5)
然后继续这样处理直到达到所需的词汇大小。
分词紧密跟随训练过程,新输入的分词通过以下步骤完成:
- 标准化
- 预分词
- 将词拆分为单个字符
- 在这些拆分上按顺序应用学习到的合并规则
以刚才使用的例子为例,三条学习到的合并规则为:
("u", "g") -> "ug"
("u", "n") -> "un"
("h", "ug") -> "hug"
单词“bug”将被分词为["b", "ug"]。然而,“mug”将被分词为["[UNK]", "ug"],因为字母“m”不在基础词汇表中。同样,“thug”将被分词为["[UNK]", "hug"]:字母“t”不在基础词汇表中,应用合并规则后首先会合并“u”和“g”,然后合并“h”和“ug”。
2. BPE代码实现
2.1 创建jupyter实验环境
为了快速方便验证代码,因此我们在服务器上安装了jupyter,来进行编程演示。这里记录下安装和部署的方式。
首先服务器上下载安装jupyter:
pip install jupyter
设置登录密码
jupyter notebook password
启动jupyter
jupyter notebook --no-browser --ip=0.0.0.0 --allow-root
访问jupyter-lab
一般域名就是:https://你的服务器ip地址:8888/lab
2.2 代码实现
示例语料库如下
corpus = ["This is the Hugging Face Course.","This chapter is about tokenization.","This section shows several tokenizer algorithms.","Hopefully, you will be able to understand how they are trained and generate tokens.",
]
我们需要将该语料库预分词为单词。这里将使用gpt2分词器进行预分词,国内的话,为了方便,我们依然采用model scope的模型库来操作, 下载gpt2模型到本地并加载,下载大概要花个几分钟的样子:
import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
import os
from transformers import AutoTokenizermodel_dir = snapshot_download('AI-ModelScope/gpt2', cache_dir='/root/autodl-tmp', revision='master')
mode_name_or_path = '/root/autodl-tmp/AI-ModelScope/gpt2'
tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, trust_remote_code=True)
然后,在预分词的同时,我们计算每个单词在语料库中的频率,并且计算基础词汇表,由语料库中使用的所有字符组成,将模型使用的特殊标记添加到词汇表的开头。对于GPT-2,唯一的特殊标记是"<|endoftext|>"。另外说明下:前面带有“Ġ”符号的词(例如“Ġis”、“Ġthe”)通常是在使用字节级别的BPE(Byte-level BPE)分词时生成的。这个符号的作用是标记一个单词是以空格开头的,即这个单词前面有一个空格。这种标记方式在处理文本时有助于保持词与词之间的分隔,使模型能够更好地理解上下文。
from collections import defaultdictword_freqs = defaultdict(int)for text in corpus:words_with_offsets = tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str(text)new_words = [word for word, offset in words_with_offsets]for word in new_words:word_freqs[word] += 1print(word_freqs)
alphabet = []for word in word_freqs.keys():for letter in word:if letter not in alphabet:alphabet.append(letter)
alphabet.sort()print(alphabet)
将每个单词拆分为单个字符,以便开始训练。计算每个标记对的频率。找到出现次数最多的词对。
splits = {word: [c for c in word] for word in word_freqs.keys()}
def compute_pair_freqs(splits):pair_freqs = defaultdict(int)for word, freq in word_freqs.items():split = splits[word]if len(split) == 1:continuefor i in range(len(split) - 1):pair = (split[i], split[i + 1])pair_freqs[pair] += freqreturn pair_freqspair_freqs = compute_pair_freqs(splits)for i, key in enumerate(pair_freqs.keys()):print(f"{key}: {pair_freqs[key]}")if i >= 5:break
best_pair = ""
max_freq = Nonefor pair, freq in pair_freqs.items():if max_freq is None or max_freq < freq:best_pair = pairmax_freq = freqprint(best_pair, max_freq)
第一个合并学习的是 ('Ġ', 't')
-> 'Ġt'
,我们将 'Ġt'
添加到词汇表中。接下来,在分割字典中应用这个合并。
merges = {("Ġ", "t"): "Ġt"}
vocab.append("Ġt")
def merge_pair(a, b, splits):for word in word_freqs:split = splits[word]if len(split) == 1:continuei = 0while i < len(split) - 1:if split[i] == a and split[i + 1] == b:split = split[:i] + [a + b] + split[i + 2 :]else:i += 1splits[word] = splitreturn splits
splits = merge_pair("Ġ", "t", splits)
print(splits["Ġtrained"])
循环,直到学习到我们想要的所有合并。设置目标词汇表大小为 50。
vocab_size = 50while len(vocab) < vocab_size:pair_freqs = compute_pair_freqs(splits)best_pair = ""max_freq = Nonefor pair, freq in pair_freqs.items():if max_freq is None or max_freq < freq:best_pair = pairmax_freq = freqsplits = merge_pair(*best_pair, splits)merges[best_pair] = best_pair[0] + best_pair[1]vocab.append(best_pair[0] + best_pair[1])print(merges)
接下来为了对新文本进行分词,先进行预分词,再拆分,然后应用所有学习到的合并规则:
def tokenize(text):pre_tokenize_result = tokenizer._tokenizer.pre_tokenizer.pre_tokenize_str(text)pre_tokenized_text = [word for word, offset in pre_tokenize_result]splits = [[l for l in word] for word in pre_tokenized_text]for pair, merge in merges.items():for idx, split in enumerate(splits):i = 0while i < len(split) - 1:if split[i] == pair[0] and split[i + 1] == pair[1]:split = split[:i] + [merge] + split[i + 2 :]else:i += 1splits[idx] = splitreturn sum(splits, [])
3. 参考材料
【1】Summary of the tokenizers
【2】Byte-Pair Encoding tokenization
【3】RUC AI BOX 大预言模型
相关文章:
【大模型实战篇】大模型分词算法BPE(Byte-Pair Encoding tokenization)及代码示例
词元化是针对自然语言处理任务的数据预处理中一个重要步骤,目的是将原始文本切分成模型可以识别和处理的词元序列。在大模型训练任务中,就是作为大模型的输入。传统的自然语言处理方法,如基于条件随机场的序列标注,主要采用基于词…...
低功耗4G模组LCD应用示例超全教程!不会的小伙伴看这篇就够了!
希望大家通过本文的介绍,学会LCD显示屏与Air780E开发板结合使用的方法。利用LCD显示屏,你可以为你的项目增加丰富的显示内容,提升用户体验。记住,实践出真知,赶快动手尝试吧!相信这篇教程对你有所帮助~ 本文…...
Java while语句练习 C语言的函数递归
1. /* public static void main(String[] args) {int[] arr {25, 24, 12, 98, 36, 45};int max arr[0];//不能写0for (int i 1; i < arr.length; i) {if (arr[i] > max) {max arr[i];}}System.out.println(max);}*//*public static void main(String[] args) {doubl…...
illustrator免费插件 截图识别文字插件 textOCR
随手可得的截图识别文字插件 textOCR,识别出来的文字可直接输入到illustrator的当前文档中: 执行条件 1、需截图软件支持,推荐笔记截图工具 2、截好图片直接拖入面板即可完成识别 ****后期可完成实现在illustrator选择图片对象完成文字识别。…...
提升数据管理效率:ETLCloud与达梦数据库的完美集成
达梦数据库的核心优势在于其强大的数据处理能力和高可用性设计。它采用先进的并行处理技术,支持大规模的数据操作,同时具备出色的事务处理能力和数据安全保障。此外,达梦数据库还提供了丰富的功能模块,如数据备份、恢复、监控等&a…...
头歌——人工智能(搜索策略)
文章目录 第1关:搜索策略第2关:盲目搜索第3关:启发式搜索 - 扫地机器人最短路径搜索第4关:搜索算法应用 - 四皇后问题 第1关:搜索策略 什么是搜索技术 人类的思维过程可以看作是一个搜索过程。从小学到现在࿰…...
gorm.io/sharding改造:赋能单表,灵活支持多分表策略(下)
背景 分表组件改造的背景,我在这篇文章《gorm.io/sharding改造:赋能单表,灵活支持多分表策略(上)》中已经做了详细的介绍——这个组件不支持单表多个分表策略,为了突破这个限制做的改造。 在上一篇文章中&…...
域渗透AD渗透攻击利用 MS14-068漏洞利用过程 以及域渗透中票据是什么 如何利用
目录 wmi协议远程执行 ptt票据传递使用 命令传递方式 明文口令传递 hash口令传递 票据分类 kerberos认证的简述流程 PTT攻击的过程 MS14-068 漏洞 执行过程 wmi协议远程执行 wmi服务是比smb服务高级一些的,在日志中是找不到痕迹的,但是这个主…...
C++进阶-->继承(inheritance)
1. 继承的概念及定义 1.1 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要手段,他允许我们在保证原有类的特性基础上还进行扩展,通过继承产生的类叫做派生类(子类),被继承的类叫做基类&a…...
可视化项目 gis 资源复用思路(cesium)
文章目录 可视化项目 gis 资源复用思路底图、模型替换思路具体操作 可视化项目 gis 资源复用思路 背景: A项目的底图、模型 是现在在做的 B项目所需要的,现在要把 B项目的底图之类的替换成 A系统的 底图、模型替换思路 观察可访问系统的 gis 相关网络请…...
SQL实战测试
SQL实战测试 (请写下 SQL 查询语句,不需要展示结果) 表 a DateSalesCustomerRevenue2019/1/1张三A102019/1/5张三A18 1. **用一条 ** SQL 语句写出每个月,每个销售有多少个客户收入多少 输出结果表头为“月”,“销…...
Java 基础教学:基础语法-变量与常量
变量 变量是程序设计中的基本概念,它用于存储信息,这些信息可以在程序执行过程中被读取和修改。 变量的声明 在Java中,声明变量需要指定变量的数据类型以及变量的名称。数据类型定义了变量可以存储的数据种类(例如整数、浮点数…...
vue3使用element-plus手动更改url后is-active和菜单的focus颜色不同步问题
在实习,给了个需求做个新的ui界面,遇到了一个非常烦人的问题 如下,手动修改url时,is-active和focus颜色不同步 虽然可以直接让el-menu-item:focus为白色能解决这个问题,但是我就是想要有颜色哈哈哈,有些执…...
每天五分钟深度学习框架pytorch:从底层实现一元线性回归模型
本文重点 本节课程我们继续搭建一元线性回归模型,不同的是这里我们不使用pytorch框架已经封装好的一些东西,我们做这个目的是为了更加清楚的看到pytorch搭建模型的本质,为了更好的理解,当然实际中我们还是使用pytorch封装好的一些东西,不要重复造轮子。 模型搭建 #定义…...
编辑器加载与AB包加载组合
解释: 这个 ABResMgr 类是一个资源加载管理器,它用于整合 AB包(Asset Bundle)资源加载和 编辑器模式资源加载。通过这个管理器,可以根据开发环境选择资源加载方式,既支持 运行时使用Asset Bundle加载&…...
【c++】vector中的back()函数
nums.back() 是 C 中 std::vector 类的一个成员函数,用于获取数组(向量)中的最后一个元素。以下是一些关于 nums.back() 的详细解释和示例使用: 1. 功能 nums.back() 返回数组 nums 中的最后一个元素。如果数组为空,…...
[分享] SQL在线编辑工具(好用)
在线SQL编写工具(无广告) - 在线SQL编写工具 - Web SQL - SQL在线编辑格式化 - WGCLOUD...
element-ui隐藏表单必填星号
// 必填星号在前显示 去掉 .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label:before { content: !important; margin-right: 0px!important; } // 必填星号在结尾显示 .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__labe…...
自动驾驶系列—激光雷达点云数据在自动驾驶场景中的深度应用
🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…...
C#删除dataGridView 选中行
关键在于:从最后一行开始删除。 从前往后删只能删除其中一半,我理解是再remove行的时候dataGridView内部行序列发生了变化,包含在选中行中的特定行会被忽略,从后往前删就可避免这个问题,最后一行的行号影响不到前面的…...
K8S调度不平衡问题分析过程和解决方案
不平衡问题排查 问题描述: 1、业务部署大量pod(据反馈,基本为任务型进程)过程中,k8s node内存使用率表现不均衡,范围从80%到百分之几; 2、单个node内存使用率超过95%,仍未发生pod驱逐,存在node…...
Python中类、继承和方法重写的使用
😀前言 本篇博文将介绍如何定义类、创建类的实例、访问类的成员、使用属性、实现继承及方法重写,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以…...
【Neo4j】- 轻松入门图数据库
文章目录 前言-场景一、Neo4j概述二、软件安装部署1.软件下载2.软件部署3.软件使用4.语法学习 总结 前言-场景 这里用大家都了解的关系数据与图数据据库对比着说,更加方便大家理解图数据库的作用 图形数据库和关系数据库均存储信息并表示数据之间的关系。但是,关系…...
LeetCode 206 - 反转链表
解题思路 我们可以使用迭代的方法来实现链表的反转,这里我们先介绍迭代的方法。迭代的思路是:从头节点开始,依次将节点的next指针进行反转,使得当前节点的next指向其前一个节点,然后依次向后移动指针,直至…...
AI生成大片,Movie Gen 可以生成长视频并配上完美的音效,带给观众更好的观看体验。
之前的文章中已经给大家介绍了一些关于长视频生成相关的技术,AI生成大片已经越来越近了。感兴趣的小伙伴可以点击下面链接阅读~ Movie Gen 的工作原理可以简单理解为两个主要部分:一个是生成视频的模型,另一个是生成音频的模型。首先&#x…...
Flink on yarn模式下,JobManager异常退出问题
这个问题排除了很久,其中更换了Flink版本,也更换了Hadoop版本一直无法解决,JobManager跑着跑着就异常退出了。资源管理器上是提示运行结束,运行状态是被Kill掉。 网上搜了一圈,都说内存不足、资源不足,配置…...
面对AI算力需求激增,如何守护数据中心机房安全?
随着人工智能(AI)技术飞速发展,AI算力需求呈现爆发式增长,导致对数据设备电力的需求指数级攀升。这给数据中心带来前所未有的挑战和机遇,从提供稳定的电力供应、优化高密度的部署,到数据安全的隐私保护&…...
Connection --- 连接管理模块
目录 模块设计 模块实现 shared_from_this 模块测试纠错 模块设计 Connection模块是对通信连接也就是通信套接字的整体的管理模块,对连接的所有操作都是通过这个模块提供的接口来完成的。 那么他具体要进行哪些方面的管理呢? 首先每个通信连接都需…...
iconfont图标放置在某个元素的最右边
在网页设计中,如果你想要将iconfont图标放置在某个元素的最右边,你可以通过CSS来实现这个布局。以下是一些基本的CSS代码示例,它们可以帮助你根据不同的布局需求将图标放置在最右边: 内联元素(如<span>ÿ…...
Android10 recent键相关总结
目录 初始化流程 点击Recent键流程 RecentsActivity 显示流程 RecentsModel 获取数据管理类 RecentsActivity 布局 已处于Recent界面时 点击recent 空白区域 点击返回键 recent组件配置 Android10 Recent 功能由 System UI,Launcher共同实现。 初始化流程 …...
商标查询官方入口/免费优化网站
1、打 开 新 标 签 页启动 Vim 时用 "vim -p filename ...":tabe[dit]:tabnew 在当前标签页之后打开带空窗口的新标签页。:tabe[dit] [opt] [cmd]:tabnew [opt] [cmd]打开新标签页并编辑 ,其余和 |:edit| 类同。:tabf[ind] [opt] [cmd]打开新标签…...
福建建设执业资格注册管理中心网站/在线超级外链工具
质量是衡量一个软件是否成功的关键要素。而对于商业软件系统,尤其是企业应用软件系统来说,除了软件运行质量、文档质量以外,代码的质量也是非常重要的。软件开发进行到编码阶段的时候,最大的风险就在于如何保证代码的易读性和一致…...
php网站服务器/友情链接的获取途径有哪些
GET & POST GET GET的语义是获取指定URL的资源将数据按照variablevalue的形式,添加到action所指向的URL后面,并且两者使用"?"连接,各变量之间使用"&"连接貌似不安全,因为在传输过程中,数…...
商品网站做推广/当阳seo外包
Sabayon是一份自启动运行DVD,它被设计为能在5分钟以内使一台电脑进入强大的Gentoo Linux系统。Gentoo Linux是一份Linux发行,它由软件安装管理引擎Portage来驱动。除了作为自启动运行DVD使用,Sabayon Linux也能安装到硬盘上,实际上…...
深圳网站建设方案优化/北京百度seo排名点击器
效率好低,,,, 今天一天没有吧区间dp结束, 好吧,今晚加把劲,争取结束, 继续努力吧, 看博客, 。...
php动态网站开发视频教程/河南网站建设定制
先要做准备工作 先下载DS_Dictionary.h和Ds_Dictionary.cpp,不多说提供下载地址http://www.cocos2d-x.org/boards/6/topics/6125?r13203#message-13203文件基于pugixml下面是下载地址http://pugixml.org/下面提供test.plist作对照 <?xml version"1.0" encoding&…...