Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将Scikit Learn Keras模型保存到持久性文件(pickle/hd5/json/yaml)_Python_Scikit Learn_Persistence_Pickle_Keras - Fatal编程技术网

Python 如何将Scikit Learn Keras模型保存到持久性文件(pickle/hd5/json/yaml)

Python 如何将Scikit Learn Keras模型保存到持久性文件(pickle/hd5/json/yaml),python,scikit-learn,persistence,pickle,keras,Python,Scikit Learn,Persistence,Pickle,Keras,我使用以下代码: 如代码中所述,它在该行失败: pickle.dump(model_tt, open(filename, 'wb')) 出现此错误时: pickle.PicklingError: Can't pickle <function create_model at 0x101c09320>: it's not found as __main__.create_model pickle.PicklingError:无法pickle:找不到它作为\uuuu main\uuuu

我使用以下代码:

如代码中所述,它在该行失败:

pickle.dump(model_tt, open(filename, 'wb'))
出现此错误时:

pickle.PicklingError: Can't pickle <function create_model at 0x101c09320>: it's not found as __main__.create_model
pickle.PicklingError:无法pickle:找不到它作为\uuuu main\uuuu.create\u模型

我怎样才能避开它?

编辑1:关于保存模型的原始答案

对于HDF5:

# saving model
json_model = model_tt.model.to_json()
open('model_architecture.json', 'w').write(json_model)
# saving weights
model_tt.model.save_weights('model_weights.h5', overwrite=True)


# loading model
from keras.models import model_from_json

model = model_from_json(open('model_architecture.json').read())
model.load_weights('model_weights.h5')

# dont forget to compile your model
model.compile(loss='binary_crossentropy', optimizer='adam')
编辑2:iris数据集的完整代码示例

# Train model and make predictions
import numpy
import pandas
from keras.models import Sequential, model_from_json
from keras.layers import Dense
from keras.utils import np_utils
from sklearn import datasets
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

# load dataset
iris = datasets.load_iris()
X, Y, labels = iris.data, iris.target, iris.target_names
X = preprocessing.scale(X)

# encode class values as integers
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)

# convert integers to dummy variables (i.e. one hot encoded)
y = np_utils.to_categorical(encoded_Y)

