Qlib 如何保存并重新加载 DataHandler、Dataset 与 Model(Serializable 序列化)?
【免费下载链接】qlibQlib is an AI-oriented Quant investment platform that aims to use AI tech to empower Quant Research, from exploring ideas to implementing productions. Qlib supports diverse ML modeling paradigms, including supervised learning, market dynamics modeling, and RL, and is now equipped with https://github.com/microsoft/RD-Agent to automate R&D process.项目地址: https://gitcode.com/GitHub_Trending/qli/qlib
如果你需要把训练好的数据状态(例如归一化用到的参数)保存到磁盘,之后换一个新的时间窗口继续取数,或者把DataHandler、Dataset、Model的状态持久化后在新脚本中重新加载,Qlib 提供了统一的序列化机制:基类qlib.utils.serial.Serializable(实现见 qlib/utils/serial.py),它的状态可以以pickle格式 dump 到磁盘再 load 回来。官方文档见 docs/advanced/serial.rst,完整的可运行示例在 examples/highfreq/。
Serializable 机制:哪些内容会被保存
DataHandler、Dataset、Processor、Model等类都是qlib.utils.serial.Serializable的子类(例如 qlib/model/base.py 中BaseModel继承自Serializable)。dump 时的属性取舍规则是:
- 属性名不以
_开头→ 保存到磁盘;以_开头 → 默认不保存; - 用
config()方法、to_pickle()的 kwargs,或覆盖default_dump_all属性可以改变这个行为。to_pickle支持三个参数:dump_all(是否连_开头的属性一起保存)、exclude(强制不保存的属性列表)、include(强制保存的属性列表); pickle_backend属性可选"pickle"(默认)或"dill"(能序列化更多对象,例如函数)。
文档强调的一点是:以DatasetH为例,落盘的应该只是它的状态(state),比如数据归一化用到的mean和variance;数据本身不是状态,不应保存。
主路径:dump 与 reload 一个 DatasetH
docs/advanced/serial.rst 给出的最小用法:
##=============dump dataset============= dataset.to_pickle(path="dataset.pkl") # dataset is an instance of qlib.data.dataset.DatasetH ##=============reload dataset============= with open("dataset.pkl", "rb") as file_dataset: dataset = pickle.load(file_dataset)dataset.pkl是 dump 文件的路径,可替换成你需要的任意路径。
重新加载后:重置状态并重新生成数据
文档明确说明:reload 之后需要重新初始化——重置DataHandler或Dataset的一些状态(如instruments、start_time、end_time、segments),再按新状态生成数据。两个关键方法:
DataHandler.config(**kwargs):接受instruments、start_time、end_time,文档注释写明它是为「从磁盘 load handler 后按不同时间范围重新初始化数据」设计的(见 qlib/data/dataset/handler.py);DatasetH.config(handler_kwargs=..., segments=...)+DatasetH.setup_data(handler_kwargs=...):前者更新 handler 参数与分段,后者按init_type重新装载数据(见 qlib/data/dataset/init.py)。
examples/highfreq/workflow.py 中dump_and_load_dataset方法的完整做法(节选单个 dataset,原例中还有第二个dataset_backtest做同样处理):
from qlib.data.dataset.handler import DataHandlerLP from qlib.utils.pickle_utils import restricted_pickle_load ##=============reload dataset============= with open("dataset.pkl", "rb") as file_dataset: dataset = restricted_pickle_load(file_dataset) ##=============reinit dataset============= dataset.config( handler_kwargs={ "start_time": "2021-01-19 00:00:00", "end_time": "2021-01-25 16:00:00", }, segments={ "test": ( "2021-01-19 00:00:00", "2021-01-25 16:00:00", ), }, ) dataset.setup_data( handler_kwargs={ "init_type": DataHandlerLP.IT_LS, }, ) ##=============get data============= xtest = dataset.prepare("test")示例中原始数据集的时间范围是2020-09-15到2021-01-18(fit 窗口到2020-11-30),reload 后把窗口重置为2021-01-19到2021-01-25,即沿用已保存的归一化状态,对之后的新数据生成特征——这正是该机制的典型用途。上面的时间值来自示例,替换为你自己的窗口即可。
跑通仓库中的完整示例
examples/highfreq/ 提供了端到端示例,其中 dataset 实现为DatasetH。在examples/highfreq/目录下按顺序执行:
python workflow.py get_data这一步会先初始化 qlib(1min 频率、CN region 的HIGH_FREQ_CONFIG),并通过GetData().qlib_data(..., exists_skip=True)下载 1 分钟线数据——注意它是网络下载,数据已存在时会跳过。
python workflow.py dump_and_load_dataset这一步依次完成 dump 两个 dataset、reload、reinit,最后print(xtest, backtest_test)。示例输出就是prepare("test")返回的新窗口数据(文档未给出固定数值,判断标准是脚本正常跑完并打印出两个 DataFrame)。
需要注意:示例 reload 用的是restricted_pickle_load而不是裸的pickle.load。它是 qlib/utils/pickle_utils.py 提供的安全加载器,只允许白名单内的类(内置类型、datetime、pandas/numpy模块、qlib.data.dataset.handler.DataHandler/DataHandlerLP、StaticDataLoader等)参与反序列化,遇到非白名单类会抛出pickle.UnpicklingError,目的是防止 pickle 反序列化执行任意代码。如果你要加载的自定义类被拦截,文档提供了add_safe_class(module, name)扩展白名单,但源码注释提醒只添加你完全控制的类。
Model 与 DataHandler 的保存、加载
任意Serializable子类都可以走同一套接口,除了obj.to_pickle(path)+pickle.load的组合,基类还直接提供了:
SomeClass.load(filepath):类方法,load 后会校验实例是否为SomeClass的实例,不是则抛TypeError;Serializable.general_dump(obj, path):对象是Serializable时转调to_pickle,否则用普通pickle.dump落盘。
所以Model、DataHandler等与DatasetH使用相同的路径:dump 前可用to_pickle(path, exclude=[...])控制不落盘大对象,reload 后按需重置状态。
限制与注意点
- 数据不落盘:文档 note 明确「只有
DatasetH的状态应保存到磁盘」,数据不保存,reload 后必须通过config+setup_data重新生成; - 环境一致性:docs/component/recorder.rst 提到「Python objects are saved based on pickle, which may results in issues when the environment dumping objects and loading objects are different」——dump 环境与 load 环境不一致时 pickle 可能出问题,跨机器加载时留意版本依赖;
- 安全加载的白名单限制:
restricted_pickle_load只放行白名单类,自定义 handler/loader 需要时要用add_safe_class显式加入; - 示例
_prepare_calender_cache使用了 Linux 的 copy-on-write 特性加速日历缓存,源码注释说明它在 Windows 和 Mac OS 上可能无效。
【免费下载链接】qlibQlib is an AI-oriented Quant investment platform that aims to use AI tech to empower Quant Research, from exploring ideas to implementing productions. Qlib supports diverse ML modeling paradigms, including supervised learning, market dynamics modeling, and RL, and is now equipped with https://github.com/microsoft/RD-Agent to automate R&D process.项目地址: https://gitcode.com/GitHub_Trending/qli/qlib
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考