xxxPipeline.from_pretrained(model_path)加载自定义路径下的模型结构
问题:
许多模型(特别是huggingface上的模型),在进行推理时都会使用xxxPipeline.from_pretrained(model_path)来加载推理流程,在该过程中,会自动实现各个子模块的初始化以及权重的加载。
而且许多子模块都来自于各种python库,例如transformers或者diffusers,当我们在本地重写了相关模型的结构(即import本地文件中的函数,而不是库中的),并且进行微调后,xxx.Pipeline.from_pretrained并不会加载我们本地的模型结构,依旧是从库中调用。
例如:在diffusers库中有model_A.py,其中包含模型A_function(),为了改动模型A的结构,一般会把该模型移至本地,从本地加载;但是当微调完模型后,xxx.Pipeline.from_pretrained()还是会按照库中的函数进行调用,并且由于from_pretrained()封装较深,直接对pipeline的改动会较为复杂。
解决:
其实xxx.Pipeline.from_pretrained()在加载模型时,通常会按照model_path路径中的model.json/model_index.json来加载,其中的内容例如为:
{
"_class_name": "ModelPipeline",
"_diffusers_version": "0.31.0.dev0",
"scheduler": [
"diffusers",
"ModelScheduler"
],
"text_encoder": [
"transformers",
"Text_EncoderModel"
],
"tokenizer": [
"transformers",
"Text_Tokenizer"
],
"transformer": [
"diffusers",
"ModelA_Transformer3DModel"
],
"vae": [
"diffusers",
"AutoencoderKL"
]
}
在该json文件中,会告诉xxxPipeline.from_pretrained()从哪个库中调用哪个模型,例如从diffusers中调用ModelA_Transformer3DModel,当我们从本地加载该模型时,只需要在该json文件中将diffusers修改为本地的文件路径即可,例如:
{
"_class_name": "ModelPipeline",
"_diffusers_version": "0.31.0.dev0",
"scheduler": [
"diffusers",
"ModelScheduler"
],
"text_encoder": [
"transformers",
"Text_EncoderModel"
],
"tokenizer": [
"transformers",
"Text_Tokenizer"
],
"transformer": [
"/home/user/model/", # 或者同project路径下: model/model_A
"ModelA_Transformer3DModel"
],
"vae": [
"diffusers",
"AutoencoderKL"
]
}
这样,from_pretrained()就会从本地该模型所在文件的路径/home/user/model中去加载ModelA_Transformer3DModel.