I want to save, load back my model, and use it for prediction.
Reviewed Answers
- keras > always the same prediction value after loading saved model
- different prediction after load a model in keras
- Save / Load Tensorflow Keras model for Prediction only
- (tf.)keras loading saved model weights with trainable word embeddings
- ValueError after loading saved keras model
- Could not find matching function to call loaded from the SavedModel
- https://github.com/tensorflow/tensorflow/issues/37973 --> https://www.tensorflow.org/guide/keras/save_and_serialize <-- I have used this in the project
MODEL
### 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]
)
SAVE
model.save('saved_model/' 'model' '_rows_of_data_' str(number_of_table_rows) '_' str_date_time )
LOAD
#Load
reconstructed_model = keras.models.load_model("my_model")
# Load: I have tried this one as well but it gave the same error
loaded_model = tf.keras.models.load_model('/tmp/model')
Predict
movides_watched_by_user = df_big[df_big.userid == user_id]
'''GET movies NOT owned/played by users'''
movies_not_watched1 = movie_df[~movie_df["movieid"].isin(movies_watched_by_user.movieid.values)]["movieid"]
'''NOT df Series to list'''
movies_not_watched2 = movies_not_watched1.copy()
movies_not_watched3 = movies_not_watched2.values.tolist()
'''(NOT list) Double wrap in to a list of lists BY EXTERANL FUNCTION'''
movies_not_watched = extractDigits(movies_not_watched3)
'''UNIFY 2 rows Transpose matrix'''
user_movie_array = np.hstack((
[[user_id]] * len(movies_not_watched), movies_not_watched
))
'''Predict probability sores user_movie_array -1D'''
ratings = model.predict(user_movie_array).flatten()
ERROR
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-67-7f843e09ac34> in <module>
54
55 '''Predict probability sores user_movie_array -1D'''
---> 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'>
CodePudding user response:
You have a custom model architecture that needs to be reinitialized upon loading. This can be done by the SavedModel
, but you need to specify a get_config
and from_config
which have the values to initialize your model.
Alternatively, you could redefine the model yourself and use save_weights
and load_weights
.
For an example, see the docs.
In your case, you'd need to add this to your RecommenderNet
class:
def get_config(self):
return {
"num_users": self.num_users,
"num_movies": self.num_movies,
"embedding_size": self.embedding_size,
}
@classmethod
def from_config(cls, config):
return cls(**config)