假设我有两个项目:
train_project:其中包含src.feature_extraction.transformers.py中的定制transformer。 use_project:其中包含其他事物的src目录,或者根本没有src目录。
如果在“train_project”中使用joblib.dump()保存pipeline,然后在“use_project”中使用joblib.load()加载它,它将无法找到“src.feature_extraction.transformers”之类的内容,并抛出异常:
ModuleNotFoundError: No module named 'src.feature_extraction'
我还应该补充一点,从一开始我的意图就是简化模型的使用,使程序员可以像使用其他模型一样加载模型,传递非常简单且易于阅读的特征,所有特征的“魔术”预处理(例如梯度提升)都在实际模型内部发生。
我考虑创建/dependencies/xxx_model/目录,将所有所需的类和函数存储在两个项目的根目录下(将代码从“train_project”复制到“use_project”),以使项目结构相同并可以加载transformer。但我认为这种解决方案非常不优雅,因为它会强制使用模型的任何项目的结构。
我想只需在“use_project”中重新创建pipeline和所有transformers,并以某种方式加载“train_project”中的拟合值即可。
最好的解决方案是如果保存的文件包含所有所需信息并且不需要依赖项,我真的很震惊sklearn.Pipelines似乎没有这种可能性——如果我不能在以后加载已拟合的对象,那么管道的拟合有什么意义呢?是的,如果我仅使用sklearn类而不创建自定义类,则它将起作用,但非自定义类没有所有所需的功能。
示例代码:
train_project
src.feature_extraction.transformers.py
from sklearn.pipeline import TransformerMixin
class FilterOutBigValuesTransformer(TransformerMixin):
def __init__(self):
pass
def fit(self, X, y=None):
self.biggest_value = X.c1.max()
return self
def transform(self, X):
return X.loc[X.c1 <= self.biggest_value]
训练项目
main.py
from sklearn.externals import joblib
from sklearn.preprocessing import MinMaxScaler
from src.feature_extraction.transformers import FilterOutBigValuesTransformer
pipeline = Pipeline([
('filter', FilterOutBigValuesTransformer()),
('encode', MinMaxScaler()),
])
X=load_some_pandas_dataframe()
pipeline.fit(X)
joblib.dump(pipeline, 'path.x')
test_projectmain.py
from sklearn.externals import joblib
pipeline = joblib.load('path.x')
期望的结果是管道已正确加载,可以使用转换方法。
实际结果是加载文件时出现异常。