I am trying to follow the tutorial on the Tensorflow quickstart page here. However, instead of using the movie-lens data used I am trying to use the Movie Dataset found at Kaggle Here. When I try to fit the model I get the following error
Epoch 1/3
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'movieId': <tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, 'userId': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=string>}. Consider rewriting this model with the Functional API.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-33-b20246ea89fa> in <module>
4
5 # Train for 3 epochs.
----> 6 model.fit(ratings_tf.batch(4096), epochs=3)
7
3 frames
<ipython-input-31-50917ec57dbf> in compute_loss(self, features, training)
23
24 user_embeddings = self.user_model(features["userId"])
---> 25 movie_embeddings = self.movie_model(features) #movie_embeddings = self.movie_model(features["title"])
26
27 return self.task(user_embeddings, movie_embeddings)
TypeError: in user code:
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1160, in train_function *
return step_function(self, iterator)
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1146, in step_function **
outputs = model.distribute_strategy.run(run_step, args=(data,))
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1135, in run_step **
outputs = model.train_step(data)
File "/usr/local/lib/python3.7/dist-packages/tensorflow_recommenders/models/base.py", line 68, in train_step
loss = self.compute_loss(inputs, training=True)
File "<ipython-input-31-50917ec57dbf>", line 25, in compute_loss
movie_embeddings = self.movie_model(features) #movie_embeddings = self.movie_model(features["title"])
File "/usr/local/lib/python3.7/dist-packages/keras/utils/traceback_utils.py", line 70, in error_handler
raise e.with_traceback(filtered_tb) from None
TypeError: Exception encountered when calling layer "string_lookup_1" " f"(type StringLookup).
Expected string, but got Tensor("IteratorGetNext:0", shape=(None,), dtype=int64) of type 'Tensor'.
Call arguments received by layer "string_lookup_1" " f"(type StringLookup):
• inputs={'movieId': 'tf.Tensor(shape=(None,), dtype=int64)', 'userId': 'tf.Tensor(shape=(None,), dtype=string)'}
The data I am using includes the ratings_small.csv, links_small.csv and `movie_metadata.csv'. The output of the datasets can be found below
The code I have so far is below.
movies_df = movies_df.dropna()
movies_df['release_date'] = pd.to_datetime(movies_df['release_date'])
movies_df['year'] = movies_df['release_date'].dt.year
# Select the basic features.
ratings_tf = ratings[['movieId', 'userId']] #['movie_title'] #=
ratings_tf['userId'] = ratings_tf['userId'].astype(str)
movies_tf = movies_df.dropna().drop('year', axis=1)['title']
years = []
for movie in movies_tf :
yr = movies_df[movies_df['title']==movie]['year'].values[0]
id = movies_df[movies_df['title']==movie]['id'].values[0]
years.append(yr)
for i in range(len(movies_tf)) :
movies_tf.reset_index()[i] = (movies_tf.reset_index(drop=True)[i] + ' (' + str(years[i]) + ')')
indexes = movies_tf.index
movies_tf = [movies_tf.reset_index(drop=True)[i] + ' (' + str(years[i]) + ')' for i in range(len(movies_tf))]
movies_tf = pd.DataFrame(data=movies_tf, columns=['title']).set_index(indexes)
movies_tf = movies_tf[['title']]
movies_tf = tf.data.Dataset.from_tensor_slices(dict(movies_tf))
ratings_tf = tf.data.Dataset.from_tensor_slices(dict(ratings_tf))
movies_tf = movies_tf.map(lambda x: x["title"])
ratings_tf = ratings_tf.map(lambda x: {
"movieId": x["movieId"],
"userId": x["userId"]
})
user_ids_vocabulary = tf.keras.layers.StringLookup(mask_token=None)
user_ids_vocabulary.adapt(ratings_tf.map(lambda x: x["userId"]))
movie_titles_vocabulary = tf.keras.layers.StringLookup(mask_token=None)
movie_titles_vocabulary.adapt(movies_tf)
class MovieLensModel(tfrs.Model):
# We derive from a custom base class to help reduce boilerplate. Under the hood,
# these are still plain Keras Models.
def __init__(
self,
user_model: tf.keras.Model,
movie_model: tf.keras.Model,
task: tfrs.tasks.Retrieval):
super().__init__()
# Set up user and movie representations.
self.user_model = user_model
self.movie_model = movie_model
# Set up a retrieval task.
self.task = task
def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
# Define how the loss is computed.
user_embeddings = self.user_model(features["userId"])
movie_embeddings = self.movie_model(features) #movie_embeddings = self.movie_model(features["title"])
return self.task(user_embeddings, movie_embeddings)
Define user model
user_model = tf.keras.Sequential([
user_ids_vocabulary,
tf.keras.layers.Embedding(user_ids_vocabulary.vocabulary_size(), 64)
])
# Define movie model
movie_model = tf.keras.Sequential([
movie_titles_vocabulary,
tf.keras.layers.Embedding(movie_titles_vocabulary.vocabulary_size(), 64)
])
# Define the objectives.
task = tfrs.tasks.Retrieval(metrics=tfrs.metrics.FactorizedTopK(
movies_tf.map(movie_model)
)
)
# Create a retrieval model.
model = MovieLensModel(user_model, movie_model, task)
model.compile(optimizer=tf.keras.optimizers.Adagrad(0.5))
# Train for 3 epochs.
model.fit(ratings_tf.batch(4096), epochs=3)
Any and all help would be appreciated! Thanks!

