Please help! Can't get model together
I am new to TensorFlow, in fact, I started exploring this library 2-3 weeks ago, because I am doing an internship where my project is a Recommender System.
I could follow all the tutorials available from the TF team and adapt them to my dataset, although, when I try to adapt the models to what I need, I can't manage to do it. I am doing a retail recommender system with features for the users and for the products, I would like to apply the Deep & Cross Network so the model can best learn the influence of each variable on the customers' habits.
I have tried this for these last weeks and can't manage to get it, I am starting to become very desperate, because I have a couple of weeks to finish this project. I have tried to ask for help on several places but I can't get any answer.
I know this is not the type of questions you use to answer but I am really desperate, so I will try my luck.
Here is an example of a code I tried (mixing the DCN tutorial with the DNN):
`class UserModel(tf.keras.Model):
def __init__(self):
super().__init__()
self.embedding_dimension = 32
self.user_embedding = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_user_ids, mask_token=None),
tf.keras.layers.Embedding(len(unique_user_ids) + 1, 32),
])
str_features = [
'user_gender'
]
int_features = [
'timestamp',
'user_age',
'user_lat',
'user_long'
]
self._all_features = str_features + int_features
self._embeddings = {}
# Compute embeddings for string features.
for feature_name in str_features:
vocabulary = vocabularies[feature_name]
self._embeddings[feature_name] = tf.keras.Sequential(
[tf.keras.layers.experimental.preprocessing.StringLookup(
vocabulary=vocabulary, mask_token=None),
tf.keras.layers.Embedding(len(vocabulary) + 1,
self.embedding_dimension)
])
# Compute embeddings for int features.
for feature_name in int_features:
vocabulary = vocabularies[feature_name]
self._embeddings[feature_name] = tf.keras.Sequential(
[tf.keras.layers.experimental.preprocessing.IntegerLookup(
vocabulary=vocabulary, mask_token=None),
tf.keras.layers.Embedding(len(vocabulary) + 1,
self.embedding_dimension)
])
def call(self,features):
# Concatenate embeddings
embeddings = []
for feature_name in self._all_features:
embedding_fn = self._embeddings[feature_name]
embeddings.append(embedding_fn(features[feature_name]))
return tf.concat([
self.user_embedding(features["user_id"]),
tf.concat(embeddings, axis=1)
], axis=1)`
`class QueryModel(tf.keras.Model): """Model for encoding user queries."""
def __init__(self, deep_layer_sizes, projection_dim=None):
"""Model for encoding user queries.
Args:
layer_sizes:
A list of integers where the i-th entry represents the number of units
the i-th layer contains.
"""
super().__init__()
# We first use the user model for generating embeddings.
self.embedding_model = UserModel()
self._cross_layer = tfrs.layers.dcn.Cross(
projection_dim=projection_dim,
kernel_initializer="glorot_uniform")
# Then construct the layers.
self.dense_layers = tf.keras.Sequential()
# Use the ReLU activation for all but the last layer.
self._deep_layers = [tf.keras.layers.Dense(layer_size, activation="relu")
for layer_size in deep_layer_sizes]
self._logit_layer = tf.keras.layers.Dense(1)
def call(self, features):
feature_embedding = self.embedding_model(features)
return self.dense_layers(feature_embedding)`
`class ProductModel(tf.keras.Model):
def __init__(self):
super().__init__()
self.product_embedding = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_product_names,mask_token=None),
tf.keras.layers.Embedding(len(unique_product_names) + 1, 32)
])
str_features = [
'product_colour',
'product_tear',
'product_tonality',
'product_gender',
'product_age',
'product_category',
'product_fit',
'product_rise',
'product_neckline',
'product_sleeve',
'product_denim',
'product_stretch',
'product_wash'
]
int_features = [
'price'
]
self._all_features = str_features + int_features
self._embeddings = {}
# Compute embeddings for string features.
for feature_name in str_features:
vocabulary = vocabularies[feature_name]
self._embeddings[feature_name] = tf.keras.Sequential(
[tf.keras.layers.experimental.preprocessing.StringLookup(
vocabulary=vocabulary, mask_token=None),
tf.keras.layers.Embedding(len(vocabulary) + 1, 32)
])
# Compute embeddings for int features.
for feature_name in int_features:
vocabulary = vocabularies[feature_name]
self._embeddings[feature_name] = tf.keras.Sequential(
[tf.keras.layers.experimental.preprocessing.IntegerLookup(
vocabulary=vocabulary, mask_token=None),
tf.keras.layers.Embedding(len(vocabulary) + 1, 32)
])
def call(self,features):
# Concatenate embeddings
embeddings = []
for feature_name in self._all_features:
embedding_fn = self._embeddings[feature_name]
embeddings.append(embedding_fn(features[feature_name]))
return tf.concat([
self.product_embedding(features["product_id"]),
tf.concat(embeddings, axis=1)
], axis=1)`
`class CandidateModel(tf.keras.Model): """Model for encoding movies."""
def __init__(self, deep_layer_sizes):
"""Model for encoding movies.
Args:
layer_sizes:
A list of integers where the i-th entry represents the number of units
the i-th layer contains.
"""
super().__init__()
self.embedding_model = ProductModel()
self._cross_layer = tfrs.layers.dcn.Cross(
projection_dim=None,
kernel_initializer="glorot_uniform")
# Then construct the layers.
self.dense_layers = tf.keras.Sequential()
# Use the ReLU activation for all but the last layer.
self._deep_layers = [tf.keras.layers.Dense(layer_size, activation="relu")
for layer_size in deep_layer_sizes]
self._logit_layer = tf.keras.layers.Dense(1)
def call(self, features):
feature_embedding = self.embedding_model(features)
return self.dense_layers(feature_embedding)`
`class MainModel(tfrs.models.Model):
def __init__(self, deep_layer_sizes):
super().__init__()
self.query_model = QueryModel(deep_layer_sizes)
self.candidate_model = CandidateModel(deep_layer_sizes)
self.task = tfrs.tasks.Retrieval(
metrics=tfrs.metrics.FactorizedTopK(
candidates=products.batch(128).map(self.candidate_model),
),
)
def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
# We pick out the user features and pass them into the user model.
user_embeddings = self.query_model(features["user_id"])
# And pick out the movie features and pass them into the movie model,
# getting embeddings back.
product_embeddings = self.candidate_model(features["product_id"])
# The task computes the loss and the metrics.
return self.task(user_embeddings, product_embeddings)`
When I try to run this: `num_epochs = 300
model = MainModel(deep_layer_sizes=[192, 192]) model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
one_layer_history = model.fit( cached_train, validation_data=cached_test, validation_freq=5, epochs=num_epochs, verbose=0)
accuracy = one_layer_history.history["val_factorized_top_k/top_100_categorical_accuracy"][-1] print(f"Top-100 accuracy: {accuracy:.2f}.")`
I get this error:
TypeError: Only integers, slices (:), ellipsis (...), tf.newaxis (None) and scalar tf.int32/tf.int64 tensors are valid indices, got 'product_colour'
I don't know why the variables in the Candidate Model are not in the correct format, since I have done the same way on the Query Model. Even if I remove those features from the Product/Candidate Model I get different errors. I have been debuging code for the last 4 days, and every time I find something, I get another error.
And I also tried to embed every single feature manually and I get errors and errors without any sight of hope.
Basically all I want is a DCN Model that I can retrieve recommendations from.
I kindly ask for your help.
Hey @joaoalveshenriques, That error is because you are trying to index a tensor with a string. Somewhere in the code you think you have a dictionary, where you don't.
my bet is here
def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
# We pick out the user features and pass them into the user model.
user_embeddings = self.query_model(features["user_id"])
# And pick out the movie features and pass them into the movie model,
# getting embeddings back.
product_embeddings = self.candidate_model(features["product_id"])
# The task computes the loss and the metrics.
return self.task(user_embeddings, product_embeddings)`
You're only passing the user_id and the product_id to your query and candidate models, and your embedding_model looks like it should receive the complete dictionary of tensor slices.
Ahoi @joaoalveshenriques ,
for debugging & dimension fitting you can try to call the model directly QueryModel(deep_layer_size)({features})
By changing or deleting some features, you can see how the Model's responds to ... e.g for the DCN tutorial:
hp = hyper_parameter
qm = QueryModel(hp['query'])({
'user_id': tf.constant(['27']),
'timestamp': tf.constant([893286638]),
'raw_user_age': tf.constant([0]),
'user_occupation_text': tf.constant(['something else']),
'user_zip_code': tf.constant(['0'])})
cm = CandidateModel(hp['candidate'])(tf.constant(["Flipper (1963)"]))
print(qm)
print(cm)
print("---Ranks---")
print(RankingModel(hp['rank'])((qm, cm)))
Outputs:
tf.Tensor(
[[ 0.01111957 -0.00569402 0.0125189 -0.00817162 -0.01598354 -0.00456765
-0.00278555 -0.00917748 0.00891546 0.00064161 0.0166869 -0.01235288
-0.0066494 -0.00980284 0.00471782 -0.00196177 0.00076775 -0.00880383
-0.01292935 0.02296012 0.0247306 -0.01458024 0.02450829 -0.02104228
0.00308327 0.00611366 0.00268212 -0.0138782 0.00437069 0.00086666
0.00729643 -0.00432106 0.02260074 0.00700762 0.00462822 -0.01425572
0.00919784 0.00171392 0.01206899 0.02586481 0.00133068 0.00974165
0.03375589 0.00320698 0.02395621 0.01023746 0.00383784 -0.01420912
0.00319639 0.00188528 -0.00858403 -0.00972638 -0.00651975 0.01432493
-0.01951187 0.00285484 -0.00766864 -0.01873302 0.03432124 0.00225209
0.02280079 -0.00747533 0.01959535 -0.02121245]], shape=(1, 64), dtype=float32)
tf.Tensor(
[[ 0.00258152 0.02014538 0.00117832 0.02041735 -0.02042701 -0.02395442
-0.01068465 -0.02712064 0.02140838 0.00242466 -0.00810128 0.01110235
-0.00146593 0.01292215 0.00348439 0.01334237 -0.01953124 0.01687023
0.0073176 0.00047215 -0.0129725 -0.01578198 -0.01907879 0.00742687
-0.00760885 0.01814296 -0.01059827 0.01759749 -0.00437215 0.02974381
0.01503188 -0.00359801 -0.00707248 0.00693541 -0.01820476 -0.01429193
0.01161771 0.00879416 0.01932933 -0.00318049 0.01815645 0.00342331
0.01157722 0.01645537 0.01013768 -0.01330452 0.00395723 0.00353524
-0.00485211 0.00153592 -0.00889693 -0.00504893 0.00879492 -0.01121669
0.01522924 -0.0181746 -0.02131601 0.0081171 0.00515315 -0.00096183
-0.00070595 -0.01315595 -0.03314487 -0.00645945]], shape=(1, 64), dtype=float32)
---Ranks---
tf.Tensor([[-0.5163227]], shape=(1, 1), dtype=float32)
@joaoalveshenriques did you solved the problem? I followed the above suggestion but I still can't solve it. Can you share what you did for this problem? Thanks!