Transformer 库中的 models

创建Transformer 模型

from transformers import AutoModel
model = AutoModel.from_pretrained("bert-base-cased")

AutoModel 是一个 auto 类,意味着它会为你猜测合适的模型架构并实例化正确的模型类。如果你知道你想使用的模型类型,可以直接使用它来定义其架构的类,比如我确定我要使用BERT模型,则可以这样:

from transformers import BertModel
model = BertModel.from_pretrained("bert-base-cased")

save models

save_pretrained() 方法保存模型的权重架构配置

model.save_pretrained("directory_on_my_computer") 会保存模型到指定路径。内容包含 config.jsonpytorch_model.bin

  • config.json 构建模型架构所需的所有必要属性,还包括checkpoint的来源,以及那时是使用的transformer 的版本。

  • pytorch_model.bin 文件被称为 state dictionary, 它包含你模型的所有权重。

这两个文件协同工作:配置文件用于了解模型架构,而模型权重是模型的参数。

load saved models

要重用保存的模型,再次使用 from_pretrained() 方法:

from transformers import AutoModel
model = AutoModel.from_pretrained("directory_on_my_computer")

分享你的模型或 embedding

Encoding text

已经知道 tokenizer 将文本分割成 tokens,然后将这些标记转换为数字 input IDs。可以观察这种转换:

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
encoded_input = tokenizer("How are you?", "I'm fine, thank you!", return_tensors="pt")
print(encoded_input)

{'input_ids': 
tensor([[101, 1731, 1132, 1128, 136, 102], 
        [101, 1045, 1005, 1049, 2503, 117, 5763, 1128,136, 102]]), 
 'token_type_ids': 
 tensor([[0, 0, 0, 0, 0, 0], 
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]),   # wrong?为什么都是0,分明是两个batch?
 'attention_mask': 
 tensor([[1, 1, 1, 1, 1, 1], 
         [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}
  • input_ids: token 转化为数值表示
  • token_type_ids: 些告诉模型输入的哪部分是句子 A,哪部分是句子 B。为句子 A 的 token 分配 0,为句子 B 的 token 分配 1,帮助模型理解两部分的边界和关系。
  • attention_mask: 这表示哪些标记应该被关注,哪些不应该。

tokenizer() 方法这里有几个参数:

  1. return_tensors="pt" 将输出转化为 PyTorch tensors。
  2. padding=True/False 将输入填充。
  3. truncation=True 如果输入太长,则截断它们。

1. Padding 输入填充

encoded_input = tokenizer(
    ["How are you?", "I'm fine, thank you!"],  # 一组,所以是一个句子
    padding=True, 
    return_tensors="pt"
)
print(encoded_input)

{'input_ids': 
tensor([[101,1731,1132,1128, 136, 102, 0,  0,    0,    0],
        [101,1045,1005,1049,2503, 117,5763,1128, 136, 102]]), 
 'token_type_ids': 
 tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],  
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]),  # 一组,所以是一个句子
 'attention_mask': 
 tensor([[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
         [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}

为什么要 Padding 成长度一样的?

答:因为 Transformer 模型要求输入张量形状一致(批量处理时需要固定维度),便于并行计算和高效处理不同长度的输入。

2. Truncating inputs 截断输入

张量可能会太大以至于无法被模型处理。例如,BERT 只预训练了最多 512 个 token 的序列,所以它无法处理更长的序列。如果你有超过模型处理能力的序列,你需要使用 truncation 参数来截断它们。 通过结合padding 和 truncation 参数,你可以确保你的张量具有你需要的精确大小:

encoded_input = tokenizer(
    ["How are you?", "I'm fine, thank you!"],  # 一组,所以是一个句子
    padding=True,
    truncation=True,
    max_length=5,
    return_tensors="pt",
)
print(encoded_input)


{'input_ids': 
tensor([[  101,  1731,  1132,  1128,   102],
        [  101,  1045,  1005,  1049,   102]]), 
 'token_type_ids': 
 tensor([[0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0]]),  # 一组,所以是一个句子
 'attention_mask': 
 tensor([[1, 1, 1, 1, 1],
         [1, 1, 1, 1, 1]])}

tokenizer 之后的 input ids 即 token的数量一般大于原始句子中的单词数量,为什么?

原因有以下:

  1. Transformer 模型的 tokenizer(如 BERT、Qwen 的 tokenizer)通常使用具体的tokenizer 方法如 WordPiece、BPE 或 SentencePiece,将句子拆分为更小的单元(subword tokens)

  2. Tokenizer 会添加特殊 token,如 [CLS](分类标记)、[SEP](句子分隔符)或 [PAD](填充标记)

  3. 标点符号(如?!.) 通常被单独编码为 token。

所以token数量多于单词数量。那么如何查看token分别是啥? 可以通过 decode input id 反过来得到原始文本:

tokenizer.decode(encoded_input["input_ids"][0])
"[CLS] How are you? [SEP]"

看,第一句话有6个token,但是只有3个单词。

那么其中的特殊 token 是什么?

添加特殊tokens

特殊 Tokens 对 BERT 及其衍生模型尤为重要。这些标记被添加以更好地表示句子边界,例如句子的开始( [CLS] )或句子之间的分隔符( [SEP] )。

这些 Tokens 由 tokenizer 自动添加。并非所有模型都需要特殊标记。模型在预训练时使用了这些标记,所以你使用预训练模型时,也需要使用这些特殊 token 的。

最后 encoded_input 会作为模型的输入。


Stay curious and keep asking questions! 🧠✨