【Pytorch神经网络理论篇】 40 Transformers中的词表工具Tokenizer

简介: 在Transformers库中,提供了一个通用的词表工具Tokenizer,该工具是用Rust编写的,其可以实现NLP任务中数据预处理环节的相关任务。

同学你好!本文章于2021年末编写,获得广泛的好评!

故在2022年末对本系列进行填充与更新,欢迎大家订阅最新的专栏,获取基于Pytorch1.10版本的理论代码(2023版)实现,


Pytorch深度学习·理论篇(2023版)目录地址为:


CSDN独家 | 全网首发 | Pytorch深度学习·理论篇(2023版)目录


本专栏将通过系统的深度学习实例,从可解释性的角度对深度学习的原理进行讲解与分析,通过将深度学习知识与Pytorch的高效结合,帮助各位新入门的读者理解深度学习各个模板之间的关系,这些均是在Pytorch上实现的,可以有效的结合当前各位研究生的研究方向,设计人工智能的各个领域,是经过一年时间打磨的精品专栏!

https://v9999.blog.csdn.net/article/details/127587345


欢迎大家订阅(2023版)理论篇

以下为2021版原文~~~~


46b55d3d9ec04e20ab427ba0221cc9b4.png


1 Tokenizer


在Transformers库中,提供了一个通用的词表工具Tokenizer,该工具是用Rust编写的,其可以实现NLP任务中数据预处理环节的相关任务。


17d3c877468a4a6f8b0281afa078b3f9.png


1.1 Tokenizer工具中的组件


在词表工具Tokenizer中,主要通过PreTrainedTokenizer类实现对外接口的使用。


1.1.1 Normaizer


对输入字符串进行规范化转换,如对文本进行小写转换、使用uni-code规范化。


1.1.2 PreTokenizer


对输入数据进行预处理,如基于字节空格、字符等级别对文本进'Madel:生成和使用子词的横型,如Wordlevel、BPE、WordPlece等模型。这部分是可训练的。


1.1.3 Post-Processor


对分词后的文本进行二次处理。例如,在BERT模型中,使用ssor为输入文本添加特殊字符(如[CLS]、[SEP]等)。


1.1.4 Dcoder


负责将标记化输入映射回原始字符串。


1.1.5 Trainer


为每个模型提供培训能力。


1.2 子词的拆分


