ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

PaddleHub Module API 权威指南:预训练模型加载、运行与推理导出的统一入口

PaddleHub Module API 权威指南:预训练模型加载、运行与推理导出的统一入口 PaddleHub Module API 权威指南预训练模型加载、运行与推理导出的统一入口【免费下载链接】PaddleFormersPaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFormersPaddleHub 是 PaddlePaddle 生态中的模型库与开发工具而paddlehub.Module是其最核心的统一抽象无论是用于端到端预测的预训练模型如人脸检测、词法分析还是需要微调的预训练语言模型如 BERT/ERNIE都以 Module 的形式被加载、调用与导出。本文以官方 API 文档 docs/docs_en/api/module.rst 为骨架结合仓库源码逐层剖析paddlehub.Module的构造参数、成员函数、类方法与属性并辅以真实模块示例帮助你在实际项目中完成模型加载、命令行运行、ONNX/Paddle Inference 导出等完整工作流。Module 是什么可执行模型的一等公民在 PaddleHub 中Module 表示一个可执行的模型单元executable module。官方文档给出了其精确定义In PaddleHub, Module represents an executable module, which usually a pre-trained model that can be used for end-to-end prediction, such as a face detection model or a lexical analysis model, or a pre-trained model that requires finetuning, such as BERT/ERNIE.这段定义揭示了 Module 的两大典型形态端到端预测型例如仓库中的词法分析模块modules/lexical_analysis、语音识别模块modules/audio/asr/deepspeech2_aishell加载后可直接对输入文本或音频做推理微调基座型例如modules/text/language_model下的 BERT/ERNIE 系列作为预训练权重提供给paddlehub.finetune.Trainer使用。一个关键行为是按名称加载 Module 时如果本地不存在PaddleHub 会自动向服务器或指定的 Git 源请求并下载资源。这一自动下载机制的完整实现位于 paddlehub/module/module.py 与 paddlehub/module/manager.py详见下文加载流程小节。构造参数详解paddlehub.Module的完整类签名如下来自 module.py 与官方文档class paddlehub.Module( name: str None, directory: str None, version: str None, ignore_env_mismatch: bool False, **kwargs)各参数含义与行为参数类型默认值说明namestr可选None模块名称。指定后按名称加载模块本地不存在时自动下载。directorystr可选None待加载模块的目录仅在未指定name时生效用于从本地目录直接加载用户自定义模块。versionstr可选None模块版本约束仅在指定name时生效。当本地模块不满足指定版本条件时PaddleHub 会重新向服务器请求下载合适版本。默认为 None表示直接使用本地模块若本地不存在则按当前使用环境从服务器下载可用最新版本。ignore_env_mismatchbool可选False安装模块时是否忽略环境不匹配如 PaddlePaddle / PaddleHub 版本不兼容。默认 False。需要特别强调的是Module是一个工厂类源码中Module.__new__module.py会根据传入参数分发到两条初始化路径传入name时 →init_with_name(...)走按名称搜索 → 本地缺失则安装的逻辑传入directory时 →init_with_directory(...)直接从指定目录加载。同时__new__会启动一个后台线程CacheUpdater(update_cache, module..., version...)用于更新本地缓存记录这正是自动下载背后的基础设施之一。除了官方文档列出的四个参数源码中的init_with_name还额外支持sourceGit 仓库地址指定后不再从默认服务器下载而是从该仓库查找、update是否更新本地缓存的 Git 仓库仅在指定source时生效默认 False与branch指定 Git 仓库的分支这些参数以**kwargs的形式透传供从 Git 源安装模块的高级场景使用。按名称加载hub.Module(namexxx)这是最常见的用法。仓库测试 tests/test_module.py 给出了大量真实调用示例import paddlehub as hub # 词法分析 lac hub.Module(namelac) results lac.lexical_analysis(data{text: [今天是个好日子]}) # 情感分析 senta hub.Module(namesenta_bilstm) results senta.sentiment_classify(data{text: [这家餐厅很好吃]}) # 短文本相似度 simnet_bow hub.Module(namesimnet_bow) results simnet_bow.similarity(data{text_1: [...], text_2: [...]}) # 目标检测 ssd hub.Module(namessd_mobilenet_v1_pascal) results ssd.object_detection(data{image: [test_img_path]})指定版本时PaddleHub 会做版本匹配只有当本地模块存在且其版本满足version约束时才直接使用本地模块否则重新下载对应init_with_name中的if not user_module_cls or not user_module_cls.version.match(version)判断见 module.py。按目录加载hub.Module(directoryxxx)当不指定name而指定directory时PaddleHub 直接加载该目录下定义的模块类。仓库示例 modules/demo/test.py 展示了完整用法import paddlehub as hub senta_test hub.Module(directorysenta_test) print(senta_test.sentiment_classify([这部电影太糟糕了, 这部电影太棒了]))该示例对应的模块源码位于 modules/demo/senta_test/module.py这是一个被moduleinfo修饰、继承paddle.nn.Layer或普通类的用户自定义模块详见后文装饰器与自定义模块。加载流程从 name 到可用对象的完整调用链按名称加载是 Module 最核心的机制其完整调用链如下依据 module.py 与 manager.py构造LocalModuleManager()按模块主目录MODULE_HOME缓存为单例调用manager.search(name, sourcesource, branchbranch)在本地查找模块先查内存缓存_local_modules未命中则在~/.paddlehub/modules/name目录下通过HubModule.load()加载并缓存若指定了source/branch还会校验与模块记录的一致性若本地未找到或版本不匹配则调用manager.install(...)默认从服务器下载module_server.search_module查询可用版本 → 校验环境兼容性不匹配时抛EnvironmentMismatchError除非ignore_env_mismatchTrue→ 从 URL 下载压缩包并解压安装_install_from_url→_install_from_archive→_install_from_directory若指定 Git 源_install_from_source会克隆/更新仓库、写入_source_info.yaml记录 source 与 branch、先安装requirements.txt依赖再加载模块安装完成后从规范化路径模块名中的-会被替换为_以符合 Python 命名规范见_get_normalized_name加载模块类并实例化。Module.load()module.py的加载逻辑也值得注意它优先检查目录下是否存在module_desc.pb描述文件存在则按旧版 ModuleV1 加载否则加载module.py通过 AST/反射查找被_hook_by_hub标记的类即被moduleinfo修饰的类并将directory、source、branch等元信息挂到类上后返回。若目录下是paddle.nn.Layer子类还会根据paddle.get_device()自动设置正确的设备以兼容多卡环境。成员函数模型导出与子模块管理save_inference_model导出 Paddle Inference 格式def save_inference_model( dirname: str, model_filename: str None, params_filename: str None, input_spec: List[paddle.static.InputSpec] None, include_sub_modules: bool True, combined: bool True):将模型导出为 Paddle Inference 推理格式。参数说明dirname保存推理模型的目录model_filename模型文件名默认__model__params_filename参数文件名仅在combinedTrue时生效默认__params__input_spec描述模型 forward 方法输入的规格可用InputSpec或示例 Tensor 描述若为 None则使用原始 Layer forward 方法的全部输入变量作为输入默认 Noneinclude_sub_modules是否同时导出子模块默认 Truecombined是否将所有参数合并保存为单一文件默认 True。源码实现module.py揭示了两个重要细节子模块递归导出当include_sub_modulesTrue时会对sub_modules()返回的每个子模块递归调用save_inference_model子目录路径由os.path.join(dirname, key)规范化得到单个子模块导出失败不会中断整体流程会通过utils.record_exception记录双路径支持若模块是paddle.nn.Layer动态图模型先自动推导input_spec——若类上定义了input_spec属性则直接使用否则当type以cv/image开头时自动使用[paddle.static.InputSpec(shape[None, 3, None, None], dtypefloat32)]作为默认图像输入其他类型则抛出RuntimeError提示必须在调用时显式指定input_spec。随后通过paddle.jit.to_staticpaddle.jit.save完成动转静导出若模块不是 Layer则走静态图路径先通过_pretrained_model_path属性定位预训练模型文件依次探测pretrained_model_path、rec_pretrained_model_path、default_pretrained_model_path、model_path等属性再用paddle.static.load_inference_model加载并调用paddle.static.save_inference_model保存。若模块没有任何预训练模型路径会抛出RuntimeError(Module ... does not support exporting models in Paddle Inference format.)。export_onnx_model导出 ONNX 格式def export_onnx_model( dirname: str, input_spec: List[paddle.static.InputSpec] None, include_sub_modules: bool True, **kwargs):将模型导出为 ONNX 格式。参数说明dirname保存 ONNX 模型的目录input_spec输入规格描述语义与save_inference_model相同默认 Noneinclude_sub_modules是否导出子模块默认 True**kwargs其他导出配置选项仅为兼容保留未来可能移除非必要不建议使用更详细配置可参考 PaddlePaddle 的 paddle2onnx 项目。源码实现module.py同样区分两条路径动态图 Layer 通过paddle.onnx.export(self, save_file, input_specinput_spec, **kwargs)直接导出静态图模块则先paddle.static.load_inference_model加载再调用paddle2onnx.program2onnx(program, scope, feed_var_names, target_vars, save_file, ...)完成转换输出文件名为dirname/模块名.onnx。sub_modules获取子模块def sub_modules(recursive: bool True):获取当前模块包含的所有子模块返回{属性名: 子模块对象}形式的字典。recursiveTrue默认时递归收集嵌套子模块的键名以/分隔如sub1/sub2。源码实现module.py遍历self.__dict__凡是RunModule或旧版ModuleV1的实例都会被收集同时跳过指向自身的引用id(item) id(self)避免自引用导致无限递归。该函数是save_inference_model与export_onnx_model递归导出子模块的基础。类方法依赖、加载与元信息get_py_requirementsclassmethod def get_py_requirements(cls) - List[str]:获取模块的 Python 包依赖列表。实现module.py读取模块所在目录下的requirements.txt文件按行拆分返回若文件不存在则返回空列表。在LocalModuleManager.install的安装流程中_install_module_requirements会通过pypi.install_from_file在加载模块前先安装这些依赖确保模块可正常导入。loadclassmethod def load(cls, directory: str) - Generic:加载指定目录下定义的 Module 对象返回的是模块类而非实例。这是整个加载链路的底层入口LocalModuleManager.search与Module.__new__最终都会调用它。其关键行为包括目录存在module_desc.pb时按 ModuleV1 加载否则加载目录/module.py并查找被moduleinfo标记的类加载失败时抛出InvalidHubModule(directory)异常提示is not a valid HubModule。load_module_infoclassmethod def load_module_info(cls, directory: str) - EasyDict:加载指定目录下模块的元信息返回EasyDict。与load的区别在于它只解析元数据、不实例化ModuleV1 走ModuleV1.load_module_infoV2 模块则通过ast解析module.py的抽象语法树从被moduleinfo修饰的类的装饰器关键字参数中提取name、version、author、author_email、summary、type等信息module.py。LocalModuleManager._install_from_directory正是用它先读取模块名再执行安装。属性一览官方文档为 Module 定义了以下属性属性说明is_runnable模块是否可运行即能否通过hub run命令执行。源码实现为模块是否存在被runnable标记的方法self._run_func不为空则返回 True。name模块名称。directory模块所在目录。version模块版本。type模块类型如nlp/sentiment_analysis、audio/asr、cv/image_classification。summary模块简介。author模块作者。author_email模块作者的邮箱。其中is_runnable的实现机制值得展开RunModule通过_get_func_name在当前类及其基类链中查找被注册到全局_module_runnable_func字典中的方法名module.py该字典由runnable装饰器在装饰时填充。hub run命令在执行前正是用module.is_runnable判断模块是否可执行见 paddlehub/commands/run.py不可执行时打印Module xxx is not executable.并返回失败。装饰器与自定义模块让普通类变成 HubModulepaddlehub.Module文档末尾的 note 明确指出Module 是用于自动下载和加载用户自定义模型类的工厂类除上述方法与属性外每个 Module 还有各自的自定义方法或属性。这些自定义能力来自配套的装饰器详见 docs/docs_en/api/module_decorator.rstmoduleinfodef paddlehub.module.module.moduleinfo( name: str, version: str, author: str None, author_email: str None, summary: str None, type: str None, metaNone) - Callable:为一个 Python 类标记模块信息被标记的类会自动扩展为继承RunModule即 HubModule 基类。换言之被moduleinfo修饰的 Python 类可以通过hub.Module加载。参数说明name模块名、version版本号、author作者、author_email作者邮箱、summary简介、type模块类型、meta可选的基类默认RunModule。源码实现module.py揭示了背后的类改写魔法_wrapper会动态创建一个继承自RunModule或meta指定的基类的新类将原类的方法与属性复制过去然后挂上name、version转为utils.Version对象、author、author_email、summary、type等类属性并打上_hook_by_hub True标记——这正是Module.load识别模块类的依据。runnabledef paddlehub.module.module.runnable(func: Callable) - Callable:将一个模块方法标记为可运行方法当使用hub run命令时该方法会被调用。实现上装饰器把模块名.方法名记录到全局_module_runnable_func字典并返回一个透传包装module.py。hub run module args时RunCommand.execute会调用module._run_func(argv[1:])即被标记的方法并将返回值打印run.py。示例见 modules/demo/senta_test/module.pyrun_cmd方法被runnable标记内部用argparse解析--input_text参数并调用预测逻辑。servingdef paddlehub.module.module.serving(func: Callable) - Callable:将一个模块方法标记为服务方法当使用hub serving命令时该方法会被调用。实现机制与runnable对称记录到_module_serving_func字典用于将模块包装为 HTTP 服务接口。仓库真实示例见 modules/audio/asr/deepspeech2_aishell/module.py其speech_recognize(audio_file, devicecpu)方法被serving标记可对外提供语音识别服务。完整实战从零定义一个可运行模块结合上文内容一个标准 PaddleHub 模块的目录结构通常包含module.py定义模块类用moduleinfo标记元信息用runnable/serving标记可执行/可服务方法requirements.txtPython 依赖列表会被get_py_requirements读取并在安装时自动安装模型权重文件、配置文件与词典等资源文件如modules/demo/senta_test/vocab.list。以仓库示例 modules/demo/senta_test/module.py 为蓝本import argparse import os import paddlehub as hub from paddlehub.module.module import runnable, moduleinfo from senta_test.processor import load_vocab moduleinfo( namesenta_test, version1.0.0, summaryThis is a PaddleHub Module. Just for test., authoranonymous, author_email, typenlp/sentiment_analysis, ) class SentaTest: def __init__(self): # 为 hub run 准备命令行参数解析 self.parser argparse.ArgumentParser( descriptionRun the senta_test module., proghub run senta_test, usage%(prog)s, add_helpTrue) self.parser.add_argument(--input_text, typestr, defaultNone, helptext to predict) # 加载词表资源 vocab_path os.path.join(self.directory, vocab.list) self.vocab load_vocab(vocab_path) def sentiment_classify(self, texts): results [] for text in texts: sentiment positive for word in self.vocab: if word in text: sentiment negative break results.append({text: text, sentiment: sentiment}) return results runnable def run_cmd(self, argvs): args self.parser.parse_args(argvs) texts [args.input_text] return self.sentiment_classify(texts)注意__init__中通过self.directory定位资源文件——该属性由Module.load在加载时注入到类上。定义好模块后即可在 Python 中按目录加载import paddlehub as hub senta_test hub.Module(directorysenta_test) print(senta_test.sentiment_classify([这部电影太糟糕了, 这部电影太棒了]))也可以使用hub run命令行执行被runnable标记的方法hub run senta_test --input_text 这部电影太棒了对于动态图模型paddle.nn.Layer子类可以进一步调用save_inference_model与export_onnx_model导出推理模型若模块类型为cv/image导出时即使不传input_spec也会自动使用[None, 3, None, None]的默认图像输入规格。小结paddlehub.Module是 PaddleHub 中连接模型资源与业务代码的枢纽moduleinfo让普通 Python 类升级为可被自动下载、加载的模块Module(name...)/Module(directory...)两个构造入口分别覆盖了线上资源与本地自定义两种场景runnable/serving装饰器打通了命令行与 HTTP 服务两种运行方式save_inference_model/export_onnx_model则让训练好的模块能够无缝迁移到 Paddle Inference 与 ONNX 推理生态。理解这一套 API 的底层实现工厂类分发、LocalModuleManager 单例管理、版本匹配与自动安装、AST 元信息解析将帮助你在 PaddleHub 生态中高效地开发、部署与集成自己的模型模块。如需进一步了解底层模块管理器与装饰器的细节可继续阅读 docs/docs_en/api/module_manager.rst 与 docs/docs_en/api/module_decorator.rst并在 modules/demo/senta_test/module.py、paddlehub/module/module.py 中对照源码实践。【免费下载链接】PaddleFormersPaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFormers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表