def build_model():
    # create model
    model = Sequential()
    model.add(Dense(4, input_dim=4, init='normal', activation='relu'))
    model.add(Dense(3, init='normal', activation='sigmoid'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

def save_model(model):
    # saving model
    json_model = model.to_json()
    open('model_architecture.json', 'w').write(json_model)
    # saving weights
    model.save_weights('model_weights.h5', overwrite=True)

def load_model():
    # loading model
    model = model_from_json(open('model_architecture.json').read())
    model.load_weights('model_weights.h5')
    model.compile(loss='categorical_crossentropy', optimizer='adam')
    return model


X_train, X_test, Y_train, Y_test = train_test_split(X, y, test_size=0.3, random_state=seed)

# build
model = build_model()
model.fit(X_train, Y_train, nb_epoch=200, batch_size=5, verbose=0)

# save
save_model(model)

# load
model = load_model()

# predictions
predictions = model.predict_classes(X_test, verbose=0)
print(predictions)
# reverse encoding
for pred in predictions:
    print(labels[pred])
请注意,我只使用了Keras,没有使用包装。它只会在一些简单的事情上增加一些复杂性。此外,代码是自愿性的,不考虑因素,因此您可以了解整个情况


另外,您说过要输出1或0。这在这个数据集中是不可能的,因为您有3个输出DIM和类(Iris setosa、Iris versicolor、Iris virginica)。如果您只有2个类,那么使用sigmoid output Function,您的输出dim和类将是0或1。

只是添加到gaarv的答案中-如果您不需要在模型结构(
model.to_json()
)和权重(
model.save_weights()
)之间进行分离,您可以使用以下选项之一:

  • 使用内置的
    keras.models.save_model
    和“keras.models.load_model”将所有内容存储在一个hdf5文件中
  • 使用pickle将模型对象(或包含对其引用的任何类)序列化为文件/网络/任何..
    不幸的是,Keras默认不支持pickle。你可以用 我的补丁解决方案添加了这一缺失的功能。工作代码是 在这里:

另一个很好的选择是在您的
适合您的型号时使用。特别是回调,如下所示:

从keras.callbacks导入模型检查点
#创建ModelCheckpoint的实例
chk=ModelCheckpoint(“myModel.h5”,monitor='val\u loss',save\u best\u only=False)
#将该回调添加到要传递的回调列表中
回调\u列表=[chk]
#创建您的模型
模型tt=KerasClassifier(构建fn=create模型,nb时代=150,批量大小=10)
#使您的模型符合您的数据。将回调传递到此处
模型拟合(X列,y列,回调=回调列表)
这将把每个历元的训练保存到
myModel.h5
文件中。这提供了巨大的好处,因为你可以在你想要的时候停止训练(比如当你看到训练开始过度时),并且仍然保持以前的训练

请注意,这将结构和权重保存在相同的
hdf5
文件中(如Zach所示),因此您可以使用
keras.models.load\u model
加载模型

如果只想单独保存权重,则可以在实例化
ModelCheckpoint
时使用
save\u weights\u only=True
参数,以便按照Gaarv的说明加载模型。从中提取:

仅保存权重:如果为True,则仅保存模型的权重(model.save\u weights(filepath)),否则保存完整模型(model.save(filepath))


公认的答案太复杂了。您可以在
.h5
文件中完全保存和恢复模型的各个方面。直截了当地说:

您可以使用
model.save(filepath)
将Keras模型保存到单个 包含以下内容的HDF5文件:

  • 模型的体系结构,允许重新创建模型
  • 模型的权重
  • 培训配置(丢失、优化器)
  • 优化器的状态,允许在您停止的位置恢复培训
然后可以使用
keras.models.load\u model(filepath)
重新实例化模型
load_model
还将负责使用保存的培训配置编译模型(除非一开始从未编译过模型)

以及相应的代码:

from keras.models import load_model

model.save('my_model.h5')  # creates a HDF5 file 'my_model.h5'
del model  # deletes the existing model

# returns a compiled model identical to the previous one
model = load_model('my_model.h5')

如果您的keras包装器模型在scikit管道中,您可以单独保存管道中的步骤

import joblib
from sklearn.pipeline import Pipeline
from tensorflow import keras

# pass the create_cnn_model function into wrapper
cnn_model = keras.wrappers.scikit_learn.KerasClassifier(build_fn=create_cnn_model)

# create pipeline
cnn_model_pipeline_estimator = Pipeline([
    ('preprocessing_pipeline', pipeline_estimator),
    ('clf', cnn_model)
])

# train model
final_model = cnn_model_pipeline_estimator.fit(
X, y, clf__batch_size=32, clf__epochs=15)

# collect the preprocessing pipeline & model seperately
pipeline_estimator = final_model.named_steps['preprocessing_pipeline']
clf = final_model.named_steps['clf']

# store pipeline and model seperately
joblib.dump(pipeline_estimator, open('path/to/pipeline.pkl', 'wb'))
clf.model.save('path/to/model.h5')

# load pipeline and model
pipeline_estimator = joblib.load('path/to/pipeline.pxl')
model = keras.models.load_model('path/to/model.h5')

new_example = [[...]]

# transform new data with pipeline & use model for prediction
transformed_data = pipeline_estimator.transform(new_example)
prediction = model.predict(transformed_data)

分类器
函数之外定义
create_model
函数。有什么理由需要这个词法闭包吗?@juanpa.arrivillaga:我需要在里面有
分类器
,因为我需要传递参数。看到这个问题的其他任何人谁在这里登陆…助手功能在(接受)的答案实际上没有帮助。带有这些helper函数的完整代码示例是有效的,因为在该代码示例中,Keras模型从未包装为sklearn KerasClassifier(如问题所述)。保存sklearn KerasClassifier对象的真正答案在github对同一问题的回答中给出:这是在KerasClassifier对象的.model属性上使用内置Keras保存方法:your_model_name.model.save('saved filename.h5')您好,是的,它不解决KerasClassifier的问题,实际上,我在评论中的代码下面提到了这一点。另一方面,包装纸上应该有一些东西放在桌子上,我在这里没有看到。Keras已经足够简单/紧凑,不需要任何包装。感谢您提供此补丁。然而,使用
KerasClassifier
我现在在尝试加载pkl时遇到了一个不同的错误:
AttributeError:无法在
上获取属性“create\u model”――似乎
构建fn
被引用,但未存储在pickle中。有什么建议吗?这个问题/答案是2016年的,当时还没有实施这个快捷方式。谢谢分享这个答案!你能解释一下为什么需要拆分而不能将整个管道保存为一个pkl文件吗?从我的观点来看,整个管道可以保存为一个pkl文件BTW-使用这个解决方案,
模型。predict
返回
管道的值。predict_proba
,因此你需要使用
predict_class
import joblib
from sklearn.pipeline import Pipeline
from tensorflow import keras

# pass the create_cnn_model function into wrapper
cnn_model = keras.wrappers.scikit_learn.KerasClassifier(build_fn=create_cnn_model)

# create pipeline
cnn_model_pipeline_estimator = Pipeline([
    ('preprocessing_pipeline', pipeline_estimator),
    ('clf', cnn_model)
])

# train model
final_model = cnn_model_pipeline_estimator.fit(
X, y, clf__batch_size=32, clf__epochs=15)

# collect the preprocessing pipeline & model seperately
pipeline_estimator = final_model.named_steps['preprocessing_pipeline']
clf = final_model.named_steps['clf']

# store pipeline and model seperately
joblib.dump(pipeline_estimator, open('path/to/pipeline.pkl', 'wb'))
clf.model.save('path/to/model.h5')

# load pipeline and model
pipeline_estimator = joblib.load('path/to/pipeline.pxl')
model = keras.models.load_model('path/to/model.h5')

new_example = [[...]]

# transform new data with pipeline & use model for prediction
transformed_data = pipeline_estimator.transform(new_example)
prediction = model.predict(transformed_data)