tokenizer简述

651137632ddc16946a083bdabac1d683.png

知乎:难赋
链接:https://zhuanlan.zhihu.com/p/721054525

简述

为了方便计算机处理文本,我们常把文本转化为数值的形式。具体操作是把文本分割成有意义的片段,再把这些片段映射为数组,就能够利用各种深度学习的技术来处理文本了。把文本分割成有意义的片段这一过程称为tokenize,片段称为token。我们可以发现,token是计算机处理文本的基本单位。

tokenize是一个复杂的问题,针对不同的情况出现了很多的算法。人力资源是非常昂贵的,程序员是一群喜欢自动化的人。因此我们在处理这个问题时首先回答了一个这样的问题:能否采用某种无监督的方式,通过某种算法将连续的文本自动地转化为token?

回答完这个问题后,人们把tokenize的过程分为以下几个步骤:

  1. 把训练文本中的所有字符作为初始token

  2. 根据某种规则把联系紧密的token对合并为更高阶的token,这一步我们有时称之为训练

  3. 重复第2步,直到满足某种限制条件(如词汇表达到限额)

之后我们可以利用最终的词汇表进行tokenize和detokenize。

接下来,我们根据huggingface的开源库来介绍常用的tokenize方法。

huggingface

huggingface关于tokenize有两个主要的文件:tokenizers库和transformers里的基类。

  • tokenizers库提供了tokenizer的定义、训练、使用等代码。

  • transformers提供了预训练模型中使用的tokenizer的实现以及包含共有方法的基类。

这两处的代码比较独立。

tokenizer

这部分我们会介绍tokenizers库的使用和自定义。

我们可以通过传入vocab.txt文件来初始化tokenizer或者采用from_pretrained方法加载云端的预训练tokenizer。

from tokenizers import Tokenizertokenizer = Tokenizer.from_pretrained("bert-base-uncased")

或者

from tokenizers import BertWordPieceTokenizertokenizer = BertWordPieceTokenizer("bert-base-uncased-vocab.txt", lowercase=True)

这个库把tokenize的过程分为四个步骤:

  1. Normalization

    让字符串变得不那么杂乱,使其规范化。主要处理编码层面的一些事情,如 https://unicode.org/reports/tr15 是最常实现的一个normalization。

  2. Pre-tokenization

    把字符串分割为word,也即保证token的范围为:char ≤ token ≤ word,防止出现token大于word的情况(否则I'm可能分不开)。

  3. Model

    用于实现str->token的学习过程。常用的有:

    详见模型小节。

  • models.BPE

  • models.Unigram

  • models.WordLevel

  • models.WordPiece

1.Post-processing

用于添加特殊的token等,如[UNK][PAD]

这里给出一份tokenizer的训练代码:

from tokenizers import Tokenizer
from tokenizers.models import WordPiecebert_tokenizer = Tokenizer(WordPiece(unk_token="[UNK]"))from tokenizers import normalizers
from tokenizers.normalizers import NFD, Lowercase, StripAccentsbert_tokenizer.normalizer = normalizers.Sequence([NFD(), Lowercase(), StripAccents()])from tokenizers.pre_tokenizers import Whitespacebert_tokenizer.pre_tokenizer = Whitespace()from tokenizers.processors import TemplateProcessingbert_tokenizer.post_processor = TemplateProcessing(single="[CLS] $A [SEP]",pair="[CLS] $A [SEP] $B:1 [SEP]:1",special_tokens=[("[CLS]", 1),("[SEP]", 2),],
)from tokenizers.trainers import WordPieceTrainertrainer = WordPieceTrainer(vocab_size=30522, special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"]
)
files = [f"data/wikitext-103-raw/wiki.{split}.raw"for split in ["test", "train", "valid"]
]
bert_tokenizer.train(files, trainer)
bert_tokenizer.save("data/bert-wiki.json")

模型

WordPiece(2016)

来自:Google's Neural Machine Translation System。BERT之后进入大众视野。未开源训练代码,开源分词代码。

  1. 准备模型的训练语料

  2. 确定「期望的词表大小」

  3. 将训练语料中的所有单词拆分为字符,这些字符作为初始的词表

  4. 统计训练语料中紧挨的token对的分数,选取最高的进行合并ead64880f116f00dab772c8281942824.png

  5. 重复第4步,直到词表大小达到我们设定的期望或者剩下的字节对出现频率最高为1

编码方式采用字典树按最长优先进行匹配。

BPE(GPT2,2019)
  1. 准备模型的训练语料

  2. 确定「期望的词表大小」

  3. 将训练语料中的所有单词拆分为字符,这些字符作为初始的词表

  4. 统计训练语料中紧挨的token对出现的频率,「选择出现频率最高的token对合并成新的subword,并更新词表」,把被合并的token对加入合并规则表

  5. 重复第4步,直到词表大小达到我们设定的期望或者剩下的字节对出现频率最高为1

编码方式:

把字符串按字符拆分,按照合并规则表进行合并。

transformers

transformers库中关于分词由三个文件组成:tokenization_utils.pytokenization_utils_base.pytokenization_utils_fast.py。其中tokenization_utils_fast.py为Rust的快速实现版本,与tokenization_utils.py的接口几乎没区别。接下来我们梳理一下这几个文件。

tokenization_utils_base.py

这个文件主要实现 PreTrainedTokenizer 的基类。

  • class BatchEncoding(UserDict)

    PreTrainedTokenizerBase输出对象,tokenizer进行str->token处理时会以这个对象的形式返回结果。处理chartokenwordsentence的相互转化。

    >>> type(tokenizer(["1!"]))
    transformers.tokenization_utils_base.BatchEncoding
  • class SpecialTokensMixin

    以model独立的方式处理特殊token。

  • class PreTrainedTokenizerBase(SpecialTokensMixin, PushToHubMixin)

    PreTrainedTokenizerPreTrainedTokenizerFast的公有方法。主要涉及:

    • chat模板、预训练模型加载与保存、tokenize(未实现,str->[id])、encodestr->[id])、__call__tokenizeprepare方法)、paddingprepare_for_model(处理[id]以供model使用)、truncate_sequencesconvert_tokens_to_string(未实现)、batch_decodedecodeget_special_tokens_maskprepare_seq2seq_batch

