保存KerasClassifier模型https://github.com/keras-team/keras/blob/master/keras/wrappers/scikit_learn.py的权重和json配置后,我需要恢复它并验证结果。 但是,如果我恢复重量和模型,那么我就有一个序列对象,如何从中重建原始KerasClassifier?
答案 0 :(得分:1)
如果您有两个文件model.json和weights.h5,则可以轻松加载模型并根据需要使用它。
from keras.models import model_from_json
json_file = open('model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
loaded_model.load_weights("model.h5")
# evaluate loaded model on test data
loaded_model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
score = loaded_model.evaluate(X, Y, verbose=0)
print("%s: %.2f%%" % (loaded_model.metrics_names[1], score[1]*100))
答案 1 :(得分:1)
我不确定我是否正确理解您,但请提出以下解决方案。 KerasClassifier
继承自具有以下BaseWrapper
签名的__init__
:
def __init__(self, build_fn=None, **sk_params):
self.build_fn = build_fn
self.sk_params = sk_params
self.check_params(sk_params)
好的,什么是build_fn和sk_params?
build_fn
应该构造,编译并返回Keras模型,该模型 然后将用于拟合/预测。以下之一 三个值可以传递给build_fn
:
1.功能
2.实现__call__
方法的类的实例
3.没有。这意味着您要实现一个继承自任一类的类
KerasClassifier
或KerasRegressor
。的__call__
方法 当前类将被视为默认的build_fn
。
...
sk_params
同时使用模型参数和拟合参数。法律模式 参数是build_fn
的参数。请注意,就像其他所有 scikit-learnbuild_fn
中的估算器应为 它的参数,以便您可以创建估算器而无需传递任何 值sk_params
。
...
省略了一些
您可以在this和this链接上阅读完整的评论。
由于build_fn
期望函数返回已编译的keras模型(无论是Sequential
还是Model
),您可以将其作为值函数传递,该函数返回已加载的模型。
编辑,您还应该使用一些参数调用fit
,以使用该方法恢复模型。
将模型加载为build_fn
fit
方法将调用build_fn
,因此,每次尝试训练此类分类器时,都会加载然后适合已加载的clssifier。
例如:
from keras.models import load_model # or another method - but this one is simpliest
from keras.wrappers.scikit_learn import KerasClassifier
def load_model(*args, **kwargs):
"""probably this function expects sk_params, so you can use it in theory"""
path="my_model.hd5"
model = load_model(path)
return model
keras_classifier = KerasClassifier(load_model, sk_params) # use your sk_params
keras_classifier.fit(X_tr, y_tr) # I use slice (1, input_shape) to train
-它会起作用,因为已加载的模型几乎已经过训练和编译。但是,即使您以1的大小和1个时期的批处理来调用它,它也会给您的模型带来很小的变化。
通过build_fn闭包加载
此外,您可以先加载模型(如果您希望轻松提供路径并且硬编码路径不可接受),然后返回“ build_fn-可接受” 的函数:
def load_model_return_build_fn(path):
model = load_model(path)
def build_fn(*args, **kwars):
"""probably this function expects sk_params"""
return model # defined above
return build_fn
build_fn = load_model_return_build_fn("model.hd5")
keras_classifier = KerasClassifier(build_fn, sk_params) # use your sk_params
keras_classifier.fit(X_tr, y_tr) # I use slice (1, input_shape) to train
为模型分配属性
如果您计划仅加载并使用预训练的模型,则可以使用any加载它,将其分配给model
属性,然后不要调用fit
。
build_fn = load_model_return_build_fn("model.hd5")
# or the function which realy builds and fits a model
keras_classifier = KerasClassifier(build_fn, sk_params) # use your sk_params
keras_classifier.model = model # assign model here, don't call fit
-在这种情况下,您将模型明确设置为其属性。请注意,build_fn应该是一个正确的build_fn-否则它不会通过self.check_params(sk_params)
测试。
从KerasClassifier继承(不是我想象的那么容易)
毕竟,我知道最好的解决方案是从KerasClassifier
继承并添加load
和/或from_file
方法。
class KerasClassifierLoadable(KerasClassifier):
@classmethod
def from_file(cls, path, *args, **kwargs):
keras_classifier = cls(*args, **kwargs)
keras_classifier.model = load_model(path)
outp_shape = keras_classifier.model.layers[-1].output_shape[-1]
if outp_shape > 1:
keras_classifier.classes_ = np.arange(outp_shape, dtype='int32')
else:
raise ValueError("Inconsistent output shape: outp_shape={}".format(outp_shape))
keras_classifier.n_classes_ = len(keras_classifier.classes_)
return keras_classifier
def load(self, path):
self.model = load_model(path)
outp_shape = keras_classifier.model.layers[-1].output_shape[-1]
if outp_shape > 1:
keras_classifier.classes_ = np.arange(outp_shape, dtype='int32')
else:
raise ValueError("Inconsistent output shape: outp_shape={}".format(outp_shape))
self.n_classes_ = len(self.classes_)
在这里,我们应该将self.classes_设置为正确的类标签-但我只使用来自range(0,n_classes)的整数值。
用法(build_fn
可以是任何合适的build_fn
):
keras_classifier = KerasClassifierLoadable.from_file("model.hd5", build_fn=build_fn)
keras_classifier = KerasClassifierLoadable(build_fn=build_fn)
keras_classifier.load("model.hd5")