问题:
许多模型(特别是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.