Issue
This is taking the code from this project and converting to the Keras functional API. I un-subclassed the model from here and re-define it starting at inputs
.
The snag I'm running into is I get the following error when I try to fit the model.
ValueError: Layer "model" expects 1 input(s), but it received 2 input tensors. Inputs received:
[<tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>]
So I must have the shape of the initial tensor wrong- but I'm unsure how to proceed as I've tried a few different ways and nothing seems to make sense.
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras import layers
# Import CF Model Architecture
from CFModel import CFModel
RNG_SEED = 42
# Reading ratings file
ratings = pd.read_csv('data/ratings.csv', sep='\t', encoding='latin-1',
usecols=['user_id', 'movie_id', 'user_emb_id', 'movie_emb_id', 'rating'])
max_userid = ratings['user_id'].drop_duplicates().max()
max_movieid = ratings['movie_id'].drop_duplicates().max()
# Reading ratings file
users = pd.read_csv('data/users.csv', sep='\t', encoding='latin-1',
usecols=['user_id', 'gender', 'zipcode', 'age_desc', 'occ_desc'])
# Reading ratings file
movies = pd.read_csv('data/movies.csv', sep='\t', encoding='latin-1',
usecols=['movie_id', 'title', 'genres'])
# Create training set
shuffled_ratings = ratings.sample(frac=1., random_state=RNG_SEED)
# Shuffling users
Users = shuffled_ratings['user_emb_id'].values
print( 'Users:', Users, ', shape =', Users.shape)
# Users: [5411 5439 367 ... 853 4032 785] , shape = (1000209,)
# Shuffling movies
Movies = shuffled_ratings['movie_emb_id'].values
print( 'Movies:', Movies, ', shape =', Movies.shape)
# Movies: [2682 903 3716 ... 3101 3478 1390] , shape = (1000209,)
# Shuffling ratings
Ratings = shuffled_ratings['rating'].values
print( 'Ratings:', Ratings, ', shape =', Ratings.shape)
# Ratings: [2 5 4 ... 3 5 4] , shape = (1000209,)
K_FACTORS = 100 # The number of dimensional embeddings for movies and users
TEST_USER = 2000 # A random test user (user_id = 2000)
# Define model
inputs = layers.Input(shape=(1000209, 100)) # What should this input be?
embeddingUsers = layers.Embedding(max_userid, K_FACTORS, input_length=1)
usersEmbedded = embeddingUsers(inputs)
embeddingMovies = layers.Embedding(max_movieid, K_FACTORS, input_length=1)
moviesEmbedded = embeddingMovies(inputs)
inputs = layers.Dot(axes=1)([usersEmbedded, moviesEmbedded])
outputs = layers.Dense(5, activation='relu')(inputs)
model = keras.Model(inputs=inputs, outputs=outputs)
keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)
print(model.summary())
# Layer (type) Output Shape Param #
# =================================================================
# input_2 (InputLayer) [(None, 100, 100, 100, 1 0
# 00)]
# dense (Dense) (None, 100, 100, 100, 5) 505
# =================================================================
# Total params: 505
# Trainable params: 505
# Non-trainable params: 0
# _________________________________________________________________
model.compile(optimizer="rmsprop", loss="mse")
history = model.fit(
[Users, Movies],
Ratings,
epochs=10,
batch_size=32,
validation_split=0.2,
)
# ValueError: Layer "model" expects 1 input(s), but it received 2 input tensors. Inputs received:
# [<tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>]
Solution
I think you are mixing up a few things. The CFModel
, which you referenced and are trying to convert into a Model
with the functional API, consists of two Sequential
sub-models. If you want to pass two inputs to your model, it should have two Input
layers:
import tensorflow as tf
max_userid = 5000
max_movieid = 5000
K_FACTORS = 100
user_input = tf.keras.layers.Input(shape=(1,))
movie_input = tf.keras.layers.Input(shape=(1,))
embedding_users = tf.keras.layers.Embedding(max_userid, K_FACTORS, input_length=1)
users_embedded = embedding_users(user_input)
embedding_movies = tf.keras.layers.Embedding(max_movieid, K_FACTORS, input_length=1)
movies_embedded = embedding_movies(movie_input)
inputs = tf.keras.layers.Dot(axes=1)([users_embedded, movies_embedded])
outputs = tf.keras.layers.Dense(5, activation='relu')(inputs)
model = tf.keras.Model(inputs=[user_input, movie_input], outputs=outputs)
tf.keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)
print(model.summary())
model.compile(optimizer="rmsprop", loss="mse")
history = model.fit(
[Users, Movies],
Ratings,
epochs=10,
batch_size=32,
validation_split=0.2,
)
Model: "model_1"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_4 (InputLayer) [(None, 1)] 0 []
input_5 (InputLayer) [(None, 1)] 0 []
embedding_2 (Embedding) (None, 1, 100) 500000 ['input_4[0][0]']
embedding_3 (Embedding) (None, 1, 100) 500000 ['input_5[0][0]']
dot_1 (Dot) (None, 100, 100) 0 ['embedding_2[0][0]',
'embedding_3[0][0]']
dense_1 (Dense) (None, 100, 5) 505 ['dot_1[0][0]']
==================================================================================================
Total params: 1,000,505
Trainable params: 1,000,505
Non-trainable params: 0
__________________________________________________________________________________________________
None
Since both Users
and Movies
have the shape (1000209,)
, your input shape for both Input
layers is shape=(1,)
. This means that each sample consists of an ID that is mapped to a 100-dimensional vector using the Embedding
layers. Oh, and just in case it's not intentional, the CFModel
does not use a Dense
layer after calculating the dot product.
Answered By - AloneTogether
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.