3

当我在 linux (x86-64) 中反序列化已在 os-x (darwin) 上序列化的causalml (0.10.0) 模型时,出现以下错误:

ValueError: numpy.ndarray size changed, may indicate binary incompatibility.

出乎意料的是,尝试在同一个 python 会话中再次反序列化它确实成功了!

环境

在序列化机器上:

  • Python 3.8,一首诗 .venv
  • numpy 1.18.5(兼容 causalml 0.10.0 的最新版本)
  • 操作系统-x

在反序列化机器上:

  • 基于 AWS lambda python 3.8 的 docker
  • 蟒蛇 3.8
  • linux x86_64

两者都有cython版本0.28causalml版本0.10.0

使用cython版本0.29.26(根据pip兼容),重新运行不成功。

错误在causaltree.cpython-38-x86_64-linux-gnu.so .

Joblib 或 Pickle

我尝试了 python 的picklejoblib,都引发了错误。

在使用 joblib 的情况下,会发生以下堆栈跟踪:

File "/var/task/joblib/numpy_pickle.py", line 577, in load
    obj = _unpickle(fobj)
  File "/var/task/joblib/numpy_pickle.py", line 506, in _unpickle
    obj = unpickler.load()
  File "/var/lang/lib/python3.8/pickle.py", line 1212, in load
    dispatch[key[0]](self)
  File "/var/lang/lib/python3.8/pickle.py", line 1537, in load_stack_global
    self.append(self.find_class(module, name))
  File "/var/lang/lib/python3.8/pickle.py", line 1579, in find_class
    __import__(module, level=0)
  File "/var/task/causalml/inference/tree/__init__.py", line 3, in <module>
    from  .causaltree import CausalMSE, CausalTreeRegressor
  File "__init__.pxd", line 238, in init causalml.inference.tree.causaltree

使用更新的 python 版本

其他答案提到升级(在反序列化环境中)到更新的 numpy,它应该是向后兼容的,可能会有所帮助。就我而言,它没有帮助。

安装 causalml 后,我pip3 install --upgrade numpy==XXX在反序列化机器上单独替换了 numpy 版本。

  • 对于 numpy1.18.51.19.5,错误提到:Expected 96 from C header, got 80 from PyObject
  • 使用 numpy 1.20.3,错误提到:Expected 96 from C header, got 88 from PyObject

其他 numpy 数组可以序列化和反序列化吗?:是的

为了验证 numpy 序列化和反序列化是否真的可行,我测试了序列化一个随机数组(使用picklejoblib

with open(str(path / "numpy.pkl"), "wb") as f:
    pickle.dump(object, f, protocol=5)

with open(str(path / "numpy.joblib"), "wb") as f:
    joblib.dump(object, f, compress=True)

这些实际上反序列化没有错误:

with open(str(path / "numpy.pkl"), "rb") as f:
    read_object = pickle.load(f)

with open(str(path / "numpy.pkl"), "rb") as f:
    read_object = joblib.load(f)

麻木源

如果我查看这一行numpy的源代码,似乎只有在检索到的大小大于预期大小时才会引发错误。

其他一些(较旧的)stackoverflow 答案提到可以按如下方式使警告静音。但也没有帮助:

import warnings;
warnings.filterwarnings("ignore", message="numpy.dtype size changed");
warnings.filterwarnings("ignore", message="numpy.ufunc size changed");

尝试两次解决了它 我找到了解决这个问题的一种方法:在同一个 python 会话中,两次加载序列化模型。第一次引发错误,第二次没有。

然后,加载的模型会按预期运行。

怎么了?有没有办法让它第一次成功?

4

0 回答 0