用它包装的函数保存 sklearn `FunctionTransformer`
Saving an sklearn `FunctionTransformer` with the function it wraps
我正在使用 sklearn
的 Pipeline
和 FunctionTransformer
以及自定义函数
from sklearn.externals import joblib
from sklearn.preprocessing import FunctionTransformer
from sklearn.pipeline import Pipeline
这是我的代码:
def f(x):
return x*2
pipe = Pipeline([("times_2", FunctionTransformer(f))])
joblib.dump(pipe, "pipe.joblib")
del pipe
del f
pipe = joblib.load("pipe.joblib") # Causes an exception
我得到这个错误:
AttributeError: module '__ main__' has no attribute 'f'
如何解决这个问题?
请注意,此问题也发生在 pickle
我能够使用 marshal
模块(除了 pickle
)破解解决方案并覆盖 getstate
和 setstate
使用的魔法方法 pickle
.
import marshal
from types import FunctionType
from sklearn.base import BaseEstimator, TransformerMixin
class MyFunctionTransformer(BaseEstimator, TransformerMixin):
def __init__(self, f):
self.func = f
def __call__(self, X):
return self.func(X)
def __getstate__(self):
self.func_name = self.func.__name__
self.func_code = marshal.dumps(self.func.__code__)
del self.func
return self.__dict__
def __setstate__(self, d):
d["func"] = FunctionType(marshal.loads(d["func_code"]), globals(), d["func_name"])
del d["func_name"]
del d["func_code"]
self.__dict__ = d
def fit(self, X, y=None):
return self
def transform(self, X):
return self.func(X)
现在,如果我们使用 MyFunctionTransformer
而不是 FunctionTransformer
,代码将按预期工作:
from sklearn.externals import joblib
from sklearn.pipeline import Pipeline
@MyFunctionTransformer
def my_transform(x):
return x*2
pipe = Pipeline([("times_2", my_transform)])
joblib.dump(pipe, "pipe.joblib")
del pipe
del my_transform
pipe = joblib.load("pipe.joblib")
它的工作方式是从 pickle 中删除函数 f
,取而代之的是 marshaling
它的代码和名称。
dill
看起来也是一个不错的封送处理替代方案
我正在使用 sklearn
的 Pipeline
和 FunctionTransformer
以及自定义函数
from sklearn.externals import joblib
from sklearn.preprocessing import FunctionTransformer
from sklearn.pipeline import Pipeline
这是我的代码:
def f(x):
return x*2
pipe = Pipeline([("times_2", FunctionTransformer(f))])
joblib.dump(pipe, "pipe.joblib")
del pipe
del f
pipe = joblib.load("pipe.joblib") # Causes an exception
我得到这个错误:
AttributeError: module '__ main__' has no attribute 'f'
如何解决这个问题?
请注意,此问题也发生在 pickle
我能够使用 marshal
模块(除了 pickle
)破解解决方案并覆盖 getstate
和 setstate
使用的魔法方法 pickle
.
import marshal
from types import FunctionType
from sklearn.base import BaseEstimator, TransformerMixin
class MyFunctionTransformer(BaseEstimator, TransformerMixin):
def __init__(self, f):
self.func = f
def __call__(self, X):
return self.func(X)
def __getstate__(self):
self.func_name = self.func.__name__
self.func_code = marshal.dumps(self.func.__code__)
del self.func
return self.__dict__
def __setstate__(self, d):
d["func"] = FunctionType(marshal.loads(d["func_code"]), globals(), d["func_name"])
del d["func_name"]
del d["func_code"]
self.__dict__ = d
def fit(self, X, y=None):
return self
def transform(self, X):
return self.func(X)
现在,如果我们使用 MyFunctionTransformer
而不是 FunctionTransformer
,代码将按预期工作:
from sklearn.externals import joblib
from sklearn.pipeline import Pipeline
@MyFunctionTransformer
def my_transform(x):
return x*2
pipe = Pipeline([("times_2", my_transform)])
joblib.dump(pipe, "pipe.joblib")
del pipe
del my_transform
pipe = joblib.load("pipe.joblib")
它的工作方式是从 pickle 中删除函数 f
,取而代之的是 marshaling
它的代码和名称。
dill
看起来也是一个不错的封送处理替代方案