当前位置: 首页 > 工具软件 > Tokenizer > 使用案例 >

transformer.config/tokenizer/model

姬自强
2023-12-01

transformers 框架主要有三个类model 类、configuration 类、tokenizer 类,这三个类,所有相关的类都衍生自这三个类,他们都有 from_pretained() 方法和 save_pretrained() 方法。


transformers 框架主要有三个类 model 类、 configuration 类、 tokenizer 类,这三个类,所有相关的类都衍生自这三个类,他们都有 from_pretained() 方法和 save_pretrained() 方法。

Tokenizer

Tokenizer 负责为模型准备输入。大多数tokenizers 都有两种使用风格:全python实现和基于Rust library tokenizers的 fast 实现。fast 实现允许:1)大大提高了速度,尤其是在batched tokenization时,2)在 original string(字符和单词)和 token space 之间映射的额外方法(比如,获取包含给定字符或与给定token相对应的字符范围的index of the token)。当前,基于SentencePiece的 Tokenizer(针对T5,ALBERT,CamemBERT,XLMRoBERTa和XLNet模型)没有可用的“快速”实现。

有两个基类:PreTrainedTokenizer and PreTrainedTokenizerFast,实现在模型输入中编码字符串输入的通用方法,从本地文件或目录或库(from HuggingFace’s AWS S3 repository)提供的预训练的Tokenizer实例化/保存python和“快速”Tokenizer。

因此,PreTrainedTokenizerPreTrainedTokenizerFast实现了使用所有Tokenizer的主要方法:

  • tokenizing (spliting strings in sub-word token strings), 把 tokens strings 转换成 to ids, and encoding/decoding (i.e. tokenizing + convert to integers),

  • 以一种与底层结构无关的方式添加 new tokens to the vocabulary (BPE, SentencePiece…),

  • 管理特殊的tokens,如 mask, beginning-of-sentence, etc(adding them, assigning them to attributes in the tokenizer for easy access)

