模型
在本节中,我们将更深入地了解如何创建和使用模型。我们将使用 AutoModel
类,当您想要从检查点实例化任何模型时,它非常方便。
AutoModel
类及其所有相关类实际上只是库中各种模型的简单包装器。它是一个聪明的包装器,因为它可以自动猜测检查点对应的模型架构,然后使用此架构实例化模型。
但是,如果您知道要使用的模型类型,则可以直接使用定义其架构的类。让我们看看 BERT 模型是如何工作的。
创建 Transformer
初始化 BERT 模型的第一步是加载配置对象
from transformers import BertConfig, BertModel
# Building the config
config = BertConfig()
# Building the model from the config
model = BertModel(config)
配置包含许多用于构建模型的属性
print(config)
BertConfig {
[...]
"hidden_size": 768,
"intermediate_size": 3072,
"max_position_embeddings": 512,
"num_attention_heads": 12,
"num_hidden_layers": 12,
[...]
}
虽然您还没有看到所有这些属性的作用,但您应该认识其中的一些:hidden_size
属性定义了 hidden_states
向量的尺寸,num_hidden_layers
定义了 Transformer 模型的层数。
不同的加载方法
从默认配置创建模型会使用随机值进行初始化
from transformers import BertConfig, BertModel
config = BertConfig()
model = BertModel(config)
# Model is randomly initialized!
模型可以在这种状态下使用,但它会输出乱码;它需要先进行训练。我们可以从头开始针对手头的任务训练模型,但正如您在第 1 章中看到的,这需要很长时间和大量数据,并且会产生不可忽略的环境影响。为了避免不必要的重复工作,能够共享和重用已经训练过的模型势在必行。
加载已经训练好的 Transformer 模型很简单——我们可以使用 from_pretrained()
方法来实现
from transformers import BertModel
model = BertModel.from_pretrained("bert-base-cased")
如您之前所见,我们可以用等效的 AutoModel
类替换 BertModel
。从现在开始我们将这样做,因为这会生成与检查点无关的代码;如果您的代码适用于一个检查点,它应该可以无缝地适用于另一个检查点。即使架构不同,只要检查点针对类似的任务进行了训练(例如,情感分析任务),这同样适用。
在上面的代码示例中,我们没有使用 BertConfig
,而是通过 bert-base-cased
标识符加载了预训练模型。这是一个由 BERT 作者自己训练的模型检查点;您可以在其模型卡片中找到更多详细信息。
此模型现在已使用检查点的所有权重进行初始化。它可以直接用于推理其训练过的任务,也可以针对新任务进行微调。通过使用预训练权重而不是从头开始训练,我们可以快速获得良好的结果。
权重已下载并缓存(因此将来调用 from_pretrained()
方法不会重新下载它们)到缓存文件夹中,默认情况下为 ~/.cache/huggingface/transformers。您可以通过设置 HF_HOME
环境变量来自定义缓存文件夹。
用于加载模型的标识符可以是模型中心上任何模型的标识符,只要它与 BERT 架构兼容即可。可以在此处找到所有可用的 BERT 检查点的完整列表。
保存方法
保存模型与加载模型一样简单——我们使用 save_pretrained()
方法,它类似于 from_pretrained()
方法
model.save_pretrained("directory_on_my_computer")
这会将两个文件保存到您的磁盘上
ls directory_on_my_computer
config.json pytorch_model.bin
如果您查看 config.json 文件,您会识别出构建模型架构所需的属性。此文件还包含一些元数据,例如检查点源自哪里以及上次保存检查点时您使用的是哪个 🤗 Transformers 版本。
pytorch_model.bin 文件称为 状态字典;它包含您模型的所有权重。这两个文件是相辅相成的;配置是了解模型架构所必需的,而模型权重是模型的参数。
使用 Transformer 模型进行推理
既然您已经了解了如何加载和保存模型,那么让我们尝试使用它进行一些预测。Transformer 模型只能处理数字——由分词器生成的数字。但在我们讨论分词器之前,让我们先了解模型接受哪些输入。
分词器可以处理将输入转换为适当框架的张量,但为了帮助您理解正在发生的事情,我们将快速了解在将输入发送到模型之前必须执行的操作。
假设我们有几个序列
sequences = ["Hello!", "Cool.", "Nice!"]
分词器将这些转换为词汇索引,这些索引通常称为输入 ID。每个序列现在都是一个数字列表!生成的输出是
encoded_sequences = [
[101, 7592, 999, 102],
[101, 4658, 1012, 102],
[101, 3835, 999, 102],
]
这是一个编码序列的列表:一个列表的列表。张量只接受矩形形状(例如矩阵)。这个“数组”已经是矩形形状,因此将其转换为张量很容易
import torch
model_inputs = torch.tensor(encoded_sequences)
使用张量作为模型的输入
使用模型中的张量非常简单——我们只需使用输入调用模型即可
output = model(model_inputs)
虽然模型接受许多不同的参数,但只有输入 ID 是必需的。我们将在后面解释其他参数的作用以及何时需要它们,但首先我们需要仔细看看构建 Transformer 模型可以理解的输入的分词器。