当我尝试保存和加载包含LSTM层的模型时,加载通用失败,并出现 ValueError:无法找到匹配的函数来调用从SavedModel加载的函数 。
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_validation.py:528: FutureWarning: From version 0.22, errors during fit will result in a cross validation score of NaN by default. Use error_score='raise' if you want an exception raised or error_score=np.nan to adopt the behavior from version 0.22.
FutureWarning)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-162-9c9a4d6ea766> in <module>
14 y = y_train1
15 model_cv_result = model_cv.fit(X, y
---> 16 , callbacks = [time_callback]
17 )
18
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_search.py in fit(self, X, y, groups, **fit_params)
685 return results
686
--> 687 self._run_search(evaluate_candidates)
688
689 # For multi-metric evaluation, store the best_index_, best_params_ and
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_search.py in _run_search(self, evaluate_candidates)
1146 def _run_search(self, evaluate_candidates):
1147 """Search all candidates in param_grid"""
-> 1148 evaluate_candidates(ParameterGrid(self.param_grid))
1149
1150
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_search.py in evaluate_candidates(candidate_params)
664 for parameters, (train, test)
665 in product(candidate_params,
--> 666 cv.split(X, y, groups)))
667
668 if len(out) < 1:
C:\ProgramData\Anaconda3\lib\site-packages\joblib\parallel.py in __call__(self, iterable)
919 # remaining jobs.
920 self._iterating = False
--> 921 if self.dispatch_one_batch(iterator):
922 self._iterating = self._original_iterator is not None
923
C:\ProgramData\Anaconda3\lib\site-packages\joblib\parallel.py in dispatch_one_batch(self, iterator)
757 return False
758 else:
--> 759 self._dispatch(tasks)
760 return True
761
C:\ProgramData\Anaconda3\lib\site-packages\joblib\parallel.py in _dispatch(self, batch)
714 with self._lock:
715 job_idx = len(self._jobs)
--> 716 job = self._backend.apply_async(batch, callback=cb)
717 # A job can complete so quickly than its callback is
718 # called before we get here, causing self._jobs to
C:\ProgramData\Anaconda3\lib\site-packages\joblib\_parallel_backends.py in apply_async(self, func, callback)
180 def apply_async(self, func, callback=None):
181 """Schedule a func to be run"""
--> 182 result = ImmediateResult(func)
183 if callback:
184 callback(result)
C:\ProgramData\Anaconda3\lib\site-packages\joblib\_parallel_backends.py in __init__(self, batch)
547 # Don't delay the application, to avoid keeping the input
548 # arguments in memory
--> 549 self.results = batch()
550
551 def get(self):
C:\ProgramData\Anaconda3\lib\site-packages\joblib\parallel.py in __call__(self)
223 with parallel_backend(self._backend, n_jobs=self._n_jobs):
224 return [func(*args, **kwargs)
--> 225 for func, args, kwargs in self.items]
226
227 def __len__(self):
C:\ProgramData\Anaconda3\lib\site-packages\joblib\parallel.py in <listcomp>(.0)
223 with parallel_backend(self._backend, n_jobs=self._n_jobs):
224 return [func(*args, **kwargs)
--> 225 for func, args, kwargs in self.items]
226
227 def __len__(self):
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_validation.py in _fit_and_score(estimator, X, y, scorer, train, test, verbose, parameters, fit_params, return_train_score, return_parameters, return_n_test_samples, return_times, return_estimator, error_score)
512 estimator.fit(X_train, **fit_params)
513 else:
--> 514 estimator.fit(X_train, y_train, **fit_params)
515
516 except Exception as e:
C:\ProgramData\Anaconda3\lib\site-packages\keras\wrappers\scikit_learn.py in fit(self, x, y, **kwargs)
149 fit_args.update(kwargs)
150
--> 151 history = self.model.fit(x, y, **fit_args)
152
153 return history
C:\ProgramData\Anaconda3\lib\site-packages\keras\engine\training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
1237 steps_per_epoch=steps_per_epoch,
1238 validation_steps=validation_steps,
-> 1239 validation_freq=validation_freq)
1240
1241 def evaluate(self,
C:\ProgramData\Anaconda3\lib\site-packages\keras\engine\training_arrays.py in fit_loop(model, fit_function, fit_inputs, out_labels, batch_size, epochs, verbose, callbacks, val_function, val_inputs, shuffle, initial_epoch, steps_per_epoch, validation_steps, validation_freq)
144 for epoch in range(initial_epoch, epochs):
145 model.reset_metrics()
--> 146 callbacks.on_epoch_begin(epoch)
147 epoch_logs = {}
148 if steps_per_epoch is not None:
C:\ProgramData\Anaconda3\lib\site-packages\keras\callbacks\callbacks.py in on_epoch_begin(self, epoch, logs)
134 logs = logs or {}
135 for callback in self.callbacks:
--> 136 callback.on_epoch_begin(epoch, logs)
137 self._reset_batch_timing()
138
<ipython-input-121-c4f8115d9239> in on_epoch_begin(self, epoch, logs)
19 self.times = []
20 def on_epoch_begin(self, epoch, logs={}):
---> 21 self.epoch_time_start = time.time()
22 def on_epoch_end(self, epoch, logs={}):
23 self.times.append(time.time() - self.epoch_time_start)
AttributeError: 'float' object has no attribute 'time'
错误报告:
class RegNet(Model):
def __init__(self,
intermediate_dim=50,
state_dim=9,
name='RegNet',
**kwargs):
super(RegNet, self).__init__()
self.d1 = Dense(intermediate_dim, activation='relu')
self.d2 = Dense(state_dim, activation='relu')
self.h = LSTM(state_dim, activation='sigmoid', return_sequences=True)
self.o = Dense(state_dim, activation='softmax')
def call(self, x):
x = self.d1(x)
x = self.d2(x)
x = self.h(x)
y = self.o(x)
return y
regNet = RegNet()
...
# Export the model to a SavedModel
regNet.save(regNet_ckpt_dir, save_format='tf')
# Recreate the exact same model
tf.keras.models.load_model(regNet_ckpt_dir)
当我评论LSTM层时,加载命令将成功。问题出在哪里?我们不能在TensorFlow 2.0中保存和加载具有LSTM层的模型吗?
答案 0 :(得分:1)
万一其他人偶然发现此解决方案,那么该解决方案对我有用:
# Save model
tf.keras.models.save_model(model, "saved_model.hp5", save_format="h5")
# Load model
loaded_model = tf.keras.models.load_model("saved_model.hp5")
不确定为什么“ model.save(filename)”语法不适用于LSTM,但是我遇到了同样的问题。
答案 1 :(得分:1)
TL; DR
尝试提供training
的默认值,即
def call(self, inputs, training=None):
我在tensorflow 2.1.0 中遇到了类似的错误:
"ValueError: Could not find matching function to call loaded from the SavedModel. Got:
Positional arguments (2 total):
* Tensor("inputs:0", shape=(None, 128, 128, 3), dtype=float32)
* Tensor("training:0", shape=(), dtype=bool)
我的模型没有LSTM层。
从错误消息中的投诉与inputs
和training
有关的事实来看,我想它与我们将call
类子类化时所需的Model
函数有关,因为inputs
和training
是该函数的两个参数名称。
解决我的问题的是:
代替
def call(self, inputs):
提供training
的默认值,即
def call(self, inputs, training=None):
答案 2 :(得分:0)
子类模型与其他keras模型类型(顺序模型和功能模型)有所不同。由于here中列出的那些差异,子类模型的保存和加载与其他Keras模型不同。
在谈到子类模型与其他keras模型(顺序模型和功能模型)之间的差异时,可以使用三种不同的方法来保存子分类模型。
class ThreeLayerMLP(keras.Model):
def __init__(self, name=None):
super(ThreeLayerMLP, self).__init__(name=name)
self.dense_1 = layers.Dense(64, activation='relu', name='dense_1')
self.dense_2 = layers.Dense(64, activation='relu', name='dense_2')
self.pred_layer = layers.Dense(10, name='predictions')
def call(self, inputs):
x = self.dense_1(inputs)
x = self.dense_2(x)
return self.pred_layer(x)
def get_model():
return ThreeLayerMLP(name='3_layer_mlp')
model = get_model()
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255
model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train,
batch_size=64,
epochs=1)
# Reset metrics before saving so that loaded model has same state,
# since metric states are not preserved by Model.save_weights
model.reset_metrics()
这种方法是使用model.save
保存整个模型,并使用load_model
恢复以前存储的子类模型。
# Save the model
model.save('path_to_my_model',save_format='tf')
# Recreate the exact same model purely from the file
new_model = keras.models.load_model('path_to_my_model')
第二种方法是使用tf.saved_model.save
。这等效于tf
中的model.save
格式。您可以再次调用load_model
以恢复先前保存的子类模型。
第三种方法是使用save_weights创建一个TensorFlow SavedModel检查点。要还原子类模型,(1)您将需要访问创建模型对象的代码并再次创建模型,(2)编译模型以还原优化器状态和任何有状态的度量,以及(3)调用在调用load_weights之前将其放在某些数据上。
model.save_weights('path_to_my_weights', save_format='tf')
# Recreate the model
new_model = get_model()
new_model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop())
# This initializes the variables used by the optimizers,
# as well as any stateful metric variables
new_model.train_on_batch(x_train[:1], y_train[:1])
# Load the state of the old model
new_model.load_weights('path_to_my_weights')
保存模型时要注意的另一重要事项如下。
整个模型可以保存为两种不同的文件格式(SavedModel
和HDF5
)。请注意,TensorFlow SavedModel('tf')格式是TF2.x中的默认文件格式。但是,模型可以HDF5格式保存。 HDF5和SavedModel之间的主要区别在于,HDF5使用对象配置保存模型体系结构,而SavedModel保存执行图。因此,SavedModels(使用save_format ='tf'保存的模型)能够保存自定义对象,例如子类模型和自定义层,而无需原始代码。
希望这会有所帮助。