BatchEncoding 保存 Tokenizer 的编码方法(__call__, encode_plus and batch_encode_plus)的输出,且继承自 Python dictionary。当 tokenizer 是 pure python tokenizer 时,此类的行为就像标准的python字典一样,并包含由这些方法 (input_ids, attention_mask…)计算出的各种模型输入。当tokenizer 是 fast tokenizer 时,此类另外提供了几种高级对齐方法,可用于在原始字符串(character and words) 和 token space 进行映射(例如获取包含给定字符或与给定 token 相对应的字符范围的index of the token

@classmethod
PreTrainedTokenizer()

Parameters

  • model_max_length – (Optional) int: 输入tokens的最大长度。用 from_pretrained 加载时,基本所有模型默认都是512。
  • padding_side – 填充位置,right(default) or left
  • additional_special_tokens (-) – (Optional) list: a list of additional special tokens. 在此处添加所有 special tokens。将与self.additional_special_tokensself.additional_special_tokens_ids关联

使用(以 BertTokenizer 为例)

加载

一般都是直接加载预训练模型,传入参数可以是本地目录也可以是模型的名字

tokenizer = BertTokenizer.from_pretrained('E:/data/transformers/bert-base-uncased')
# 可以传入的参数:
padding_side
xxx_token

可以直接调用tokenizer,(实际上是 __call__() 函数)。效果和 encode_plus() 一样。可以看下面。

词典

tokenizer.get_vocab()
tokenizer.vocab,文件 <vocab.txt> 的内容。实际上是 tokens_to_ids
tokenizer.ids_to_tokens,字面意思

tokenizer.get_vocab()
# {'[PAD]': 0, '[unused0]': 1, ...}
tokenizer.vocab
# OrderedDict([('[PAD]', 0), ('[unused0]', 1), ...])
tokenizer.ids_to_tokens
# OrderedDict([(0, '[PAD]'), (1, '[unused0]'), ...])

tokenizer.vocab_size,文件 <vocab.txt> 的大小
len(tokenizer),tokenizer 的词典大小,包括自己添加的词和token。

tokenizer.vocab_size
# 30522
len(tokenizer) #假设添加了bos和eos
# 30524

如果添加了token,那添加的token和id的映射为added_tokens_encoderadded_tokens_decoder

tokenizer.added_tokens_encoder
# {'[EOS]': 30522, '[BOS]': 30523}
tokenizer.added_tokens_decoder
# {30522: '[EOS]', 30523: '[BOS]'}

总之 len(tokenizer) == len(tokenizer.vocab) + len(tokenizer.added_tokens_encoder)

token

special token

7个预置的 speical token分别为:bos_token, eos_token, unk_token, sep_token, pad_token, cls_token, mask_token,还有一个额外的:additional_special_tokens

tokenizer.SPECIAL_TOKENS_ATTRIBUTES
# ['bos_token',  'eos_token',  'unk_token',  'sep_token',  'pad_token',  'cls_token',  'mask_token',   additional_special_tokens']

以上都是 tokenizer 的一个attribute,对应一个 token:

for t in tokenizer.SPECIAL_TOKENS_ATTRIBUTES: print(eval(f'tokenizer.{t}'), end=' ')
# None None [UNK] [SEP] [PAD] [CLS] [MASK] [] 

注意如果 tokenizer 没有某个 special token,对应的属性值为None
可以在加载的时候传入该 token 的值,也可以使用 add_special_tokens() 方法传入一个键为special token值为str的字典,具体值都可以自定义,还可以传入additional_special_tokens(当然是值为列表):

# (1)
tokenizer = BertTokenizer.from_pretrained('E:/data/transformers/bert-base-uncased', bos_token='[BOS]', eos_token='[EOS]')
# (2) 
tokenizer.add_special_tokens({'bos_token': '[BOS]', 'eos_token': '[EOS]'})
for t in tokenizer.SPECIAL_TOKENS_ATTRIBUTES: print(eval(f'tokenizer.{t}'), end=' ')
# [BOS] [EOS] [UNK] [SEP] [PAD] [CLS] [MASK] [] 

其它有关 special token 属性:

tokenizer.all_special_tokens
# ['[UNK]', '[PAD]', '[MASK]', '[CLS]', '[SEP]']
tokenizer.special_tokens_map
#  'unk_token': '[UNK]', ...
unique_no_split_tokens
# ['[UNK]', '[PAD]', '[MASK]', '[SEP]', '[CLS]']

所有的 xxx_token 都可以直接查其在 vocab 中的 id(包括all_special_ids):

tokenizer.pad_token_id
# 0
tokenizer.all_special_ids
# [100, 0, 103, 101, 102]

添加 token

add_special_tokens(special_tokens_dict) -> int

  • add_special_tokens: dict[str, str]。key 为 8 个特殊 token 之一(key为additional_special_tokens时value时list而不是str)
  • 返回成功添加的个数,为0表示已存在token无需添加

add_tokens(new_tokens, special_tokens=False) -> int

  • new_tokens: str, List[str]
  • 返回成功添加的个数,为0表示已存在token无需添加

get_added_vocab() 查看添加的 tokens

token id text 转换

string tokens ids 三者可以互相转换

  • string → tokens tokenize(text: str, **kwargs)
  • tokens → string convert_tokens_to_string(tokens: List[token])
  • tokens → ids convert_tokens_to_ids(tokens: List[token])
  • ids → tokens convert_ids_to_tokens(ids: int or List[int], skip_special_tokens=False)
  • string → ids encode(text, text_pair=None, add_special_tokens=True, padding=False, truncation=False, max_length=None, return_tensors=None)
    • text: str, List[str], List[int]。空格分隔的strlist[str]里的str不是一句话而是一个word.
    • text_pair: str, List[str], List[int], None。如果输入 sequence pair,text 是第一句,text_pair 是第二句。转换出来也是一个list,不过中间有个[SEP]。如果设置 add_special_tokens=False 好像就和single sequence 没有区别了。
    • add_special_tokens: bool。编码时是否添加特殊token(开头加[CLS]结尾加[SEP],sequence pair 中间还要加[SEP])。默认添加。 添加几个 token 可以用 num_special_tokens_to_add(pair=False) 来查询
    • max_length: int, None。下面要用。注意是指总的 token 的数目。
    • padding: bool, str。只对输入为 sequence pair 有效。pad 在左还是右由tokenizer.padding_side 指定。可以在定义 tokenizer 时传入,也可以直接更改属性值。
      • True or 'longest': padding至batch(在 batch_encode_plus() 中用到)中最长的句子长度。
      • 'max_length': padding至max_length
      • False or 'do_not_pad' (default)。
    • truncation: bool, str。只对输入为 sequence pair 有效。
      • True or 'longest_first': token by token 的截断,哪一句长,截断哪一句的最后一个 token,相同长度就第二句。截至总token数等于 max_length
      • 'only_first': 只截第一句,至总token数等于 max_length
      • 'only_second': 只截第二句,至总token数等于 max_length
      • False or 'do_not_truncate' (default)。
    • return_tensors: str, None。‘tf’, ‘pt’ or ‘np’ 分布表示不同的tensor type。
  • ids → string decode(token_ids: List[int], skip_special_tokens=False, clean_up_tokenization_spaces=True)

encode_plus:

  • encode_plus(text, text_pair=None, add_special_tokens=True, padding=False, truncation=False, max_length=None, stride=0, is_pretokenized=False, pad_to_multiple_of=None, return_tensors=None, return_token_type_ids=None, return_attention_mask=None, return_overflowing_tokens=False, return_special_tokens_mask=False, return_offsets_mapping=False, return_length=False)
    高级编译方法,返回一个字典。 等同于 tokenizer.forward

批量

  • batch_encode_plus() 输入为 encode 输入的 batch,其它参数相同。注意,plus 是返回一个字典。
  • batch_decode() 输入为 decode 输入的 batch。

例子

string = 'encode decode bert transformers.'
tokens = t.tokenize(string)
ids = t.convert_tokens_to_ids(tokens)

print(tokens)  # ['en', '##code', 'deco', '##de', 'bert', 'transformers', '.']
print(ids)  # [4372, 16044, 21933, 3207, 14324, 19081, 1012]

print(t.tokenize(string))  # ['en', '##code', 'deco', '##de', 'bert', 'transformers', '.']
print(t.convert_tokens_to_string(tokens))  # encode decode bert transformers .

print(t.convert_ids_to_tokens(ids))  # ['en', '##code', 'deco', '##de', 'bert', 'transformers', '.']
print(t.convert_tokens_to_ids(tokens))  # [4372, 16044, 21933, 3207, 14324, 19081, 1012]

print(t.encode(string))  # [101, 4372, 16044, 21933, 3207, 14324, 19081, 1012, 102]
print(t.decode(ids))  # encode decode bert transformers.
注意:encode 默认会添加 special token,decode 默认不会跳过 special token
要么 encode 设置 add_special_tokens=False,要么decode 设置 skip_special_tokens=True
print(t.decode(t.encode(string)))  # '[CLS] encode decode bert transformers. [SEP]'

print(t.encode_plus(string))  
# {'input_ids': [101, 4372, 16044, 21933, 3207, 14324, 19081, 1012, 102], 
	'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0], 
	'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}

strings = [string, string]
out = t.batch_encode_plus(strings)
print(out )
# {'input_ids': [[101, 4372, 16044, 21933, 3207, 14324, 19081, 1012, 102], 
				 [101, 4372, 16044, 21933, 3207, 14324, 19081, 1012, 102]],
	'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
					   [0, 0, 0, 0, 0, 0, 0, 0, 0]], 
	'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1], 
					   [1, 1, 1, 1, 1, 1, 1, 1, 1]]}