tokenization_utils.py
  • class Trie

    首先,文件实现了一个python版本的前缀树。

    Trie(发音为 "try")是一种特殊的数据结构,也称为前缀树(Prefix Tree)或字典树(Digital Tree)。它是一种有序树,用于存储动态集合或关联数组,其中键通常是字符串。Trie 树的主要特点是它能够高效地进行字符串的插入、查找和前缀匹配操作。

    Trie 树的主要特点:

    支持以下方法:

    • add:向里面增加word。

    • split:把句子分割为word列表。

    • cut_text:内部方法,用于实际的分割操作。

    • 每个节点包含一个字符。

    • 每个节点可以有多个子节点,每个子节点代表一个可能的字符。

    • 根节点通常不包含字符,从根节点到某个节点的路径上的字符序列表示一个字符串。

  • class ExtensionsTrie(Trie)

    扩展以下方法:

    • extensions:获取指定前缀的所有单词。

PreTrainedTokenizer(PreTrainedTokenizerBase)

实现tokenizer的共有方法。

以下是 PreTrainedTokenizer 类的公共方法的表格,仅包含方法名和描述:

方法名(带*的表示需要实现)描述
is_fast返回一个布尔值,表示当前的 Tokenizer 是否是快速版本。
vocab_size*返回基础词汇表的大小(不包括添加的标记)。
added_tokens_encoder返回从字符串到索引的排序映射。
added_tokens_decoder返回添加的标记在词汇表中的字典,索引到 AddedToken。
get_added_vocab返回添加的标记在词汇表中的字典,标记到索引。
__len__返回完整词汇表的大小(包括添加的标记)。
num_special_tokens_to_add返回在编码序列时添加的特殊标记的数量。
tokenize将字符串转换为标记序列,使用 Tokenizer。
_tokenize*将字符串转换为标记序列,使用 Tokenizer。不考虑添加的token。
convert_tokens_to_ids将标记字符串(或标记序列)转换为单个整数 ID(或 ID 序列),使用词汇表。
_convert_tokens_to_ids*将标记字符串(或标记序列)转换为单个整数 ID(或 ID 序列),使用词汇表。
_encode_plus对输入文本进行编码,并返回包含编码结果的字典。
_batch_encode_plus对一批输入文本进行编码,并返回包含编码结果的字典。
prepare_for_tokenization在 Tokenization 之前执行任何必要的转换。
get_special_tokens_mask从没有添加特殊标记的标记列表中检索序列 ID。
convert_ids_to_tokens使用词汇表和添加的标记将单个索引或索引序列转换为标记或标记序列。
_convert_id_to_token*将单个 ID 转换为对应的 token。
convert_tokens_to_string将标记列表转换为字符串。
_decode将标记 ID 列表解码为字符串。

