sklearn RandomForest模型上32- / 64位序列化异常的解决方法

Vin*_*lar 5 python pickle random-forest scikit-learn joblib

如果我们在64位计算机上使用joblib序列化randomforest模型,然后在32位计算机上解压缩,则会出现异常:

ValueError: Buffer dtype mismatch, expected 'SIZE_t' but got 'long long'
Run Code Online (Sandbox Code Playgroud)

之前曾有人问过这个问题:Scikits-Learn RandomForrest在64位python上受过训练,不会在32位python上打开。但是自2014年以来,这个问题一直没有得到回答。

学习模型的示例代码(在64位计算机上):

modelPath="../"
featureVec=...
labelVec = ...
forest = RandomForestClassifier()
randomSearch = RandomizedSearchCV(forest, param_distributions=param_dict, cv=10, scoring='accuracy',
                                      n_iter=100, refit=True)
randomSearch.fit(X=featureVec, y=labelVec)
model = randomSearch.best_estimator_
joblib.dump(model, modelPath)
Run Code Online (Sandbox Code Playgroud)

在32位计算机上解压缩的示例代码:

modelPath="../"
model = joblib.load(modelPkl) # ValueError thrown here
Run Code Online (Sandbox Code Playgroud)

我的问题是:如果我们必须在64位计算机上学习并将其移植到32位计算机上进行预测,那么是否有针对该问题的通用解决方法?

编辑:尝试直接使用pickle而不是joblib。仍然存在相同的错误。错误发生在核心pickle库中(对于joblib和pickle):

  File "/usr/lib/python2.7/pickle.py", line 1378, in load
    return Unpickler(file).load()
  File "/usr/lib/python2.7/pickle.py", line 858, in load
    dispatch[key](self)
  File "/usr/lib/python2.7/pickle.py", line 1133, in load_reduce
    value = func(*args)
  File "sklearn/tree/_tree.pyx", line 585, in sklearn.tree._tree.Tree.__cinit__ (sklearn/tree/_tree.c:7286)
ValueError: Buffer dtype mismatch, expected 'SIZE_t' but got 'long long'
Run Code Online (Sandbox Code Playgroud)

Ale*_*yes 0

我有类似的东西,我想在 64 位 Ubuntu 机器上训练并在旧的 32 位 Raspberry Pi 上运行。

就我而言,我使用 scikit-learn 进行训练,但使用treelite.

在我的 64 位机器上,我训练了 aRandomForestClassifier并导出了 a model.zip

from sklearn.ensemble import RandomForestClassifier
import treelite
import numpy as np

X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype='float32')
y = np.array([0, 1, 1, 0], dtype='float32')

clf = RandomForestClassifier(n_estimators=10).fit(X, y)

# Requires `scikit-learn==1.1.0` currently:
model = treelite.sklearn.import_model_with_model_builder(clf)
model.export_srcpkg(platform="unix", toolchain="gcc",
                    pkgpath="./mymodel.zip", libname="mymodel.so")
Run Code Online (Sandbox Code Playgroud)

然后转移model.zip到我的 32 位 Raspberry Pi 后:

unzip model.zip
cd mymodel/
make
Run Code Online (Sandbox Code Playgroud)
import numpy as np
import treelite

X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype='float32')
dmat = treelite_runtime.DMatrix(X)

predictor = treelite_runtime.Predictor("mymodel.so", verbose=True)
print(predictor.predict(dmat))
#     [0.3 0.5 0.6 0.2]
#     This would be the same as: `clf.predict_proba(X)[:, 1]`
Run Code Online (Sandbox Code Playgroud)

32 位 Raspberry Pi 的具体注意事项

如果将来有人尝试在 32 位 Raspberry Pi 上运行它,则需要执行一些额外的步骤,因为它是非标准平台。numpy==1.23.5以下是我为使用 Python 3.10.6 、、、scipy==1.9.3以及treelite-runtime==3.0.1ARMv7 处理器 rev 4 (v7l)/Raspberry Pi 3 Model B运行所做的操作。

  1. 设置依赖项:
sudo apt install gcc g++ gfortran python3-dev python3-venv make cmake ninja-build pkg-config autoconf
Run Code Online (Sandbox Code Playgroud)
  1. 增加要编译的交换空间的大小scipy(您可以获得numpy和的预构建轮子scipy,为了完整起见,此处附注。基于此答案):
sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
sudo /sbin/mkswap /var/swap.1
sudo chmod 600 /var/swap.1
sudo /sbin/swapon /var/swap.1
Run Code Online (Sandbox Code Playgroud)
  1. Python环境
python3 -m venv venv
source venv/bin/activate
pip install scipy==1.9.3 numpy==1.23.5 treelite-runtime==3.0.1
Run Code Online (Sandbox Code Playgroud)
  1. 编译模型(与之前重复)
unzip model.zip
cd mymodel/
make
Run Code Online (Sandbox Code Playgroud)