print(t.batch_decode(out.input_ids)) # 						
# ['[CLS] encode decode bert transformers. [SEP]', 
 '[CLS] encode decode bert transformers. [SEP]']

别的

都是有点冗余的方法,其实都可以在 encode等方法 中一并完成的。

  • pad(encoded_inputs, padding=True, max_length=None, pad_to_multiple_of=None, return_attention_mask=None, return_tensors=None, verbose=True)
    pad 单句或多句至指定长度或batch中的最长。pad 在左还是右由tokenizer.padding_side 指定。可以在定义 tokenizer 时传入,也可以直接更改属性值。

    • encoded_inputs: Dict[str, List[int]], Dict[str, List[List[int]]], List[Dict[str, List[int]]]
    • padding: bool, str
      • 'longest' or True: Pad to the longest sequence in the batch
      • 'max_length': Pad to the max length (default)
      • 'do_not_pad' or False: Do not pad
    • max_length: int, None
    • pad_to_multiple_of: int, None
    • return_attention_mask: bool, None。Set to False to avoid returning attention mask
    • return_tensors: str, None'tf', 'pt' or 'np'
  • truncate_sequences(ids, pair_ids=None, num_tokens_to_remove=0, truncation_strategy='longest_first', stride=0)

    • ids: list of tokenized input ids. encode 得到的 ids。
    • pair_ids: Optional second list of input ids.。
    • num_tokens_to_remove (int, defaults to 0): 根据 truncation_strategy 移除的 token 数目
    • truncation_strategy: string。同 encode(),只是默认值不同。
      • 'longest_first' (default): token by token。
      • 'only_first'
      • only_second'
      • 'do_not_truncate'
    • stride (:obj:int, optional, defaults to 0):
      • If set to a number along with max_length, the overflowing tokens returned will contain some tokens
      • from the main sequence returned. The value of this argument defines the number of additional tokens.
  • prepare_for_model(ids, pair_ids=None, add_special_tokens=True, return_length=True)
    剩下参数都是False,意思嘛,和上面的都一样了。
    输入是 encoded_ids,最好是用 convert_tokens_to_ids() 的输出作为输入,因为它不会add_special_tokens。
    如果用encode 的输出作为输入,则需要注意 prepare_for_modelencode 都有 add_special_tokens=True
    实际测试了下,效果等同于对原始的 string 进行 encode_plus

    • ids: List[int]
    • pair_ids: List[int], None
    • add_special_tokens: bool
    • padding: bool, str
    • truncation: bool, str
    • max_length: int, None
    • stride: int
    • pad_to_multiple_of: int, None
    • return_tensors: str, None
    • return_token_type_ids: bool, None
    • return_attention_mask: bool, None
    • return_overflowing_tokens: bool
    • return_special_tokens_mask: bool
    • return_offsets_mapping: bool
    • return_length: bool
    • verbose: bool
    • prepend_batch_axis: bool
  • build_inputs_with_special_tokens(token_ids_0, token_ids_1=None)
    添加 special token,等同于 encode() 方法中的 add_special_tokens=True 这个参数的效果。

  • get_special_tokens_mask(token_ids_0, token_ids_1=None, already_has_special_tokens=False )
    字面意思。

