Serialization 定制scikit学习酸洗不';不能在网格搜索中工作
我已经写了一个scikit学习估计器。它有一个参数和一个由Serialization 定制scikit学习酸洗不';不能在网格搜索中工作,serialization,scikit-learn,keras,pickle,Serialization,Scikit Learn,Keras,Pickle,我已经写了一个scikit学习估计器。它有一个参数和一个由fit设置的model属性 class MyEstimator(BaseEstimator, TransformerMixin): def __init__(self, param="default"): self.param = param self.model_ = None def fit(self, x, y): # Sets the value of self.m
fit
设置的model
属性
class MyEstimator(BaseEstimator, TransformerMixin):
def __init__(self, param="default"):
self.param = param
self.model_ = None
def fit(self, x, y):
# Sets the value of self.model_
我希望能够pickleMyEstimator
,但是我创建的model\uu
对象不能用pickle序列化,因为它是一个模型。按照博客文章“”的示例,我向类中添加了以下pickling处理程序方法
class MyEstimator(BaseEstimator, TransformerMixin):
def __getstate__(self):
state = super().__getstate__().copy()
with tempfile.NamedTemporaryFile(suffix=".hdf5", delete=True) as fd:
keras.models.save_model(self.model_, fd.name, overwrite=True)
state["model_"] = fd.read()
return state
def __setstate__(self, state):
super().__setstate__(state)
with tempfile.NamedTemporaryFile(suffix=".hdf5", delete=True) as fd:
fd.write(state["model_"])
fd.flush()
self.__dict__["model_"] = keras.models.load_model(fd.name)
这将用keras的序列化程序生成的可pickle的表示形式替换不可pickle的模型
成员。使用这种定制,我可以调用fit
,序列化和反序列化,并返回我的原始模型。一切正常
e = MyEstimator()
e.fit(x, y)
with open("myfile.pk", mode="wb") as f:
pickle.dump(e, f)
with open("myfile.pk", mode="rb") as f:
pickle.load(f) # Returns a copy of e
但是,当我试图将MyEstimator放入a中并对a的结果进行pickle处理时,序列化不起作用
在pickle.dump
调用过程中,我希望看到MyEstimator.\uuuuu getstate\uuuu
使用一个合适的self.model\uu
对象调用。(这是我在网格搜索之外单独序列化模型时发生的情况。)相反,self.model
是None
,因此我无法序列化网格搜索生成的best\u estimator
看起来网格搜索序列化正在实例化一个新的MyEstimator
对象,而不是使用管道中的对象。我觉得这是不对的。我已经浏览了scikit学习代码,但看不出这是在哪里发生的
这是scikit learn中的一个bug,还是我做错了什么
(注意:keras确实有一个可以将某些keras模型转换为scikit学习估计器的方法,但出于其他原因,我不能在这里使用它,我不确定它是否会有相同的问题。)搜索对象包含一个混合的
MyEstimator
对象,其中一些对象没有调用fit
。修复方法是在尝试使用keras工具序列化之前,检查model_uu
是否为None
class MyEstimator(BaseEstimator, TransformerMixin):
def __getstate__(self):
state = super().__getstate__().copy()
if self.model_ is not None:
with tempfile.NamedTemporaryFile(suffix=".hdf5", delete=True) as fd:
keras.models.save_model(self.model_, fd.name, overwrite=True)
state["model_"] = fd.read()
return state
def __setstate__(self, state):
super().__setstate__(state)
if self.model_ is not None:
with tempfile.NamedTemporaryFile(suffix=".hdf5", delete=True) as fd:
fd.write(state["model_"])
fd.flush()
self.__dict__["model_"] = keras.models.load_model(fd.name)
我不知道为什么在网格搜索完成后,搜索对象中会有任何不适合的模型,但确实有。看看这一点:大多数scikit中的模型评估工具,如
cross\u val\u score
,GridSearchCV
等,都会在拟合之前克隆给定的估计器。在GridSearchCV中,您可以看到它克隆了它。指出特定的源代码行会有所帮助。我在调试器中单步执行此过程时迷路了。我不明白为什么搜索完成后会有任何克隆没有调用fit
。你是在尝试pickle整个GridSearchCV
对象,还是仅仅是GridSearchCV。最佳估计器(基本上就是你想要的)我正在尝试pickle整个搜索对象。我知道,GridSearchCV.best_estimator\u
是我在测试时使用的,但我也想比较各种超参数设置的交叉验证分数。
class MyEstimator(BaseEstimator, TransformerMixin):
def __getstate__(self):
state = super().__getstate__().copy()
if self.model_ is not None:
with tempfile.NamedTemporaryFile(suffix=".hdf5", delete=True) as fd:
keras.models.save_model(self.model_, fd.name, overwrite=True)
state["model_"] = fd.read()
return state
def __setstate__(self, state):
super().__setstate__(state)
if self.model_ is not None:
with tempfile.NamedTemporaryFile(suffix=".hdf5", delete=True) as fd:
fd.write(state["model_"])
fd.flush()
self.__dict__["model_"] = keras.models.load_model(fd.name)