使用lzma压缩保存Scikit-learn Pipeline后加载出现EOFError求助
问题描述
我有一个Scikit-learn Pipeline,使用以下代码进行序列化:
with lzma.open('outputs/baseModel_LR.joblib',"wb") as f: dill.dump(pipeline, f)
当尝试用以下代码加载该Pipeline时:
with lzma.open('outputs/baseModel_LR.joblib',"rb") as f: model = dill.load(f)
出现如下错误:
--------------------------------------------------------------------------- EOFError Traceback (most recent call last) somePath/notebooks/test.ipynb Cell 5 in <cell line: 1>() 1 with lzma.open('outputs/baseModel_LR.joblib',"rb") as f: ----> 2 model = dill.load(f) 3 model File /anaconda/envs/azureml_py38/lib/python3.8/site-packages/dill/_dill.py:373, in load(file, ignore, **kwds) 367 def load(file, ignore=None, **kwds): 368 """ 369 Unpickle an object from a file. 370 371 See :func:`loads` for keyword arguments. 372 """ --> 373 return Unpickler(file, ignore=ignore, **kwds).load() File /anaconda/envs/azureml_py38/lib/python3.8/site-packages/dill/_dill.py:646, in Unpickler.load(self) 645 def load(self): #NOTE: if settings change, need to update attributes --> 646 obj = StockUnpickler.load(self) 647 if type(obj).__module__ == getattr(_main_module, '__name__', '__main__'): 648 if not self._ignore: 649 # point obj class to main File /anaconda/envs/azureml_py38/lib/python3.8/lzma.py:200, in LZMAFile.read(self, size) 194 """Read up to size uncompressed bytes from the file. ... 100 "end-of-stream marker was reached" 101 else: 102 rawblock = b"" **EOFError: Compressed file ended before the end-of-stream marker was reached**
由于未压缩的joblib文件大小为27GB,压缩后仅20MB,所以选择使用lzma,求解决该加载错误的方法。
可行的解决方法
检查文件完整性:先确认压缩文件未损坏,可对比保存前后的文件大小,或用命令行工具尝试解压验证:
lzma -d outputs/baseModel_LR.joblib若解压失败,说明文件已损坏,需重新序列化保存。
使用joblib自带的lzma压缩:joblib原生支持lzma压缩,无需手动嵌套lzma文件流,兼容性更强,代码如下:
# 保存模型 import joblib joblib.dump(pipeline, 'outputs/baseModel_LR.joblib', compress='lzma') # 加载模型 model = joblib.load('outputs/baseModel_LR.joblib')这种方式会自动处理压缩的细节,避免手动操作文件流可能出现的截断问题。
确保文件流正确关闭:如果坚持使用dill+lzma的组合,保存时可手动刷新文件流,确保数据完全写入:
with lzma.open('outputs/baseModel_LR.joblib',"wb") as f: dill.dump(pipeline, f) f.flush()保存完成后,可立即尝试加载一次,验证文件是否正常生成。
分块序列化(备选):针对超大型模型,可考虑分块保存,但joblib的lzma压缩已经能很好处理大文件,优先尝试前面的方法。
内容的提问来源于stack exchange,提问作者Obiii
相关产品推荐
相关产品推荐