我们实现自己的tokenizer需要实现的抽象方法:

PreTrainedTokenizer

  • vocab_size*

  • _tokenize*

  • _convert_tokens_to_ids*

  • _convert_token_to_id*

  • _convert_id_to_token*

PreTrainedTokenizerBase

  • get_vocab(返回词汇表作为token到索引的字典)。

最简实现
class miniTokenizer(PreTrainedTokenizer):def __init__(self,vocab_file,unk_token="[UNK]",sep_token="[SEP]",pad_token="[PAD]",cls_token="[CLS]",mask_token="[MASK]",):self.vocab_file = vocab_filewith open(vocab_file, "r", encoding="utf-8") as f:self.vocab = f.read().split("\n")  # id2tokenself.vocab_size_ = len(self.vocab)self.token2id = {token: id_ for id_, token in enumerate(self.vocab)}super().__init__(unk_token=unk_token,sep_token=sep_token,pad_token=pad_token,cls_token=cls_token,mask_token=mask_token,)def vocab_size(self) -> int:return self.vocab_size_def _tokenize(self, text, **kwargs):return list(text)def _convert_tokens_to_ids(self, tokens):return [self.token2id.get(token, self.token2id[self.unk_token]) for token in tokens]def _convert_token_to_id(self, token):return self.token2id.get(token, self.token2id[self.unk_token])def _convert_id_to_token(self, id_):return self.vocab[id_]def get_vocab(self):return self.token2idtokenizer = miniTokenizer("vocab.txt")
tokenizer(["1!123"])  # {'input_ids': [[1, 6, 1, 2, 3]], 'token_type_ids': [[0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1]]}

vocab.txt内容:

0
1
2
3
4
)
!
@
#
$
123

备注:昵称-学校/公司-方向/会议(eg.ACL),进入技术/投稿群

57fece1ccdc79276955f61faeea249ae.png

id:DLNLPer,记得备注呦

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

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

相关文章

FastStone Capture屏幕长截图软件注册码

FastStone Capture是一款功能强大的电脑屏幕截图、录像软件,并支持图像编辑、注释及分享等使用功能。FastStone Capture可以免费用30天试用,终身版88元单台电脑终身使用,终身更新。不过网上分享的FastStone Capture注册码似乎也可以正常激活&…

Java开发:文件上传和下载

一、文件上传 使用MultipartFile 类型接收参数; 调用上传有两种方式: 方式一:使用curl命令 curl -F "file/data/filename.txt" http://localhost:8080/upload --verbose方式二:使用html,写一个form表单&…

Mysql基本理解

系列文章目录 Mysql的基础理论知识 目录 系列文章目录 文章目录 一、数据库概述 1.数据库概念 2.数据库的作用 3.什么是关系型数据库? 4.Mysql的优点 5.数据库术语 6.SQL语言分类 二、Mysql安装 三、 Mysql使用 1.登录数据库、退出登录 2.创建、列出数据库 3.选择…

Node.JS有什么用?给谁用?怎么学?通俗易懂,超级详细!

现在,nodejs主要是前端的小伙伴来用的。前端小伙伴也不用说去怎么学node,而是把node当做是一个环境。我们利用这个环境去搭建上层的一些应用,去使用一些工具。就像学习Windows一样,我们没有必要深入了解Windows的每一个细节&#…

【hot100-java】【环形链表 II】

