赞
踩
以下为2021版原文~~~~
在Transformers库中,提供了一个通用的词表工具Tokenizer,该工具是用Rust编写的,其可以实现NLP任务中数据预处理环节的相关任务。
在词表工具Tokenizer中,主要通过PreTrainedTokenizer类实现对外接口的使用。
对输入字符串进行规范化转换,如对文本进行小写转换、使用uni-code规范化。
对输入数据进行预处理,如基于字节空格、字符等级别对文本进'Madel:生成和使用子词的横型,如Wordlevel、BPE、WordPlece等模型。这部分是可训练的。
对分词后的文本进行二次处理。例如,在BERT模型中,使用ssor为输入文本添加特殊字符(如[CLS]、[SEP]等)。
负责将标记化输入映射回原始字符串。
为每个模型提供培训能力。
词表工具将liyongle分成了[lI',yong','#le],使用子词的拆分技术可以防止NLP任务中,在覆盖大量词汇的同时,词表过大的问题。
在进行NLP时,通过为每个不同词对应一个不同的向量,来完成文字到数值之间的转换,这个映射表被称作词表。
对于某些形态学丰富的语言(如德语,或是带有时态动词的英语),如果将每个变化的词都对应一个数值,则会导致词表过大的问题。而且这种方式使得两个词之间彼此独立,也不能体现出其本身的相近意思(如pad和padding)。
子词就是将一般的词,如padding分解成更小单元pad+ding。而这些小单元也有各自意思,同时这些小单元也能用到其他词中。子词与单词中的词根、词缀非常相似。通过将间分解成子词,可以大大降低模型的词汇量,减少运算量。
Byte Pair Encoding(BPE)法:统计频次,即先对语料统计出相邻符号对的频次,再根据频词进行融合。
WordPiece法:WordPiece法统计最大似然,是Google公司内部的子词包,其未对外公开。BERT最初用的就是WordPiece法分词。
Unigram Language Model法:先初始化一个大词表,接着通过语言模型评估不断减少词表,一直减少到限定词汇量。
在神经网络模型中,还可以使用模型训练的方法对子词进行拆分。常见的有子词正则和BPEDropout方法。二者相比,BPEDropout方法更为出色。
在模型的训练过程中,输入的句子是以子词形式存在的,这种方式得到的预测结果也是子词。
当使用模型进行预测时,模型输出子词之后,再将其合并成整词即可。例如,训练时先把liyongle分成了[lI',yong','##le'],获得结果后,将句子中的“##”去掉即可。
在PreTrainedTokenizer类中,将词分成了两部分:普通词与特殊词。其中特殊词是指用于标定句子的特殊标记,主要是在训练模型中使用
- 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属性。
- 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
- )
- 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]']
- 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]
- 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]
- # 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]
- # }
- # 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]]}
- 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。