类似凡科建站的网站,wordpress dux主题会员中心,iis架设网站教程,贵州软件制作同学你好#xff01;本文章于2021年末编写#xff0c;获得广泛的好评#xff01;
故在2022年末对本系列进行填充与更新#xff0c;欢迎大家订阅最新的专栏#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现#xff0c;
Pytorch深度学习理论篇(2023版)目录地址…
同学你好本文章于2021年末编写获得广泛的好评
故在2022年末对本系列进行填充与更新欢迎大家订阅最新的专栏获取基于Pytorch1.10版本的理论代码(2023版)实现
Pytorch深度学习·理论篇(2023版)目录地址为
CSDN独家 | 全网首发 | Pytorch深度学习·理论篇(2023版)目录本专栏将通过系统的深度学习实例从可解释性的角度对深度学习的原理进行讲解与分析通过将深度学习知识与Pytorch的高效结合帮助各位新入门的读者理解深度学习各个模板之间的关系这些均是在Pytorch上实现的可以有效的结合当前各位研究生的研究方向设计人工智能的各个领域是经过一年时间打磨的精品专栏https://v9999.blog.csdn.net/article/details/127587345欢迎大家订阅(2023版)理论篇 以下为2021版原文~~~~ 1 Tokenizer
在Transformers库中提供了一个通用的词表工具Tokenizer该工具是用Rust编写的其可以实现NLP任务中数据预处理环节的相关任务。 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分成了[lIyong#le]使用子词的拆分技术可以防止NLP任务中在覆盖大量词汇的同时词表过大的问题。
1.2.1 子词的拆分原理
在进行NLP时通过为每个不同词对应一个不同的向量来完成文字到数值之间的转换这个映射表被称作词表。
1.2.2 字词拆分优势
对于某些形态学丰富的语言如德语或是带有时态动词的英语)如果将每个变化的词都对应一个数值则会导致词表过大的问题。而且这种方式使得两个词之间彼此独立也不能体现出其本身的相近意思如pad和padding)。
子词就是将一般的词如padding分解成更小单元padding。而这些小单元也有各自意思同时这些小单元也能用到其他词中。子词与单词中的词根、词缀非常相似。通过将间分解成子词可以大大降低模型的词汇量减少运算量。
1.2.3 于统计方法实现的子词的分词方法
Byte Pair Encoding(BPE)法统计频次即先对语料统计出相邻符号对的频次再根据频词进行融合。
WordPiece法WordPiece法统计最大似然是Google公司内部的子词包其未对外公开。BERT最初用的就是WordPiece法分词。
Unigram Language Model法先初始化一个大词表接着通过语言模型评估不断减少词表一直减少到限定词汇量。
1.2.4 使用模型训练的方法对子词进行拆分
在神经网络模型中还可以使用模型训练的方法对子词进行拆分。常见的有子词正则和BPEDropout方法。二者相比BPEDropout方法更为出色。
1.2.5 模型中使用子词
在模型的训练过程中输入的句子是以子词形式存在的这种方式得到的预测结果也是子词。
当使用模型进行预测时模型输出子词之后再将其合并成整词即可。例如训练时先把liyongle分成了[lIyong##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. tokerstrprint(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_pairNone, #第二个句子add_special_tokensTrue,#是否添加特殊词如果为False则不会增加[CLS],[SEP]等标记词max_lengthNone, # #最大长度stride0, #返回截断词的步长窗口stride在encode方法中没有任何意义。该参数主要为兼容底层的encode_plus方法。在encode_plus方法中会根据stride的设置来返回从较长句子中截断的词。truncation_strategylongest_first, # 截断策略#截断策略longest_first默认值)当输入是2个句子的时候从较长的那个句子开始处理对其进行截断使其长度小于max_length参数。#截断策略only_frst只截断第一个句子。#截断策略only_second只截断第二个句子。#截断策略dou not_truncate不截断如果输入句子的长度大于max_length参数则会发生错误)。pad_to_max_lengthFalse,#对长度不足的句子是否填充return_tensorsNone, #是否返回张量类型,可以设置成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_toindtwo_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_length10,pad_to_max_lengthTrue)
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_length5)
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_lengthTrue)
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_lengthTrue )
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 方法定义
添加普通词:调用add_tokens方法,填入新词的字符串.添加特殊词:调用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))# 输出词表总长度:30522print(-------------------------添加特殊词后-------------------------)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