词表工具将liyongle分成了[lI',yong','#le],使用子词的拆分技术可以防止NLP任务中,在覆盖大量词汇的同时,词表过大的问题。


1.2.1 子词的拆分原理


在进行NLP时,通过为每个不同词对应一个不同的向量,来完成文字到数值之间的转换,这个映射表被称作词表。


1.2.2 字词拆分优势


对于某些形态学丰富的语言(如德语,或是带有时态动词的英语),如果将每个变化的词都对应一个数值,则会导致词表过大的问题。而且这种方式使得两个词之间彼此独立,也不能体现出其本身的相近意思(如pad和padding)。


子词就是将一般的词,如padding分解成更小单元pad+ding。而这些小单元也有各自意思,同时这些小单元也能用到其他词中。子词与单词中的词根、词缀非常相似。通过将间分解成子词,可以大大降低模型的词汇量,减少运算量。


1.2.3 于统计方法实现的子词的分词方法


Byte Pair Encoding(BPE)法:统计频次,即先对语料统计出相邻符号对的频次,再根据频词进行融合。


WordPiece法:WordPiece法统计最大似然,是Google公司内部的子词包,其未对外公开。BERT最初用的就是WordPiece法分词。


Unigram Language Model法:先初始化一个大词表,接着通过语言模型评估不断减少词表,一直减少到限定词汇量。


1.2.4 使用模型训练的方法对子词进行拆分


在神经网络模型中,还可以使用模型训练的方法对子词进行拆分。常见的有子词正则和BPEDropout方法。二者相比,BPEDropout方法更为出色。


1.2.5 模型中使用子词


在模型的训练过程中,输入的句子是以子词形式存在的,这种方式得到的预测结果也是子词。


当使用模型进行预测时,模型输出子词之后,再将其合并成整词即可。例如,训练时先把liyongle分成了[lI',yong','##le'],获得结果后,将句子中的“##”去掉即可。


2 PreTrainedTokenizer类


2.1 PreTrainedTokenizer类中的特殊词


在PreTrainedTokenizer类中,将词分成了两部分:普通词与特殊词。其中特殊词是指用于标定句子的特殊标记,主要是在训练模型中使用


2.1.1 使用代码查看系统特殊词


import torch
from transformers import BertTokenizer, BertForMaskedLM
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
for tokerstr in tokenizer.SPECIAL_TOKENS_ATTRIBUTES:
    strto = "tokenizer." + tokerstr
    print(tokerstr, eval(strto))
# 获得标记词在词表中的索引值
print(“masktken”,tokenizer.mask_token,tokenizer.mask_token_id)
# 输出
输出:
bos_token None 
eos_token None
unk_token [UNK] # 未知标记
Using bos_token, but it is not set yet.
sep_token [SEP] # 句子结束标记
pad_token [PAD] # 填充标记
Using eos_token, but it is not set yet.
cls_token [CLS] # 开始标记
mask_token [MASK] # 遮蔽词标记
additional_special_tokens [] # 用于扩充使用,用户可以把自己的自定义特殊词添加到里面,可以对应多个标记,这些标记都会被放到列表中。获取该词对应的标记并不是一个,在获取对应索引值时,需要使用additional_special_tokens_ids属性。


2.2  PreTrainedTokenizer类中特殊词的使用方法


2.2.1 encode完整定义


def encode(self,
           text, # 第一个句子
           text_pair=None,  #第二个句子
           add_special_tokens=True,#是否添加特殊词,如果为False,则不会增加[CLS],[SEP]等标记词
           max_length=None, # #最大长度
           stride=0, #返回截断词的步长窗口,stride在encode方法中没有任何意义。该参数主要为兼容底层的encode_plus方法。在encode_plus方法中,会根据stride的设置来返回从较长句子中截断的词。
           truncation_strategy="longest_first", # 截断策略
            #截断策略:longest_first(默认值))当输入是2个句子的时候,从较长的那个句子开始处理对其进行截断,使其长度小于max_length参数。
            #截断策略:only_frst:只截断第一个句子。
            #截断策略:only_second:只截断第二个句子。
            #截断策略:dou not_truncate:不截断(如果输入句子的长度大于max_length参数,则会发生错误)。
           pad_to_max_length=False,#对长度不足的句子是否填充
           return_tensors=None, #是否返回张量类型,可以设置成"tf"或"pt",主要用于指定是否返回PyTorch或TensorFlow框架下的张量类型。如果不设置,默认为None,即返回Python中的列表类型。
           **kwargs
           )


2.2.2 代码实现:使用encode方法实现语句分词与分句


from transformers import BertTokenizer, BertForMaskedLM
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
# encode方法对每句话的开头和结尾都分别使用了[CLS]和[SEP]进行标记,并对其进行分词
one_toind = tokenizer.encode("Who is Li BiGor ?")#将第一句转化成向量
two_toind = tokenizer.encode("Li BiGor is a programmer")#将第二句转化成向量
# 在合并时,使用了two_toind[1:]将第二句的开头标记[CLS]去掉,表明两个句子属于一个段落。
all_toind = one_toind+two_toind[1:] #将两句合并
print(tokenizer.convert_ids_to_tokens(one_toind))
print(tokenizer.convert_ids_to_tokens(two_toind))
print(tokenizer.convert_ids_to_tokens(all_toind))
# 输出:
# ['[CLS]', 'who', 'is', 'li', 'big', '##or', '?', '[SEP]']
# ['[CLS]', 'li', 'big', '##or', 'is', 'a', 'programmer', '[SEP]']
# ['[CLS]', 'who', 'is', 'li', 'big', '##or', '?', '[SEP]', 'li', 'big', '##or', 'is', 'a', 'programmer', '[SEP]']


2.2.3 代码实现:使用encode方法实现语句的索引值填充


from transformers import BertTokenizer, BertForMaskedLM
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
# encode方法的参数max_length代表转换后的总长度.如果超过该长度,则会被截断。
# 如果小于该长度,并且参数pad_to_max_length为True时,则会对其进行填充。
padd_sequence_word = tokenizer.encode("Li BiGor is a man",max_length=10,pad_to_max_length=True)
print("padd_sequence_word:",padd_sequence_word)
# 输出:padd_sequence_word: [101, 5622, 2502, 2953, 2003, 1037, 2158, 102, 0, 0]


2.2.4 代码实现:使用encode方法实现语句的截断


from transformers import BertTokenizer, BertForMaskedLM
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
return_num = tokenizer.encode("Li BiGor is a man",max_length=5)
return_word = tokenizer.decode(return_num) # 使用decode将索引值转化为汉子
print("return_word:",return_word)
# 输出:return_word: [CLS] li bigor [SEP]


2.2.5 代码实现:使用encode_plus方法完成非填充部分的掩码标志,被截短词的附加信息


# encode_plus方法是PreTrainedTokenzer类中更为底层的方法。在调用encode方法时,最终也是通过encode_plus方法来实现的。
from transformers import BertTokenizer, BertForMaskedLM
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
# encode_plus方法输出了一个字典,字典中含有3个元素:
# input_jds:对句子处理后的词素引值,与encode方法输出的结果一致。
# token_type_ids:对两个句子中的词进行标识,属于第一个句子中的词用0表示,属于第二个句子中的词用1表示。
# attention_mask:表示非填充部分的掩码,非填充部分的词用1表示,填充部分的词用0表示。
padded_plus_toind = tokenizer.encode_plus("Li BiGor is a man",maxlength = 10,pad_to_max_length=True)
print("padded_plus_toind:",padded_plus_toind)
# 输出:padded_plus_toind: {'input_ids': [101, 5622, 2502, 2953, 2003, 1037, 2158, 102],
#                        'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0],
#                        'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1]
#                        }


2.2.5 代码实现:使用batch_encode_pus方法批处理语句


# batch_encode_pus方法同时处理两个句子,并输出了一个字典对象两个句子对应的处理结果被放在字典对象value的列表中。
from transformers import BertTokenizer, BertForMaskedLM
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
tokens = tokenizer.batch_encode_plus(["This is a sample","This is another longer sample text"],pad_to_max_length=True )
print(tokens)
# 输出:{'input_ids': [[101, 2023, 2003, 1037, 7099, 102, 0, 0], [101, 2023, 2003, 2178, 2936, 7099, 3793, 102]],
#     'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]],
#     'attention_mask': [[1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1]]}


3 向PreTrainedTokenizer类中添加词(普通词和特殊词)


3.1 方法定义


1.添加普通词:调用add_tokens方法,填入新词的字符串.


2.添加特殊词:调用add_Special_tokens方法,填入特殊词字典.


3.2 代码实现:向PreTrainedTokenizer类中添加词(普通词和特殊词)


from transformers import BertTokenizer, BertForMaskedLM
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
print("-------------------------添加特殊词前-------------------------")
print("特殊词列表",tokenizer.additional_special_tokens) # 特殊词列表 ['<#>']
print("特殊词索引值列表:",tokenizer.additional_special_tokens_ids) # 特殊词索引值列表: [30522]
toind = tokenizer.encode("<#> yes <#>")
print(tokenizer.convert_ids_to_tokens(toind))
 # 将索引词转化成字符串并输出 :['[CLS]', '<', '#', '>', 'yes', '<', '#', '>', '[SEP]']
print(len(tokenizer))# 输出词表总长度:30522
print("-------------------------添加特殊词后-------------------------")
special_tokens_dict = {'additional_special_tokens':["<#>"]}
tokenizer.add_special_tokens(special_tokens_dict)  # 添加特殊词
print("特殊词列表",tokenizer.additional_special_tokens) # 特殊词列表 []
print("特殊词索引值列表:",tokenizer.additional_special_tokens_ids) # 特殊词索引值列表: []
toind = tokenizer.encode("<#> yes <#>")
print(tokenizer.convert_ids_to_tokens(toind))  # tokenzer在分词时,没有将“<#>”字符拆开。
# 将索引词转化成字符串并输出 :['[CLS]', '<#>', 'yes', '<#>', '[SEP]']
print(len(tokenizer))   # 输出词表总长度:30523


目录
相关文章
|
2月前
|
监控 数据可视化 Java
VMware Aria Operations for Networks 6.14 - 网络和应用监控工具
VMware Aria Operations for Networks 6.14 - 网络和应用监控工具
72 0
VMware Aria Operations for Networks 6.14 - 网络和应用监控工具
|
7月前
|
机器学习/深度学习 计算机视觉 iOS开发
RT-DETR改进策略【模型轻量化】| 替换骨干网络 CVPR-2024 RepViT 轻量级的Vision Transformers架构
RT-DETR改进策略【模型轻量化】| 替换骨干网络 CVPR-2024 RepViT 轻量级的Vision Transformers架构
357 0
RT-DETR改进策略【模型轻量化】| 替换骨干网络 CVPR-2024 RepViT 轻量级的Vision Transformers架构
|
3月前
|
运维 监控 Linux
网络延迟监测工具选择(第一篇)
**WGCLOUD**是一款开源免费的跨平台运维监控工具,支持Windows、Linux、MacOS等系统,具备网络延迟监测功能。其内置的**PING监测**模块可实时ping目标IP,图形化展示延迟趋势,并在目标IP不可达时发送告警通知。支持分组管理,操作简单便捷,适合运维人员高效监控网络状态。
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
基于Pytorch 在昇腾上实现GCN图神经网络
本文详细讲解了如何在昇腾平台上使用PyTorch实现图神经网络(GCN)对Cora数据集进行分类训练。内容涵盖GCN背景、模型特点、网络架构剖析及实战分析。GCN通过聚合邻居节点信息实现“卷积”操作,适用于非欧氏结构数据。文章以两层GCN模型为例,结合Cora数据集(2708篇科学出版物,1433个特征,7种类别),展示了从数据加载到模型训练的完整流程。实验在NPU上运行,设置200个epoch,最终测试准确率达0.8040,内存占用约167M。
基于Pytorch 在昇腾上实现GCN图神经网络
|
4月前
|
机器学习/深度学习 算法 PyTorch
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
深度学习近年来在多个领域取得了显著进展,但其核心组件——人工神经元和反向传播算法自提出以来鲜有根本性突破。穿孔反向传播(Perforated Backpropagation)技术通过引入“树突”机制,模仿生物神经元的计算能力,实现了对传统神经元的增强。该技术利用基于协方差的损失函数训练树突节点,使其能够识别神经元分类中的异常模式,从而提升整体网络性能。实验表明,该方法不仅可提高模型精度(如BERT模型准确率提升3%-17%),还能实现高效模型压缩(参数减少44%而无性能损失)。这一革新为深度学习的基础构建模块带来了新的可能性,尤其适用于边缘设备和大规模模型优化场景。
135 16
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
|
7月前
|
机器学习/深度学习 数据可视化 算法
PyTorch生态系统中的连续深度学习:使用Torchdyn实现连续时间神经网络
神经常微分方程(Neural ODEs)是深度学习领域的创新模型,将神经网络的离散变换扩展为连续时间动力系统。本文基于Torchdyn库介绍Neural ODE的实现与训练方法,涵盖数据集构建、模型构建、基于PyTorch Lightning的训练及实验结果可视化等内容。Torchdyn支持多种数值求解算法和高级特性,适用于生成模型、时间序列分析等领域。
354 77
PyTorch生态系统中的连续深度学习:使用Torchdyn实现连续时间神经网络
|
4月前
|
机器学习/深度学习 搜索推荐 PyTorch
基于昇腾用PyTorch实现CTR模型DIN(Deep interest Netwok)网络
本文详细讲解了如何在昇腾平台上使用PyTorch训练推荐系统中的经典模型DIN(Deep Interest Network)。主要内容包括:DIN网络的创新点与架构剖析、Activation Unit和Attention模块的实现、Amazon-book数据集的介绍与预处理、模型训练过程定义及性能评估。通过实战演示,利用Amazon-book数据集训练DIN模型,最终评估其点击率预测性能。文中还提供了代码示例,帮助读者更好地理解每个步骤的实现细节。
|
4月前
|
机器学习/深度学习 自然语言处理 PyTorch
基于Pytorch Gemotric在昇腾上实现GAT图神经网络
本实验基于昇腾平台,使用PyTorch实现图神经网络GAT(Graph Attention Networks)在Pubmed数据集上的分类任务。内容涵盖GAT网络的创新点分析、图注意力机制原理、多头注意力机制详解以及模型代码实战。实验通过两层GAT网络对Pubmed数据集进行训练,验证模型性能,并展示NPU上的内存使用情况。最终,模型在测试集上达到约36.60%的准确率。
|
4月前
|
算法 PyTorch 算法框架/工具
PyTorch 实现FCN网络用于图像语义分割
本文详细讲解了在昇腾平台上使用PyTorch实现FCN(Fully Convolutional Networks)网络在VOC2012数据集上的训练过程。内容涵盖FCN的创新点分析、网络架构解析、代码实现以及端到端训练流程。重点包括全卷积结构替换全连接层、多尺度特征融合、跳跃连接和反卷积操作等技术细节。通过定义VOCSegDataset类处理数据集,构建FCN8s模型并完成训练与测试。实验结果展示了模型在图像分割任务中的应用效果,同时提供了内存使用优化的参考。
|
4月前
|
机器学习/深度学习 算法 PyTorch
基于Pytorch Gemotric在昇腾上实现GraphSage图神经网络
本实验基于PyTorch Geometric,在昇腾平台上实现GraphSAGE图神经网络,使用CiteSeer数据集进行分类训练。内容涵盖GraphSAGE的创新点、算法原理、网络架构及实战分析。GraphSAGE通过采样和聚合节点邻居特征,支持归纳式学习,适用于未见节点的表征生成。实验包括模型搭建、训练与验证,并在NPU上运行,最终测试准确率达0.665。

热门文章

最新文章

推荐镜像

更多