我想将 sklearn 管道保存到磁盘,包括自定义预处理和 RandomForestClassifier 以及保存文件中的所有依赖项。没有此功能,我必须将所有依赖项(自定义模块)复制到我想调用的任何地方的同一文件夹中这个模型(在我的情况下是在远程服务器上)。
预处理器在一个类中定义,该类位于我项目的同一文件夹中的另一个文件 ( preprocessing.py ) 中。所以我可以通过import访问它。
培训.py
from preprocessing import Preprocessor
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
import pickle
clf = Pipeline([
("preprocessing", Preprocessor()),
("model", RandomForestClassifier())
])
# some fitting of the classifier
# ...
# Export
with open(savepath, "wb") as handle:
pickle.dump(clf, handle, protocol=pickle.HIGHEST_PROTOCOL)
Run Code Online (Sandbox Code Playgroud)
我尝试了泡菜(及其一些变体)、莳萝和 joblib,但这不起作用。当我在其他地方导入 .pkl 时(比如在我的远程服务器上)。我必须在架构中有一个相同的preprocessing.py ......这很痛苦。
我希望在其他地方有另一个文件:
remote.py
import pickle
with open(savepath, "rb") as handle:
model = pickle.load(handle)
print(model.predict(some_matrix))
Run Code Online (Sandbox Code Playgroud)
但是这段代码目前给了我一个错误,因为它没有找到预处理器类......
问题
假设我有这个模块名为custom_module
:
class CustomClass:
pass
Run Code Online (Sandbox Code Playgroud)
我在脚本中使用此类来序列化我在以下位置定义的类的对象custom_module
:
import cloudpickle
import custom_module as cm
custom_object = cm.CustomClass()
with open('filename.pkl', 'wb') as file:
cloudpickle.dump(custom_object, file)
Run Code Online (Sandbox Code Playgroud)
我将此 pickle 文件复制到另一个环境并使用另一个脚本加载它:
import cloudpickle
with open('filename.pkl', 'rb') as file:
custom_object = cloudpickle.load(file)
Run Code Online (Sandbox Code Playgroud)
这会产生这个错误:
Traceback (most recent call last):
File "loader.py", line 4, in <module>
custom_object = cloudpickle.load(file)
ModuleNotFoundError: No module named 'custom_module'
Run Code Online (Sandbox Code Playgroud)
尴尬的解决方案
作为解决方法,可以读取并执行custom_module
脚本中的所有内容:
exec(open(path.join('custom_module.py')).read())
Run Code Online (Sandbox Code Playgroud)
但这看起来真的很奇怪,我不能使用 CustomClass 作为cm.CustomClass
. 是否有其他解决方案不涉及将第一个环境中的所有代码复制到第二个环境中?