印象题 /*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public ListNode detectCycle(ListNode head) {ListNode fasthea…

建筑工程系列专业职称评审条件大全

我们都知道,职称是分很多系列,今天甘建二主要是从建筑工程系列讲起来,从技术员到初级职称再到中级职称然后到高级职称,各个等级的评审条件给您一一解析,赶紧收藏起来。 ✨技术员1️⃣理工类或建筑工程相关专业大学专科…

视频生成技术分享

文本到视频(T2V)生成是一种技术,它通过将文本描述转换为视频内容,允许用户根据自然语言生成动态视觉媒体。近年来,扩散模型在这一领域取得了显著进展,但现有模型在处理多个对象和复杂场景时,面临…

android 跑了一个网易云信v1.0的app, 编译的过程中报错Entry name ‘assets/sm2/r.jks‘ collided的处理

1、一开始并没有报这个错误,然后直接就不知道注了什么信息以后,就报错,是因为下面的warning: 2、然后编译的时候就直接报下面的错误: 3、然后我们再之前的注解放开: 这样一切就正常了。 4、那么这个究竟是…

【动态规划】(五)动态规划——子序列问题

动态规划——子序列问题 子序列问题☆ 最长递增子序列(离散)最长连续递增序列(连续)最大子序和(连续)最长重复子数组(连续)☆ 最长公共子序列(离散-编辑距离过渡&#xf…

【动态规划】(四)动态规划——打家劫舍与买卖股票

打家劫舍与买卖股票 打家劫舍问题打家劫舍打家劫舍II打家劫舍III 买卖股票问题买卖股票的最佳时机买卖股票的最佳时机II买卖股票的最佳时机III买卖股票的最佳时机IV最佳买卖股票时机含冷冻期买卖股票的最佳时机含手续费 股票问题总结 打家劫舍问题 给定一个数组,相…

day-59 两两交换链表中的节点

思路 只需将链表两两交换节点即可,如果是奇数个节点,最后一个节点则不用交换 解题过程 可以先自定义一个头结点thead,这样更便于思考交换,最后返回thead.next即可 Code /*** Definition for singly-linked list.* public class…

SAM+无监督学习!能发顶会的高端局组合!idea效果绝佳

学过SAM的朋友都知道,SAM需要对训练数据进行全面的手动标记,每张图像都要超过20分钟...效率有待提升。那么如何解决这个短板?我们考虑SAM无监督学习。 这是因为无监督学习具有无需人工标注数据的特点,通过将两者结合,…

【LeetCode】动态规划—删除并获得点数(附完整Python/C++代码)

动态规划—#740. 删除并获得点数 前言题目描述基本思路1. 问题定义:2. 理解问题和递推关系:3. 解决方法:4. 进一步优化:5. 小总结: 代码实现Python3代码实现Python 代码解释C代码实现C 代码解释 总结: 前言 给你一个整数数组 n u m s nums nums ,你可以对它进行一…

DownShift: Tuning Shift Reduction With Reliability for Racetrack Memories

目录 DownShift: Tuning Shift Reduction With Reliability for Racetrack Memories文章摘要:文章的主要贡献包括:文章的结构如下:DownShiftDownShift通过以下方式改进了现有的数据放置策略: GROGU(Generating Reliabi…

2024最受欢迎的3款|数据库管理和开发|工具

1.SQLynx(原SQL Studio) 概述: SQLynx是一个原生基于Web的SQL编辑器,由北京麦聪软件有限公司开发。它最初被称为SQL Studio,后改名为SQLynx,支持企业的桌面和Web数据库管理。SQLynx支持所有流行的数据库&a…

工业一体机实现接口与模块选配

在现代工业自动化和智能制造的浪潮中,工业一体机因其集成化、稳定性高和适应性强的特性而逐渐成为企业生产过程中不可或缺的设备。为了满足不同客户的需求,工业一体机的接口与模块选配功能显得尤为重要。 一、工业一体机的基本概念 工业一体机是将计算、…

跟着B战学习JAVA面试八股文

学习链接:https://www.bilibili.com/video/BV1gm411S7EX/?spm_id_from333.337.search-card.all.click&vd_sourceefbaa07876b231ae3225ba8999116807 创建线程的几种方式? 继承Thread类实现Runnable接口实现Callable接口通过线程池来创建线程 为什么…

【官方Mamba库】原理简述和代码解析

目录 1 代码原理简述1.1 原始结构——SSM1.2 结构改进——S4(Structured State Space for Sequences)1.2.1 离散化1.2.2HiPPO 1.3 最终版本——Mamba(又称S6或selective SSMs) 2 代码库目录结构2.1 mamba_simple.py主体结构2.1.1 …

OLED(2)驱动篇

文章目录 1 概述2 代码简述2.1 OLED 对象2.2 OLEDProtocol 对象2.3 OLEDFont 对象 3 成果展示 1 概述 1)代码仓库:这里尝试了两种面向对象的方式,不足之处敬请指正。 OOP 方式:https://gitee.com/luyaocf/demo-jlc_stm32f407_oop.…

Unity 设计模式 之 行为型模式-【命令模式】【责任链模式】

Unity 设计模式 之 行为型模式-【命令模式】【责任链模式】 目录 Unity 设计模式 之 行为型模式-【命令模式】【责任链模式】 一、简单介绍 二、命令模式(Command Pattern) 1、什么时候使用命令模式 2、使用命令模式的好处 3、使用时的注意事项 三…