如何用PyInstaller打包Pickle序列化Sklearn模型EXE且不依赖Sklearn?
解决Pickle加载Voting Regressor模型时无需导入Sklearn打包EXE的问题
太懂你这种想压缩EXE体积的心情了——18MB和200MB的差别简直是天壤之别。先给你说透核心问题:Pickle根本不是用来打包依赖的,它只序列化了模型对象的结构和参数,加载时必须能找到原类的定义(也就是Sklearn的VotingRegressor),所以你没导入Sklearn的话,打包后运行肯定会报找不到模块的错。
下面给你三个可行的解决方案,按推荐程度排序:
1. 转成ONNX格式(最推荐,彻底脱离Sklearn)
ONNX是跨框架的模型格式,专门解决“模型部署脱离训练框架”的痛点。你只需要把训练好的Voting Regressor转成ONNX格式,用轻量的onnxruntime来推理,打包后的体积能控制在50MB以内,完全不需要Sklearn。
步骤1:训练时转换模型(仅需执行一次)
先安装依赖:
pip install onnx skl2onnx
然后运行转换代码:
from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import pickle # 加载你原有的Voting Regressor模型 model = pickle.load(open('vt_model.pkl', 'rb')) # 定义输入特征形状:你的模型是16个特征,所以设置为[None, 16](None表示支持批量预测) initial_type = [('float_input', FloatTensorType([None, 16]))] # 转换为ONNX格式 onnx_model = convert_sklearn(model, initial_types=initial_type) # 保存ONNX模型 with open('vt_model.onnx', 'wb') as f: f.write(onnx_model.SerializeToString())
步骤2:修改部署代码
把原来用Pickle加载模型和预测的部分替换成以下代码:
# 替换原有的import pickle和模型加载逻辑 import onnxruntime as rt import numpy as np # 仅需这个轻量库,比Sklearn小得多 # 加载ONNX模型 sess = rt.InferenceSession(resource_path('vt_model.onnx')) input_name = sess.get_inputs()[0].name output_name = sess.get_outputs()[0].name # 数据预处理、scaler转换部分保留不变 # ... 你的原有代码逻辑 ... # 将处理好的特征转换为numpy数组(ONNX要求数组输入) scale_array = scale_table # 这是你scaler.transform后的二维数组结果 pred_value = sess.run([output_name], {input_name: scale_array})[0] pred_value = int(np.round(pred_value[0]))
这样打包时只需要导入onnxruntime、PySimpleGUI等轻量库,体积会大幅下降,且完全脱离Sklearn依赖。
2. PyInstaller隐藏导入+裁剪Sklearn依赖(保留Pickle方案)
如果你不想更换模型格式,也可以让PyInstaller只打包Sklearn的必要部分,而非整个库。
打包命令示例:
pyinstaller --onefile --hidden-import sklearn.ensemble.VotingRegressor --exclude-module sklearn.datasets --exclude-module sklearn.utils.tests --exclude-module sklearn.dummy --exclude-module sklearn.svm test.py
--hidden-import:指定必须加载的Sklearn子模块(VotingRegressor属于sklearn.ensemble)--exclude-module:排除Sklearn中完全无用的部分,比如数据集、测试模块、示例模型等
这样打包后的体积大概会降到80-100MB,远小于全量导入Sklearn的大小。
3. 模型蒸馏(适合对精度要求不高的场景)
如果你的模型精度要求不是极端苛刻,可以用简单回归模型拟合Voting Regressor的输出:
- 用大量输入数据喂给原Voting Regressor,得到预测结果
- 把这些输入和预测结果作为新训练数据,训练一个轻量回归器(比如线性回归、小型决策树)
- 打包这个轻量模型,依赖会极小(比如仅需
sklearn.linear_model,体积非常小)
这个方法会损失少量精度,但胜在体积最小。
最后提醒
- ONNX转换时注意Sklearn版本兼容性,
skl2onnx对Sklearn 0.24-1.0版本支持较好 - 用PyInstaller裁剪依赖时,可添加更多
--exclude-module参数排除无用子模块,比如sklearn.metrics、sklearn.model_selection等
内容的提问来源于stack exchange,提问作者Polarbear1026
相关产品推荐
相关产品推荐

