无法保存管道估算器
Can't save a Pipeline estimator
我正在尝试训练一个简单的管道:
pipeline = Pipeline(
[
('scaler', StandardScaler()),
('deepnc', deepnc),
])
其中 deepnc 是 Keras 分类器:
def create_spec_model(n_col=115, density_value=2, init='normal', dropout=0.2, learning_rate=0.005, decay=0.001,
momentum=0.9):
# create model
model = Sequential()
model.add(Dropout(dropout, input_shape=(n_col,)))
model.add(Dense(50 * density_value, init=init, activation='relu', W_constraint=maxnorm(2),
W_regularizer=l1l2(l1=0, l2=1e-4)))
model.add(Dropout(dropout))
model.add(Dense(30 * density_value, init=init, activation='relu', W_constraint=maxnorm(2),
W_regularizer=l1l2(l1=0, l2=1e-4)))
model.add(Dropout(dropout))
model.add(Dense(1, init=init, activation='sigmoid'))
# load weights
try:
model.load_weights(spec_model_path)
except:
pass
# Compile model
sgd = SGD(lr=learning_rate, momentum=momentum, decay=decay, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
return model
我将管道放入随机搜索并检查一些参数:
deepnc = KerasClassifier(build_fn=create_spec_model, validation_split=0.1, dropout=0.2, learning_rate=0.005,
decay=0.001, verbose=2)
# grid search epochs, batch size and optimizer
optimizers = ['adam']
init = ['uniform', 'normal']
epochs = np.array([20, 40])
batches = np.array([20, 50, 100])
learning_rate = [0.005, 0.01]
dropout = [0.2, 0.3, 0.5]
decay = [0, 0.001, 0.005, 0.01]
density_value = [1, 2, 4]
param_grid = dict(deepnc__nb_epoch=epochs, deepnc__batch_size=batches, deepnc__init=init, deepnc__dropout=dropout,
deepnc__learning_rate=learning_rate,
deepnc__density_value=density_value)
grid = RandomizedSearchCV(estimator=pipeline, param_distributions=param_grid, n_iter=100, cv=5, verbose=1,
scoring='accuracy', fit_params={'deepnc__callbacks': [earlyStopping, modelCheck]})
grid.fit(np.array(X_train.iloc[:, :115]), y_train)
后来想保存最好的估计器和最好的参数:
joblib.dump(grid.best_estimator_, 'models/deepn_spec_model.pkl')
joblib.dump(grid.best_params_, 'models/deepn_spec_model_best_params.pkl')
由于某种原因,前者不起作用。幸运的是,我 运行 控制台中的脚本,所以我能够 运行 单独地 运行 后者并保存最佳参数。但是,我仍在尝试弄清楚如何保存模型。我想将 Keras 的 scikit 包装器与 Pipeline 和 RandomizedSearchCV 结合使用会导致问题吗?
我也试过这个代码:
path = 'models/deepn_spec_model.pkl'
pickle.dump(grid.best_estimator_, open(path, 'wb'))
但它生成了相同的错误回溯。我 post 下面是一个缩短的版本,因为它超长并且由一遍又一遍地重复相同的片段组成。谷歌搜索错误没有帮助。有什么想法吗?
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 606, in save_list
self._batch_appends(iter(obj))
File "/usr/lib/python2.7/pickle.py", line 621, in _batch_appends
save(x)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 568, in save_tuple
save(element)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 655, in save_dict
self._batch_setitems(obj.iteritems())
File "/usr/lib/python2.7/pickle.py", line 669, in _batch_setitems
save(v)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 754, in save_global
(obj, module, name))
PicklingError: Can't pickle <function start_console_server at 0x7f0c22d08a28>: it's not found as __main__.start_console_server
奖励问题:我是否正确使用了随机搜索?与最初的努力相比,我并没有得到太大的进步。
您无法使用 joblib 或 pickle 保存 keras 模型。
而是使用保存方法并显示 here.
或者您的情况:
path = 'models/deepn_spec_model.pkl'
grid.best_estimator_.save(path)
并加载模型:
from keras.models import load_model
path = 'models/deepn_spec_model.pkl'
model = load_model(path)
另请注意,由于严格来说这不是 pickle 文件而是 HDF5 文件,您不妨将文件扩展名更改为“.h5”。
我知道这不是您要找的东西,但是...什么都没有 :
鉴于你的回调对象已经保存了最好的权重,你只需要模型对象。该模型在您的函数 create_spec_model()
中。您唯一需要的是最好的参数。所以:
# Save parameters of the best estimator.
pickle.dump(grid.best_estimator_.named_steps['deepnc'].get_params(),open('params.pkl','wb'))
在加载时,鉴于您的函数 create_spec_model()
仍在您的代码中:
import inspect
def load_model(params_path, weights_path):
params = pickle.load(open(params_path,'rb'))
params = {k: params[k] for k in inspect.getargspec(create_spec_model)[0] if k in params.keys()}
model = create_spec_model(**params)
model.load_weights(weights_path)
return model
对你有帮助吗?
无法保存包裹在 Scikit 分类器内部的 Keras 模型GitHub Reference。
但是,有一个解决方法(或 2 个)!一种是,如 ,使用 ModelCheckpoint 保存最佳权重和 "recreate" 模型。
在我的情况下,在做了一些研究之后,我决定以不同的方式来做,可以说更容易:在训练之后,简单地做:
grid.best_estimator_.model.save(path)
这(即在保存之前添加 .model)确保访问底层的 Keras 模型,对于该模型,保存方法可以正常工作。现在你可以简单地做
deepnc_cont = keras.models.load_model(path)
而且有效 - 至少对我来说 :)
请注意,如果出于某种原因,我需要一个 KerasClassifier 对象(scikit 包装器),它将无法工作,因为它的构造函数需要一个生成模型的函数,所以我可能不得不继续纳西姆的路线?不过我不确定。
只是为 Keras-Pickle 问题添加另一个解决方法。
它有点不完整,但允许使用 pickle
存储 Keras 模型,因此它适用于模型和包含对象。
我正在尝试训练一个简单的管道:
pipeline = Pipeline(
[
('scaler', StandardScaler()),
('deepnc', deepnc),
])
其中 deepnc 是 Keras 分类器:
def create_spec_model(n_col=115, density_value=2, init='normal', dropout=0.2, learning_rate=0.005, decay=0.001,
momentum=0.9):
# create model
model = Sequential()
model.add(Dropout(dropout, input_shape=(n_col,)))
model.add(Dense(50 * density_value, init=init, activation='relu', W_constraint=maxnorm(2),
W_regularizer=l1l2(l1=0, l2=1e-4)))
model.add(Dropout(dropout))
model.add(Dense(30 * density_value, init=init, activation='relu', W_constraint=maxnorm(2),
W_regularizer=l1l2(l1=0, l2=1e-4)))
model.add(Dropout(dropout))
model.add(Dense(1, init=init, activation='sigmoid'))
# load weights
try:
model.load_weights(spec_model_path)
except:
pass
# Compile model
sgd = SGD(lr=learning_rate, momentum=momentum, decay=decay, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
return model
我将管道放入随机搜索并检查一些参数:
deepnc = KerasClassifier(build_fn=create_spec_model, validation_split=0.1, dropout=0.2, learning_rate=0.005,
decay=0.001, verbose=2)
# grid search epochs, batch size and optimizer
optimizers = ['adam']
init = ['uniform', 'normal']
epochs = np.array([20, 40])
batches = np.array([20, 50, 100])
learning_rate = [0.005, 0.01]
dropout = [0.2, 0.3, 0.5]
decay = [0, 0.001, 0.005, 0.01]
density_value = [1, 2, 4]
param_grid = dict(deepnc__nb_epoch=epochs, deepnc__batch_size=batches, deepnc__init=init, deepnc__dropout=dropout,
deepnc__learning_rate=learning_rate,
deepnc__density_value=density_value)
grid = RandomizedSearchCV(estimator=pipeline, param_distributions=param_grid, n_iter=100, cv=5, verbose=1,
scoring='accuracy', fit_params={'deepnc__callbacks': [earlyStopping, modelCheck]})
grid.fit(np.array(X_train.iloc[:, :115]), y_train)
后来想保存最好的估计器和最好的参数:
joblib.dump(grid.best_estimator_, 'models/deepn_spec_model.pkl')
joblib.dump(grid.best_params_, 'models/deepn_spec_model_best_params.pkl')
由于某种原因,前者不起作用。幸运的是,我 运行 控制台中的脚本,所以我能够 运行 单独地 运行 后者并保存最佳参数。但是,我仍在尝试弄清楚如何保存模型。我想将 Keras 的 scikit 包装器与 Pipeline 和 RandomizedSearchCV 结合使用会导致问题吗?
我也试过这个代码:
path = 'models/deepn_spec_model.pkl'
pickle.dump(grid.best_estimator_, open(path, 'wb'))
但它生成了相同的错误回溯。我 post 下面是一个缩短的版本,因为它超长并且由一遍又一遍地重复相同的片段组成。谷歌搜索错误没有帮助。有什么想法吗?
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 606, in save_list
self._batch_appends(iter(obj))
File "/usr/lib/python2.7/pickle.py", line 621, in _batch_appends
save(x)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 568, in save_tuple
save(element)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 655, in save_dict
self._batch_setitems(obj.iteritems())
File "/usr/lib/python2.7/pickle.py", line 669, in _batch_setitems
save(v)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 754, in save_global
(obj, module, name))
PicklingError: Can't pickle <function start_console_server at 0x7f0c22d08a28>: it's not found as __main__.start_console_server
奖励问题:我是否正确使用了随机搜索?与最初的努力相比,我并没有得到太大的进步。
您无法使用 joblib 或 pickle 保存 keras 模型。 而是使用保存方法并显示 here.
或者您的情况:
path = 'models/deepn_spec_model.pkl'
grid.best_estimator_.save(path)
并加载模型:
from keras.models import load_model
path = 'models/deepn_spec_model.pkl'
model = load_model(path)
另请注意,由于严格来说这不是 pickle 文件而是 HDF5 文件,您不妨将文件扩展名更改为“.h5”。
我知道这不是您要找的东西,但是...什么都没有 :
鉴于你的回调对象已经保存了最好的权重,你只需要模型对象。该模型在您的函数 create_spec_model()
中。您唯一需要的是最好的参数。所以:
# Save parameters of the best estimator.
pickle.dump(grid.best_estimator_.named_steps['deepnc'].get_params(),open('params.pkl','wb'))
在加载时,鉴于您的函数 create_spec_model()
仍在您的代码中:
import inspect
def load_model(params_path, weights_path):
params = pickle.load(open(params_path,'rb'))
params = {k: params[k] for k in inspect.getargspec(create_spec_model)[0] if k in params.keys()}
model = create_spec_model(**params)
model.load_weights(weights_path)
return model
对你有帮助吗?
无法保存包裹在 Scikit 分类器内部的 Keras 模型GitHub Reference。
但是,有一个解决方法(或 2 个)!一种是,如
在我的情况下,在做了一些研究之后,我决定以不同的方式来做,可以说更容易:在训练之后,简单地做:
grid.best_estimator_.model.save(path)
这(即在保存之前添加 .model)确保访问底层的 Keras 模型,对于该模型,保存方法可以正常工作。现在你可以简单地做
deepnc_cont = keras.models.load_model(path)
而且有效 - 至少对我来说 :)
请注意,如果出于某种原因,我需要一个 KerasClassifier 对象(scikit 包装器),它将无法工作,因为它的构造函数需要一个生成模型的函数,所以我可能不得不继续纳西姆的路线?不过我不确定。
只是为 Keras-Pickle 问题添加另一个解决方法。
它有点不完整,但允许使用 pickle
存储 Keras 模型,因此它适用于模型和包含对象。