加载已保存Keras模型后预测出现ValueError问题求助
问题:模型保存、加载后预测报错
我希望实现模型的保存、重新加载并将其用于预测,但加载后预测时出现错误。
已查阅相关内容
- keras加载保存模型后预测值始终相同
- keras加载模型后预测结果不同
- 仅用于预测的TensorFlow Keras模型保存/加载
- 加载包含可训练词嵌入的keras模型权重
- 加载保存的keras模型后出现ValueError
- 找不到匹配的函数来调用加载的SavedModel
- TensorFlow官方序列化文档(已在项目中使用)
模型代码
### ML MODEL EMBEDDING_SIZE = 50 class RecommenderNet(keras.Model): def __init__(self, num_users, num_movies, embedding_size, **kwargs): super(RecommenderNet, self).__init__(**kwargs) self.num_users = num_users self.num_movies = num_movies self.embedding_size = embedding_size self.user_embedding = layers.Embedding( num_users, embedding_size, embeddings_initializer="he_normal", embeddings_regularizer=keras.regularizers.l2(1e-6), ) self.user_bias = layers.Embedding(num_users, 1) self.movie_embedding = layers.Embedding( num_movies, embedding_size, embeddings_initializer="he_normal", embeddings_regularizer=keras.regularizers.l2(1e-6), ) self.movie_bias = layers.Embedding(num_movies, 1) def call(self, inputs): user_vector = self.user_embedding(inputs[:, 0]) user_bias = self.user_bias(inputs[:, 0]) movie_vector = self.movie_embedding(inputs[:, 1]) movie_bias = self.movie_bias(inputs[:, 1]) dot_user_movie = tf.tensordot(user_vector, movie_vector, 2) # Add all the components (including bias) x = dot_user_movie + user_bias + movie_bias # The sigmoid activation forces the rating to between 0 and 1 return tf.nn.sigmoid(x) model = RecommenderNet(num_users, num_movies, EMBEDDING_SIZE) model.compile( loss=tf.keras.losses.BinaryCrossentropy(), optimizer=keras.optimizers.Adam(lr=0.001) ) ##### LOG HISTORY from keras.callbacks import CSVLogger csv_logger = CSVLogger('save_training_history/' + 'history' + '_rows_of_data_' + str(number_of_table_rows) + '_time_' + str_date_time + 'training.log' , separator=',' , append=False) #### TRAIN history = model.fit( x=x_train, y=y_train, batch_size=64, epochs=10, verbose=1, validation_data=(x_val, y_val), callbacks=[csv_logger] )
保存代码
model.save('saved_model/' + 'model' + '_rows_of_data_' + str(number_of_table_rows) + '_' + str_date_time )
加载代码
# Load reconstructed_model = keras.models.load_model("my_model") # Load: 我也尝试过这种方式,但出现相同错误 loaded_model = tf.keras.models.load_model('/tmp/model')
预测代码
movides_watched_by_user = df_big[df_big.userid == user_id] '''获取用户未观看/未拥有的电影''' movies_not_watched1 = movie_df[~movie_df["movieid"].isin(movies_watched_by_user.movieid.values)]["movieid"] '''将DataFrame Series转为列表''' movies_not_watched2 = movies_not_watched1.copy() movies_not_watched3 = movies_not_watched2.values.tolist() '''通过外部函数将列表转为嵌套列表''' movies_not_watched = extractDigits(movies_not_watched3) '''合并为两行转置矩阵''' user_movie_array = np.hstack(( [[user_id]] * len(movies_not_watched), movies_not_watched )) '''预测概率分数并将结果展平为一维''' ratings = model.predict(user_movie_array).flatten()
报错信息
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-67-7f843e09ac34> in <module> 54 55 '''预测概率分数并将结果展平为一维''' ---> 56 ratings = model.predict(user_movie_array).flatten() 57 #print(ratings.shape) 58 ~/anaconda3/envs/tfkgpu/lib/python3.7/site-packages/keras/utils/traceback_utils.py in error_handler(*args, **kwargs) 65 except Exception as e: # pylint: disable=broad-except 66 filtered_tb = _process_traceback_frames(e.__traceback__) ---> 67 raise e.with_traceback(filtered_tb) from None 68 finally: 69 del filtered_tb ~/anaconda3/envs/tfkgpu/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py in autograph_handler(*args, **kwargs) 1145 except Exception as e: # pylint:disable=broad-except 1146 if hasattr(e, "ag_error_metadata"): ---> 1147 raise e.ag_error_metadata.to_exception(e) 1148 else: 1149 raise ValueError: in user code: File "/home/ubuntu/anaconda3/envs/tfkgpu/lib/python3.7/site-packages/keras/engine/training.py", line 1801, in predict_function * return step_function(self, iterator) File "/home/ubuntu/anaconda3/envs/tfkgpu/lib/python3.7/site-packages/keras/engine/training.py", line 1790, in step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) File "/home/ubuntu/anaconda3/envs/tfkgpu/lib/python3.7/site-packages/keras/engine/training.py", line 1783, in run_step ** outputs = model.predict_step(data) File "/home/ubuntu/anaconda3/envs/tfkgpu/lib/python3.7/site-packages/keras/engine/training.py", line 1751, in predict_step return self(x, training=False) File "/home/ubuntu/anaconda3/envs/tfkgpu/lib/python3.7/site-packages/keras/utils/traceback_utils.py", line 67, in error_handler raise e.with_traceback(filtered_tb) from None ValueError: Exception encountered when calling layer "recommender_net" (type RecommenderNet). Could not find matching concrete function to call loaded from the SavedModel. Got: Positional arguments (1 total): * Tensor("inputs:0", shape=(None, 2), dtype=int64) Keyword arguments: {} Expected these arguments to match one of the following 2 option(s): Option 1: Positional arguments (1 total): * TensorSpec(shape=(None, 2), dtype=tf.int32, name='inputs') Keyword arguments: {} Option 2: Positional arguments (1 total): * TensorSpec(shape=(None, 2), dtype=tf.int32, name='input_1') Keyword arguments: {} Call arguments received: • args=('tf.Tensor(shape=(None, 2), dtype=int64)',) • kwargs=<class 'inspect._empty'>
解决方案
问题根源
报错核心是输入数据类型不匹配:模型加载后期望的输入是int32类型,但传入的user_movie_array是int64类型,导致找不到对应的调用函数。
快速修复
在生成user_movie_array后,直接转换为int32类型:
user_movie_array = np.hstack(( [[user_id]] * len(movies_not_watched), movies_not_watched )).astype(np.int32)
彻底规避(可选)
- 训练阶段统一数据类型:将
x_train和x_val都转为int32,让模型保存时记录的输入签名与后续预测输入一致,从根源避免类型问题。 - 保存模型前生成明确的输入签名:先运行一次dummy预测,让模型锁定输入格式:
# 生成符合输入格式的测试数据 dummy_input = tf.convert_to_tensor([[0, 0]], dtype=tf.int32) _ = model.predict(dummy_input) # 再保存模型 model.save('saved_model/your_model_path') - 加载模型时指定自定义类:如果加载时提示找不到
RecommenderNet类,需传入custom_objects参数:loaded_model = tf.keras.models.load_model('saved_model/your_model_path', custom_objects={'RecommenderNet': RecommenderNet})
内容的提问来源于stack exchange,提问作者sogu
相关产品推荐
相关产品推荐