保存

  • save_pretrained(save_directory)
  • save_vocabulary(vocab_path)

Model

使用(以 BertModel 为例)

加载

一般都是直接加载预训练模型,传入参数可以是本地目录也可以是模型的名字

model = BertModel.from_pretrained("E:/data/transformers/bert-base-uncased/")

向上溯源是来自 torch.nn.Moduletorch.nn.Module 的重要方法有: cpu() cuda() train() eval() forward() parameters() named_parameters() requires_grad_() zero_grad() to() add_module()

属性

  • model.base_model: 模型结构,有几个组成部分:model.embeddingsmodel.encodermodel.pooler
  • model.config
  • model.device
  • model.dtype
  • model.dummy_inputs: model 的虚拟输入,可以看看是什么格式的数据
m.dummy_inputs
# {'input_ids': tensor([[7, 6, 0, 0, 1],
 						  [1, 2, 3, 0, 0],
 						  [0, 0, 0, 4, 5]])}

方法

  • num_parameters(only_trainable=False) 获取参数数量
  • tie_weights()

embedding 相关

  • get_input_embeddings()
  • get_output_embeddings()
  • resize_token_embeddings(new_num_tokens)
  • set_input_embeddings(value)

attention 相关

  • get_extended_attention_mask(attention_mask, input_shape, device)
  • invert_attention_mask(encoder_attention_mask)

head 相关

  • get_head_mask(head_mask, num_hidden_layers, is_attention_chunked)
  • prune_heads(heads_to_prune)

其它

  • postprocess_next_token_scores( scores, input_ids, no_repeat_ngram_size, bad_words_ids, cur_len, min_length, max_length, eos_token_id, repetition_penalty, batch_size, num_beams)
  • prepare_inputs_for_generation(input_ids)
  • save_pretrained(save_directory)
  • generate()

Config

属性和方法

config = BertConfig.from_pretrained('E:/data/transformers/bert-base-chinese/')
all_fields = [x for x in dir(config) if not x.startswith("_")]
print('all attribute:', end=' ')
for field in all_fields:
    if type(eval(f'config.{field}'))!=type(config.from_dict):
        print(f'`{field}`,', end=' ') 
print('\n\nall method:', end=' ')
for field in all_fields:
    if type(eval(f'config.{field}'))==type(config.from_dict):
        print(f'`{field}()`,', end=' ') 

输出:

all attribute: architectures, attention_probs_dropout_prob, bad_words_ids, bos_token_id, decoder_start_token_id, directionality, do_sample, early_stopping, eos_token_id, finetuning_task, gradient_checkpointing, hidden_act, hidden_dropout_prob, hidden_size, id2label, initializer_range, intermediate_size, is_decoder, is_encoder_decoder, label2id, layer_norm_eps, length_penalty, max_length, max_position_embeddings, min_length, model_type, no_repeat_ngram_size, num_attention_heads, num_beams, num_hidden_layers, num_labels, num_return_sequences, output_attentions, output_hidden_states, pad_token_id, pooler_fc_size, pooler_num_attention_heads, pooler_num_fc_layers, pooler_size_per_head, pooler_type, prefix, pruned_heads, repetition_penalty, task_specific_params, temperature, top_k, top_p, torchscript, type_vocab_size, use_bfloat16, use_cache, vocab_size, xla_device,

all method: from_dict(), from_json_file(), from_pretrained(), get_config_dict(), save_pretrained(), to_dict(), to_diff_dict(), to_json_file(), to_json_string(), update(),

好像没什么好说的。

 类似资料: