Transformers中加载预训练模型的过程剖析(一)

使用HuggingFace的Transformers库加载预训练模型来处理下游深度学习任务很是方便,然而加载预训练模型的方法多种多样且过程比较隐蔽,这在一定程度上会给人带来困惑。因此,本篇文章主要讲一下使用不同方法加载本地预训练模型的区别、加载预训练模型及其配置的过程,藉此做个记录,也可供参考。

加载预训练模型的过程

transformers里主要使用 from_pretrained 方法来加载预训练模型,调用这个方法时会执行以下过程:

  • 加载预训练模型:from_pretrained方法可以选择从本地加载已下载的预训练模型,或者提供模型名称从HuggingFace的模型仓库下载预训练模型权重;
  • 加载配置:from_pretrained方法会加载预训练模型的配置文件,配置包含了模型的名称、架构、参数等信息。这些配置参数用来定义模型的结构;
  • 初始化模型:使用配置文件中的参数初始化模型,构建模型的各个层和结构;
  • 载入权重:将预训练模型权重载入到初始化的模型结构中;
  • 创建实例:返回加载了权重的模型实例,利用这个实例进一步完成特定的下游任务。

加载预训练模型

要加载预训练模型,可以使用transformers库的 AutoModel 方法或具体模型对应的方法(比如要加载的是Ernie模型,则可以直接使用 ErnieModel )。这两者有区别吗?

先说结论:AutoModel.from_pretrainedErnieModel.from_pretrained 方法本质上是一样的。

本文以 shibing624/text2vec-base-chinese-paraphrase 模型为例,可以下载到本地以作示例之用。注意至少需要下载 pytorch_model.binconfig.jsonvocab.txt 三个文件,其中前两个文件加载预训练模型会用到,第三个文件加载切词器会用到,否则会报错。


在这里插入图片描述

图1

#需要先安装transformers模块(pip install transformers -i https://pypi.tuna.tsinghua.edu.cn/simple/)
from transformers import AutoModel, ErnieModel
#下载的预训练模型的路径(按自己存放位置修改)
model_path = './pretrain_models/shibing624-text2vec-base-chinese-paraphrase' 
model = AutoModel.from_pretrained(model_path)

将鼠标悬停在上述代码的 from_pretrained 上,可以看到 AutoModel.from_pretrained 其实是调用了其父类 _BaseAutoModelClass 里面的from_pretrained方法,如图2所示。


在这里插入图片描述

图2

具体过程:

  1. AutoModel.from_pretrained里面的 AutoModel 实际是在文件 transformers/models/auto/modeling_auto.py 的类 AutoModelWithLMHead 里且继承自父类 _AutoModelWithLMHead 里的from_pretrained:

在这里插入图片描述

图3

  1. 再来看 _AutoModelWithLMHead ,它继承自 _BaseAutoModelClass 类,因此说 AutoModel.from_pretrained 其实是调用了 _BaseAutoModelClass 里的from_pretrained方法。类 _BaseAutoModelClass 存在于文件 transformers/models/auto/auto_factory.py 中。

在这里插入图片描述

图4

我们已知 AutoModel.from_pretrained 实际上调用了类 _BaseAutoModelClass 里的 from_pretrained 方法,下面来看看它会返回什么。

图5是截取了类 _BaseAutoModelClassfrom_pretrained 方法里获取预训练模型的片段代码,如果加载的是本地下载的预训练模型,走的是 elif 这条路,更详细的不赘述了,描述一下大概流程:走这条路会利用下载的预训练模型里的配置文件 config.json (稍后会讲它的加载过程)来匹配要加载的模型,具体来说,会用到配置文件里 architectures (配置文件参数如图6所示) 这个属性来匹配模型(通过调用 _get_model_class 方法)。

比如对于 ErnieModel ,查找到的模型(model_class)会是:transformers.models.ernie.modeling_ernie.ErnieModel

再结合返回值 return model_class.from_pretrained(pretrained_model_name_or_path, *model_args, config=config, **hub_kwargs, **kwargs)

因此通过最初的 AutoModel.from_pretrained(model_path) ,最终会和直接使用 ErnieModel.from_pretrained(model_path) 得到相同的结果,即会调用 transformers.models.ernie.modeling_ernie 里的 ErnieModel ,如图7所示,此谓之殊途同归。


在这里插入图片描述

图5

在这里插入图片描述

图6

在这里插入图片描述

图7

加载配置文件

再来看配置文件的加载机制,transformers里预训练模型配置文件的加载分为显式加载和隐式加载。

显式加载

from transformers import AutoConfig, ErnieConfig, AutoModel, ErnieModel
#显式加载
config = AutoConfig.from_pretrained(model_path)
model = AutoModel.from_pretrained(model_path, config = config)

隐式加载

from transformers import AutoConfig, ErnieConfig, AutoModel, ErnieModel
#隐式加载
model = AutoModel.from_pretrained(model_path)

对于隐式加载,由于未在 AutoModel.from_pretrained 里指定 config 参数,因此会在上面加载模型时用的类 _BaseAutoModelClass 里的 from_pretrained 方法里面进行配置文件的加载,片段代码如图8所示:


在这里插入图片描述

图8

具体过程:

  1. AutoConfig.from_pretrained 里的 AutoConfig 实际上是在文件 transformers/models/auto/configuration_auto.py 里,AutoConfig.from_pretrained 方法本质上是通过 PretrainedConfig.get_config_dict 方法来加载配置文件,如图9所示。 PretrainedConfig.get_config_dict 来自文件 transformers/configuration_utils.py
  2. PretrainedConfig.get_config_dict 会利用 AutoModel.from_pretrained 中传入的模型本地路径 model_path 拼接上 CONFIG_NAME(来自:transformers/utils/init.py里面的CONFIG_NAME = “config.json”),从而取到本地预训练模型的配置文件 config.json ,至此,可以成功加载配置文件。

在这里插入图片描述

图9

上面是隐式加载配置文件过程,再来看看显式加载过程。

图10可以看出 AutoConfig.from_pretrained(model_path) 里的 AutoConfig 来自 transformers.models.auto.configuration_auto ,所以 AutoConfig.from_pretrained(model_path) 引用的实际上是 configuration_auto.py 里的 from_pretrained 方法,这就回到了图9里面的函数,因此,通过 AutoConfig.from_pretrained(model_path) 这种显式加载配置文件,其实也是和隐式一样到了相同的归处。


在这里插入图片描述

图10

更进一步,再来看下使用具体模型的加载方法: ErnieConfig.from_pretrained(model_path)ErnieConfig 本身没有 from_pretrained 方法,但它继承了 PretrainedConfig ,如图11所示。PretrainedConfig 在文件 transformers/configuration_utils.py 里,然后通过其中的 from_pretrained 方法加载配置文件(函数返回配置文件),如图12所示,返回值的类型被设置成 PretrainedConfig (因此如果显式加载了,就不会走图8那步了) 。
具体引用的PretrainedConfig.get_config_dict 见图13,其中注意一下绿色方框里面的警告:如果配置文件"config.json"里面的 model_type 属性值与cls(cls代表PretrainedConfig类)的"model_type"属性(实际上是在transformers/models/ernie/configuration_ernie.py的ErnieConfig类中定义的,随模型的改变而变化)不一样时会出现像图14的提示。


在这里插入图片描述

图11

在这里插入图片描述

图12

在这里插入图片描述

图13

在这里插入图片描述

图14

通过以上探查可以得到结论:对于配置文件的加载,无论是显式(AutoConfig.from_pretrained或ErnieConfig.from_pretrained)还是隐式加载,最终都会到达 transformers/configuration_utils.py 里的 from_pretrained 方法并且使用里面的 get_config_dict 方法来加载配置文件。
模型的初始化和预训练权重载入,下篇见!

  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
文句子关系推断是一项重要的自然语言处理任务,可以用于文本分类、情感分析、问答系统等领域。在huggingface,使用预训练模型进行文句子关系推断的实现非常简单,下面是一个示例代码: ```python from transformers import AutoTokenizer, AutoModelForSequenceClassification # 加载BERT模型 tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese") model = AutoModelForSequenceClassification.from_pretrained("bert-base-chinese") # 准备数据集 sentences = ["这是一个正向句子", "这是一个负向句子"] labels = [1, 0] # 进行数据预处理 inputs = tokenizer(sentences, padding=True, truncation=True, return_tensors="pt") # 进行模型训练和微调 outputs = model(**inputs, labels=labels) loss = outputs.loss logits = outputs.logits # 进行模型评估和推理 predictions = logits.argmax(dim=1) ``` 在上面的代码,我们使用了BERT模型进行句子关系推断的训练和微调,使用了PyTorch框架进行模型的训练和推理。在进行模型训练和微调时,我们需要指定模型输入和输出的格式,以及损失函数和优化器的选择。在进行模型评估和推理时,我们可以使用模型输出的logits进行分类,得到模型对于输入句子的分类结果。 需要注意的是,上面的代码只是一个简单的示例,实际应用还需要根据具体任务进行模型调整和性能优化。同时,在进行文句子关系推断的实战,还需要注意数据集的选择和预处理,以及模型训练的超参数的选择等方面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值