I have a Ranking model made with Tensorflow Recommender.
When i make predictions with him it works ok.
If i save it and load it, when making predictions with the loaded model, i get an error. Please see below my model and the error i get
Ranking model:
class HMRankingModel(tfrs.Model):
def __init__(self):
super().__init__()
# Customer model
self.customer_input = tf.keras.Input(shape=(1,), dtype=tf.string, name='customer_input')
self.customer_sl = tf.keras.layers.StringLookup(vocabulary=unique_customer_ids, mask_token=None, name='customer_string_lookup')(self.customer_input)
self.customer_embedding = tf.squeeze(tf.keras.layers.Embedding(len(unique_customer_ids) + 1, embedding_dimension, name='customer_emb')(self.customer_sl), axis=1)
self.age_input = tf.keras.Input(shape=(1,), name='age_input')
self.age_discretization = tf.keras.layers.Discretization(age_buckets.tolist(), name='age_discretization')(self.age_input)
self.age_embedding = tf.squeeze(tf.keras.layers.Embedding(len(age_buckets) + 1, embedding_dimension, name='age_embedding')(self.age_discretization), axis=1)
self.customer_merged = tf.keras.layers.concatenate([self.customer_embedding, self.age_embedding], axis=-1, name='customer_merged')
self.customer_dense = tf.keras.layers.Dense(embedding_dimension, activation=activation, name='customer_dense')(self.customer_merged)
# Article model
self.article_input = tf.keras.Input(shape=(1,), dtype=tf.string, name='article_input')
self.article_sl = tf.keras.layers.StringLookup(vocabulary=unique_article_ids, name='article_string_lookup')(self.article_input)
self.article_final = tf.squeeze(tf.keras.layers.Embedding(len(unique_article_ids)+1, embedding_dimension, name='article_emb')(self.article_sl), axis=1)
self.article_dense = tf.keras.layers.Dense(embedding_dimension, activation=activation, name='article_dense')(self.article_final)
# Multiply model
self.towers_multiplied = tf.keras.layers.Multiply(name='towers_multiplied')([self.customer_dense, self.article_dense])
self.towers_dense = tf.keras.layers.Dense(dense_size, activation=activation, name='towers_dense1')(self.towers_multiplied)
self.output_node = tf.keras.layers.Dense(1, name='output_node')(self.towers_dense)
# Model definition
self.model = tf.keras.Model(inputs={'customer_id': self.customer_input,
'article_id': self.article_input,
'age': self.age_input,
},
outputs=self.output_node)
self.task = tfrs.tasks.Ranking(
loss = tf.keras.losses.MeanSquaredError(),
metrics=[tf.keras.metrics.RootMeanSquaredError()]
)
def call(self, features):
return self.model({'customer_id': features["customer_id"],
'article_id': features["article_id"],
'age': features["age"],
})
def compute_loss(self, features_dict, training=False):
labels = features_dict.pop("count")
predictions = self(features_dict)
return self.task(labels=labels, predictions=predictions)
ranking_model = HMRankingModel()
ranking_model.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate=0.1))
ranking_model.fit(cached_train, validation_data=cached_validation, epochs=epochs)
prediction with the original model
ranking_model({
'customer_id': np.array(["18b3a4767533c8f1f6ff274b57ca200939c9fda3992c5bb3b50b31dc6d6b1ee5"]),
'age': np.array([29]),
'article_id': np.array(['562245059'])
})
outputs:
<tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[1.3872527]], dtype=float32)>
I save the model
tf.saved_model.save(ranking_model, ranking_model_path)
On loading the model and making predictions i get an error
saved_ranking_model = tf.saved_model.load(ranking_model_path)
predictions = saved_ranking_model({
'customer_id': np.array(["18b3a4767533c8f1f6ff274b57ca200939c9fda3992c5bb3b50b31dc6d6b1ee5"]),
'age': np.array([29]),
'article_id': np.array(['141661025'])
})
output:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [31], in <cell line: 1>()
----> 1 predictions = saved_ranking_model({
2 'customer_id': np.array(["18b3a4767533c8f1f6ff274b57ca200939c9fda3992c5bb3b50b31dc6d6b1ee5"]),
3 'age': np.array([29]),
4 'article_id': np.array(['141661025'])
5 })
File ~/miniconda3/envs/tf/lib/python3.9/site-packages/tensorflow/python/saved_model/load.py:686, in _call_attribute(instance, *args, **kwargs)
685 def _call_attribute(instance, *args, **kwargs):
--> 686 return instance.__call__(*args, **kwargs)
File ~/miniconda3/envs/tf/lib/python3.9/site-packages/tensorflow/python/util/traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
151 except Exception as e:
152 filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153 raise e.with_traceback(filtered_tb) from None
154 finally:
155 del filtered_tb
File ~/miniconda3/envs/tf/lib/python3.9/site-packages/tensorflow/python/saved_model/function_deserialization.py:286, in recreate_function.<locals>.restored_function_body(*args, **kwargs)
282 positional, keyword = concrete_function.structured_input_signature
283 signature_descriptions.append(
284 "Option {}:\n {}\n Keyword arguments: {}"
285 .format(index + 1, _pretty_format_positional(positional), keyword))
--> 286 raise ValueError(
287 "Could not find matching concrete function to call loaded from the "
288 f"SavedModel. Got:\n {_pretty_format_positional(args)}\n Keyword "
289 f"arguments: {kwargs}\n\n Expected these arguments to match one of the "
290 f"following {len(saved_function.concrete_functions)} option(s):\n\n"
291 f"{(chr(10)+chr(10)).join(signature_descriptions)}")
ValueError: Could not find matching concrete function to call loaded from the SavedModel. Got:
Positional arguments (2 total):
* {'age': <tf.Tensor 'features:0' shape=(1,) dtype=int64>,
'article_id': <tf.Tensor 'features_1:0' shape=(1,) dtype=string>,
'customer_id': <tf.Tensor 'features_2:0' shape=(1,) dtype=string>}
* False
Keyword arguments: {}
Expected these arguments to match one of the following 4 option(s):
Option 1:
Positional arguments (2 total):
* {'age': TensorSpec(shape=(None,), dtype=tf.float32, name='age'),
'article_id': TensorSpec(shape=(None,), dtype=tf.string, name='article_id'),
'customer_id': TensorSpec(shape=(None,), dtype=tf.string, name='customer_id')}
* False
Keyword arguments: {}
Option 2:
Positional arguments (2 total):
* {'age': TensorSpec(shape=(None,), dtype=tf.float32, name='features/age'),
'article_id': TensorSpec(shape=(None,), dtype=tf.string, name='features/article_id'),
'customer_id': TensorSpec(shape=(None,), dtype=tf.string, name='features/customer_id')}
* False
Keyword arguments: {}
Option 3:
Positional arguments (2 total):
* {'age': TensorSpec(shape=(None,), dtype=tf.float32, name='features/age'),
'article_id': TensorSpec(shape=(None,), dtype=tf.string, name='features/article_id'),
'customer_id': TensorSpec(shape=(None,), dtype=tf.string, name='features/customer_id')}
* True
Keyword arguments: {}
Option 4:
Positional arguments (2 total):
* {'age': TensorSpec(shape=(None,), dtype=tf.float32, name='age'),
'article_id': TensorSpec(shape=(None,), dtype=tf.string, name='article_id'),
'customer_id': TensorSpec(shape=(None,), dtype=tf.string, name='customer_id')}
* True
Keyword arguments: {}
If i remove the age data and all age related layers from the model, it works ok. I guess it may be a problem with the age layers but i can't figure it out
There is a problem with the data for the saved_model. The value for 'age' needs to be converted to float32.
predictions = saved_ranking_model({
'customer_id': np.array(["18b3a4767533c8f1f6ff274b57ca200939c9fda3992c5bb3b50b31dc6d6b1ee5"]),
'age': np.array([np.float32(29.0)]),
'article_id': np.array(['141661025'])
})
Related
I am trying to make a listwise ranking model similar to the Tensorflow Listwise Ranking Tutorial, however, the only difference is changing how the embedding is done. I want to use the BERT embedding model shown in Tensorflow Hub.
Here is my code:
import tensorflow_hub as hub
import tensorflow_text as text
import tensorflow as tf
import tensorflow_datasets as tfds
import numpy as np
import tensorflow_ranking as tfr
import tensorflow_recommenders as tfrs
preprocessor = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3")
encoder = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/4",trainable=True)
text_input = tf.keras.layers.Input(shape=(), dtype=tf.string)
encoder_inputs = preprocessor(text_input)
outputs = encoder(encoder_inputs)
pooled_output = outputs["pooled_output"]
embedding_model1 = tf.keras.Model({"user_id":text_input}, pooled_output)
text_input = tf.keras.layers.Input(shape=(), dtype=tf.string)
encoder_inputs = preprocessor(text_input)
outputs = encoder(encoder_inputs)
pooled_output = outputs["pooled_output"]
embedding_model2 = tf.keras.Model({"movie_title": text_input}, pooled_output)
ratings = tfds.load("movielens/100k-ratings", split="train")
movies = tfds.load("movielens/100k-movies", split="train")
ratings = ratings.map(lambda x: {
"movie_title": x["movie_title"],
"user_id": x["user_id"],
"user_rating": x["user_rating"],
})
movies = movies.map(lambda x: x["movie_title"])
unique_movie_titles = np.unique(np.concatenate(list(movies.batch(1000))))
unique_user_ids = np.unique(np.concatenate(list(ratings.batch(1_000).map(
lambda x: x["user_id"]))))
tf.random.set_seed(42)
# Split between train and tests sets, as before.
shuffled = ratings.shuffle(100_000, seed=42, reshuffle_each_iteration=False)
train = shuffled.take(80_000)
test = shuffled.skip(80_000).take(20_000)
# We sample 50 lists for each user for the training data. For each list we
# sample 5 movies from the movies the user rated.
train = tfrs.examples.movielens.sample_listwise(
train,
num_list_per_user=50,
num_examples_per_list=5,
seed=42
)
test = tfrs.examples.movielens.sample_listwise(
test,
num_list_per_user=1,
num_examples_per_list=5,
seed=42
)
epochs = 10
cached_train = train.shuffle(100_000).batch(32).cache()
cached_test = test.batch(16).cache()
class RankingModel(tfrs.Model):
def __init__(self, loss):
super().__init__()
# Compute embeddings for users.
self.user_embeddings = embedding_model1
# Compute embeddings for movies.
self.movie_embeddings = embedding_model2
# Compute predictions.
self.score_model = tf.keras.Sequential([
# Learn multiple dense layers.
tf.keras.layers.Dense(256, activation="relu"),
tf.keras.layers.Dense(64, activation="relu"),
# Make rating predictions in the final layer.
tf.keras.layers.Dense(1)
])
self.task = tfrs.tasks.Ranking(
loss=loss,
metrics=[
tfr.keras.metrics.NDCGMetric(name="ndcg_metric"),
tf.keras.metrics.RootMeanSquaredError()
]
)
def call(self, features):
# We first convert the id features into embeddings.
# User embeddings are a [batch_size, embedding_dim] tensor.
user_embeddings = self.user_embeddings(features["user_id"])
# Movie embeddings are a [batch_size, num_movies_in_list, embedding_dim]
# tensor.
movie_embeddings = self.movie_embeddings(features["movie_title"])
# We want to concatenate user embeddings with movie emebeddings to pass
# them into the ranking model. To do so, we need to reshape the user
# embeddings to match the shape of movie embeddings.
list_length = features["movie_title"].shape[1]
user_embedding_repeated = tf.repeat(
tf.expand_dims(user_embeddings, 1), [list_length], axis=1)
# Once reshaped, we concatenate and pass into the dense layers to generate
# predictions.
concatenated_embeddings = tf.concat(
[user_embedding_repeated, movie_embeddings], 2)
return self.score_model(concatenated_embeddings)
def compute_loss(self, features, training=False):
labels = features.pop("user_rating")
scores = self(features)
return self.task(
labels=labels,
predictions=tf.squeeze(scores, axis=-1),
)
mse_model = RankingModel(tf.keras.losses.MeanSquaredError())
mse_model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
mse_model.fit(cached_train, epochs=1, verbose=False)
mse_model.summary()
I think the issue might be the fact that BERT from Tensorflow Hub can only take in 1D tensors like (N,). How can I change the code so I can make a listwise ranking model that uses BERT as the embedder? Here is the error message I get:
WARNING:tensorflow:Model was constructed with shape (None,) for input KerasTensor(type_spec=TensorSpec(shape=(None,), dtype=tf.string, name='input_39'), name='input_39', description="created by layer 'input_39'"), but it was called on an input with incompatible shape (None, 5).
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-117-f6e1e67627f1> in <module>
127 mse_model = RankingModel(tf.keras.losses.MeanSquaredError())
128 mse_model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
--> 129 mse_model.fit(cached_train, epochs=1, verbose=False)
130 mse_model.summary()
7 frames
/usr/local/lib/python3.7/dist-packages/tensorflow_hub/keras_layer.py in <lambda>()
70 training = False
71 ag__.if_stmt(ag__.ld(self).trainable, if_body_2, else_body_2, get_state_2, set_state_2, ('training',), 1)
---> 72 result = ag__.converted_call(ag__.ld(smart_cond).smart_cond, (ag__.ld(training), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=True), fscope))), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=False), fscope)))), None, fscope)
73 result = ag__.Undefined('result')
74 ag__.if_stmt(ag__.not_(ag__.ld(self)._has_training_argument), if_body_3, else_body_3, get_state_3, set_state_3, ('result', 'training'), 1)
ValueError: 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-117-f6e1e67627f1>", line 120, in compute_loss
scores = self(features)
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
File "/tmp/__autograph_generated_filedc6sn1ck.py", line 11, in tf__call
movie_embeddings = ag__.converted_call(ag__.ld(self).movie_embeddings, (ag__.ld(features)['movie_title'],), None, fscope)
File "/tmp/__autograph_generated_file6e8815fm.py", line 74, in tf__call
ag__.if_stmt(ag__.not_(ag__.ld(self)._has_training_argument), if_body_3, else_body_3, get_state_3, set_state_3, ('result', 'training'), 1)
File "/tmp/__autograph_generated_file6e8815fm.py", line 72, in else_body_3
result = ag__.converted_call(ag__.ld(smart_cond).smart_cond, (ag__.ld(training), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=True), fscope))), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=False), fscope)))), None, fscope)
File "/tmp/__autograph_generated_file6e8815fm.py", line 72, in <lambda>
result = ag__.converted_call(ag__.ld(smart_cond).smart_cond, (ag__.ld(training), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=True), fscope))), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=False), fscope)))), None, fscope)
ValueError: Exception encountered when calling layer "ranking_model_13" " f"(type RankingModel).
in user code:
File "<ipython-input-117-f6e1e67627f1>", line 101, in call *
movie_embeddings = self.movie_embeddings(features["movie_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
File "/tmp/__autograph_generated_file6e8815fm.py", line 74, in tf__call
ag__.if_stmt(ag__.not_(ag__.ld(self)._has_training_argument), if_body_3, else_body_3, get_state_3, set_state_3, ('result', 'training'), 1)
File "/tmp/__autograph_generated_file6e8815fm.py", line 72, in else_body_3
result = ag__.converted_call(ag__.ld(smart_cond).smart_cond, (ag__.ld(training), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=True), fscope))), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=False), fscope)))), None, fscope)
File "/tmp/__autograph_generated_file6e8815fm.py", line 72, in <lambda>
result = ag__.converted_call(ag__.ld(smart_cond).smart_cond, (ag__.ld(training), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=True), fscope))), ag__.autograph_artifact((lambda : ag__.converted_call(ag__.ld(f), (), dict(training=False), fscope)))), None, fscope)
ValueError: Exception encountered when calling layer "keras_layer_8" " f"(type KerasLayer).
in user code:
File "/usr/local/lib/python3.7/dist-packages/tensorflow_hub/keras_layer.py", line 237, in call *
result = smart_cond.smart_cond(training,
ValueError: Could not find matching concrete function to call loaded from the SavedModel. Got:
Positional arguments (3 total):
* <tf.Tensor 'inputs:0' shape=(None, 5) dtype=string>
* False
* None
Keyword arguments: {}
Expected these arguments to match one of the following 4 option(s):
Option 1:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='sentences')
* False
* None
Keyword arguments: {}
Option 2:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='sentences')
* True
* None
Keyword arguments: {}
Option 3:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='inputs')
* False
* None
Keyword arguments: {}
Option 4:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='inputs')
* True
* None
Keyword arguments: {}
Call arguments received by layer "keras_layer_8" " f"(type KerasLayer):
• inputs=tf.Tensor(shape=(None, 5), dtype=string)
• training=False
Call arguments received by layer "ranking_model_13" " f"(type RankingModel):
• features={'user_id': 'tf.Tensor(shape=(None,), dtype=string)', 'movie_title': 'tf.Tensor(shape=(None, 5), dtype=string)'}
I am currently trying to do a classification problem using a pre-trained transformer model. I wrote a custom generator using tf.data.Dataset.from_generator method. The model takes two inputs : input_id and attn_mask. While calling model.fit i am getting value error "not enough values to unpack (expected 2, got 1)" The received arguments list shows it got both input_id and attn_mask. Can anyone help me solve this?
import tensorflow.keras as keras
from tensorflow.keras.models import Model
from transformers import TFBertModel,BertConfig
def _input_fn():
x = (train_data.iloc[:,0:512]).to_numpy()
y = (train_data.iloc[:,512:516]).to_numpy()
attn = np.asarray(np.tile(attn_mask,x.shape[0]).reshape(-1,512))
def generator():
for s1, s2, l in zip(x, attn, y):
yield {"input_id": s1, "attn_mask": s2}, l
dataset = tf.data.Dataset.from_generator(generator, output_types=({"input_id": tf.int32, "attn_mask": tf.int32}, tf.int32))
#dataset = dataset.batch(2)
#dataset = dataset.shuffle
return dataset
train_data is the dataframe containing the training data(16000 x 516). Last four columns are one hot encoded labels. Since i am not using the Autotokenizer function, i am passing the attention mask as attn_mask.
my model
bert = 'bert-base-uncased'
config = BertConfig(dropout=0.2, attention_dropout=0.2)
config.output_hidden_states = False
transformer_model = TFBertModel.from_pretrained(bert, config = config)
input_ids_in = tf.keras.layers.Input(shape=(512), name='input_id', dtype='int32')
input_masks_in = tf.keras.layers.Input(shape=(512), name='attn_mask', dtype='int32')
embedding_layer = transformer_model(input_ids_in, attention_mask=input_masks_in)[0]
#cls_token = embedding_layer[:,0,:]
#X = tf.keras.layers.BatchNormalization()(cls_token)
X = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(50, return_sequences=True, dropout=0.1, recurrent_dropout=0.1))(embedding_layer)
X = tf.keras.layers.GlobalMaxPool1D()(X)
#X = tf.keras.layers.BatchNormalization()(X)
X = tf.keras.layers.Dense(50, activation='relu')(X)
X = tf.keras.layers.Dropout(0.2)(X)
X = tf.keras.layers.Dense(4, activation='softmax')(X)
model = tf.keras.Model(inputs=[input_ids_in, input_masks_in], outputs = X)
for layer in model.layers[:3]:
layer.trainable = False
optimizer = tf.keras.optimizers.Adam(0.001, beta_1=0.9, beta_2=0.98,
epsilon=1e-9)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['categorical_accuracy'])
epochs = 1
batch_size =2
history = model.fit(_input_fn(), epochs= epochs, batch_size= batch_size, verbose=2)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_16908/300834086.py in <module>
2 batch_size =2
3 #history = model.fit(trainDataGenerator(batch_size), epochs= epochs, validation_data=valDataGenerator(batch_size), verbose=2) #
----> 4 history = model.fit(_input_fn(), epochs= epochs, batch_size= batch_size, verbose=2) #validation_data=val_ds,
~/.local/lib/python3.8/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
~/.local/lib/python3.8/site-packages/transformers/models/bert/modeling_tf_bert.py in call(self, input_ids, attention_mask, token_type_ids, position_ids, head_mask, inputs_embeds, encoder_hidden_states, encoder_attention_mask, past_key_values, use_cache, output_attentions, output_hidden_states, return_dict, training, **kwargs)
1124 kwargs_call=kwargs,
1125 )
-> 1126 outputs = self.bert(
1127 input_ids=inputs["input_ids"],
1128 attention_mask=inputs["attention_mask"],
~/.local/lib/python3.8/site-packages/transformers/models/bert/modeling_tf_bert.py in call(self, input_ids, attention_mask, token_type_ids, position_ids, head_mask, inputs_embeds, encoder_hidden_states, encoder_attention_mask, past_key_values, use_cache, output_attentions, output_hidden_states, return_dict, training, **kwargs)
771 raise ValueError("You have to specify either input_ids or inputs_embeds")
772
--> 773 batch_size, seq_length = input_shape
774
775 if inputs["past_key_values"] is None:
ValueError: Exception encountered when calling layer "bert" (type TFBertMainLayer).
not enough values to unpack (expected 2, got 1)
Call arguments received:
• input_ids=tf.Tensor(shape=(512,), dtype=int32)
• attention_mask=tf.Tensor(shape=(512,), dtype=int32)
• token_type_ids=None
• position_ids=None
• head_mask=None
• inputs_embeds=None
• encoder_hidden_states=None
• encoder_attention_mask=None
• past_key_values=None
• use_cache=True
• output_attentions=False
• output_hidden_states=False
• return_dict=True
• training=True
• kwargs=<class 'inspect._empty'>
Edit:
Adding the output of calling _input_fn()
<FlatMapDataset shapes: ({input_id: <unknown>, attn_mask: <unknown>}, <unknown>), types: ({input_id: tf.int32, attn_mask: tf.int32}, tf.int32)>
I solved this error by batching my tf.data.Dataset. This gave the TensorSpec in my dataset a shape that had two values to unpack ->
TensorSpec(shape=(16, 200)...
This is what the error refers to.
Solution
print(train_ds) #Before Batching
new_train_ds = train_ds.batch(16, drop_remainder=True)
print(new_train_ds) #After Batching
# Before Batching
<MapDataset element_spec=({'input_ids': TensorSpec(shape=(200,),
dtype=tf.float64, name=None), 'attention_mask': TensorSpec(shape=
(200,), dtype=tf.float64, name=None)}, TensorSpec(shape=(11,),
dtype=tf.float64, name=None))>
# After Batching
<BatchDataset element_spec=({'input_ids': TensorSpec(shape=(16, 200),
dtype=tf.float64, name=None), 'attention_mask': TensorSpec(shape=(16,
200), dtype=tf.float64, name=None)}, TensorSpec(shape=(16, 11),
dtype=tf.float64, name=None))>
I'm using Tensorflow 2 and LaBSE pre-trained model on tf-hub (not much familiar with both). (https://tfhub.dev/google/LaBSE/2). I am trying to train a multi class classifier with a custom text data set. I am also following this example on BERT classifier(https://www.tensorflow.org/text/tutorials/classify_text_with_bert), to get the idea of how the model is built. This is to check only I can train and run the model. I am using data set objects for my input texts obtained from csv data which looks like this,
"Sentence","label"
"sentence sample1", 0
"sentence sample2", 3
and I split them into X, y sets as usual. However,
I get the above error when trying to train the model. Below is my code,
def build_classifier_model():
text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')
preprocessing_layer = hub.KerasLayer(tfhub_handle_preprocess, name='preprocessing')
encoder_inputs = preprocessing_layer(text_input)
encoder = hub.KerasLayer(tfhub_handle_encoder, trainable=True, name='LaBSE_encoder')
outputs = encoder(encoder_inputs)
net = outputs['pooled_output']
activation= tf.keras.activations.softmax#None
net = tf.keras.layers.Dropout(0.1)(net)
net = tf.keras.layers.Dense(4, activation=activation, name='classifier')(net)
return tf.keras.Model(text_input, net)
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)
metrics = tf.keras.metrics.SparseCategoricalAccuracy()
epochs = 5
optimizer=tf.keras.optimizers.Adam()
train_dataset = tf.data.Dataset.from_tensor_slices(( # convert to dataset objects
np.array(X_train),np.array(y_train,dtype='int32')
))
test_dataset = tf.data.Dataset.from_tensor_slices((
np.array(X_test),np.array(y_test,dtype='int32')
))
These dataset objects' specs are, <TensorSliceDataset shapes: ((), ()), types: (tf.string, tf.int32)>
classifier_model.compile(optimizer=optimizer,
loss=loss,
metrics=metrics)
his = classifier_model.fit(train_dataset, validation_data=test_dataset,
epochs=epochs, batch_size=8) #ignore that I'm using test dataset for validation dataset
The last step gives the error;
Epoch 1/5
WARNING:tensorflow:Model was constructed with shape (None,) for input KerasTensor(type_spec=TensorSpec(shape=(None,), dtype=tf.string, name='text'), name='text', description="created by layer 'text'"), but it was called on an input with incompatible shape ().
WARNING:tensorflow:Model was constructed with shape (None,) for input KerasTensor(type_spec=TensorSpec(shape=(None,), dtype=tf.string, name='text'), name='text', description="created by layer 'text'"), but it was called on an input with incompatible shape ().
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-141-3523a14b56f1> in <module>()
1 history = classifier_model.fit(train_dataset, validation_data=test_dataset,
----> 2 epochs=epochs, batch_size=8)
9 frames
/usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
984 except Exception as e: # pylint:disable=broad-except
985 if hasattr(e, "ag_error_metadata"):
--> 986 raise e.ag_error_metadata.to_exception(e)
987 else:
988 raise
ValueError: in user code:
/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/engine/training.py:855 train_function *
return step_function(self, iterator)
/usr/local/lib/python3.7/dist-packages/tensorflow_hub/keras_layer.py:237 call *
result = smart_cond.smart_cond(training,
/usr/local/lib/python3.7/dist-packages/tensorflow/python/saved_model/load.py:670 _call_attribute **
return instance.__call__(*args, **kwargs)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/def_function.py:889 __call__
result = self._call(*args, **kwds)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/def_function.py:924 _call
results = self._stateful_fn(*args, **kwds)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/function.py:3022 __call__
filtered_flat_args) = self._maybe_define_function(args, kwargs)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/function.py:3444 _maybe_define_function
graph_function = self._create_graph_function(args, kwargs)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/function.py:3289 _create_graph_function
capture_by_value=self._capture_by_value),
/usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/func_graph.py:999 func_graph_from_py_func
func_outputs = python_func(*func_args, **func_kwargs)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/def_function.py:672 wrapped_fn
out = weak_wrapped_fn().__wrapped__(*args, **kwds)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/saved_model/function_deserialization.py:291 restored_function_body
"\n\n".join(signature_descriptions)))
ValueError: Could not find matching function to call loaded from the SavedModel. Got:
Positional arguments (3 total):
* Tensor("inputs:0", shape=(), dtype=string)
* False
* None
Keyword arguments: {}
Expected these arguments to match one of the following 4 option(s):
Option 1:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='inputs')
* True
* None
Keyword arguments: {}
Option 2:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='inputs')
* False
* None
Keyword arguments: {}
Option 3:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='sentences')
* True
* None
Keyword arguments: {}
Option 4:
Positional arguments (3 total):
* TensorSpec(shape=(None,), dtype=tf.string, name='sentences')
* False
* None
Keyword arguments: {}
I think this is an issue with the dataset object's specs provided to the input but, do not understand how to fix it or the exact reason. I do not get even though my dataset object has types of "tf.string" why it is incompatible with the input expected. I looked up in existing answers and since I'm not much familiar with TF, I want to know what is the reason and how could I fix this issue.
I am trying to create a custom classification model using Tensorflow2.3 through tf.keras.Model subclassing method, in the subclass model init function, i use tf.feature_column layer to precess features. going through all of above part, i can train, save and reload the Saved_model, but when i use the reload model to do inference, i get the following error:
ValueError: Could not find matching function to call loaded from the SavedModel. Got:
Positional arguments (3 total):
* {'age': [35], 'education': ['Bachelors']}
* False
* None
Keyword arguments: {}
Expected these arguments to match one of the following 4 option(s):
Option 1:
Positional arguments (3 total):
* {'education': TensorSpec(shape=(None, 1), dtype=tf.string, name='education'), 'age': TensorSpec(shape=(None, 1), dtype=tf.int64, name='age')}
* True
* None
Keyword arguments: {}
Option 2:
Positional arguments (3 total):
* {'age': TensorSpec(shape=(None, 1), dtype=tf.int64, name='age'), 'education': TensorSpec(shape=(None, 1), dtype=tf.string, name='education')}
* False
* None
Keyword arguments: {}
Option 3:
Positional arguments (3 total):
* {'age': TensorSpec(shape=(None, 1), dtype=tf.int64, name='inputs/age'), 'education': TensorSpec(shape=(None, 1), dtype=tf.string, name='inputs/education')}
* False
* None
Keyword arguments: {}
Option 4:
Positional arguments (3 total):
* {'education': TensorSpec(shape=(None, 1), dtype=tf.string, name='inputs/education'), 'age': TensorSpec(shape=(None, 1), dtype=tf.int64, name='inputs/age')}
* True
* None
Keyword arguments: {}
When i try to create model with tf.Keras.sequential class or without tf.feature_column layer, every thing works fine, so how can i use the reloaded tf.Keras.subclassing model within tf.feature_column layer to do inference?
Here is a minal demo to reproduce my problem:
import pathlib
import time
import pandas as pd
import tensorflow as tf
from sklearn.model_selection import train_test_split
__SELECT_COLUMN_NAMES = ['age', 'education', 'income_bracket']
def get_train_test_pandas_data():
census = pd.read_csv("/Users/vincent/Projects/DeePray/examples/census/data/raw_data/adult_data.csv")
census['income_bracket'] = census['income_bracket'].apply(lambda label: 0 if label == ' <=50K' else 1)
census = census[__SELECT_COLUMN_NAMES]
y_labels = census.pop('income_bracket')
x_data = census
x_train, x_test, y_train, y_test = train_test_split(x_data, y_labels, test_size=0.3)
return x_train, x_test, y_train, y_test
def get_feature_columns():
age = tf.feature_column.numeric_column("age", dtype=tf.int64)
education = tf.feature_column.embedding_column(
tf.feature_column.categorical_column_with_hash_bucket("education", hash_bucket_size=1000),
dimension=100)
feat_cols = [age, education]
return feat_cols
if (tf.__version__ < '2.0'):
tf.enable_eager_execution()
x_train, _, y_train, _ = get_train_test_pandas_data()
dataset = tf.data.Dataset.from_tensor_slices((dict(x_train), y_train))
dataset = dataset.shuffle(len(x_train)).batch(4)
feat_cols = get_feature_columns()
class mymodel(tf.keras.Model):
def __init__(self):
super(mymodel, self).__init__()
self.layer1 = tf.keras.layers.DenseFeatures(feature_columns=feat_cols)
self.layer2 = tf.keras.layers.Dense(10, activation='relu')
self.layer3 = tf.keras.layers.Dense(10, activation='relu')
self.layer4 = tf.keras.layers.Dense(1, activation='sigmoid')
#tf.function
def call(self, inputs, training=None, mask=None):
x = self.layer1(inputs)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
return x
model = mymodel()
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit(dataset, epochs=1)
__SAVED_MODEL_DIR = './saved_models/census_keras/{}'.format(int(time.time()))
pathlib.Path(__SAVED_MODEL_DIR).mkdir(parents=True, exist_ok=True)
tf.saved_model.save(model, export_dir=__SAVED_MODEL_DIR)
you can replace model = mymodel() with
model = tf.keras.Sequential([
tf.keras.layers.DenseFeatures(feature_columns=feat_cols),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
that will work fine.
After trained and saved the model, i try to load the SavedModel to do predict:
import tensorflow as tf
# loaded_model = tf.keras.models.load_model("./saved_models/census_keras/1601196783") # tf.saved_model.load("saved/1")
loaded_model = tf.keras.models.load_model("./saved_models/census_keras/1601196783")
y_pred = loaded_model.call({"age": [35],
"education": ["Bachelors"]})
print(y_pred)
y_pred = loaded_model.call({"age": [40],
"education": ["Assoc-voc"]})
print(y_pred)
How can i use the reloaded tf.Keras.subclassing model within tf.feature_column layer to do inference?This puzzled me for days, Can anyone post an example to do that? I will be appreciated
This problem has beed solved by https://github.com/tensorflow/tensorflow/issues/43605#issuecomment-739076002
I want to apply a condition on the output of a dense layer. For this, I tried to customize the Dense layer of Keras but when I run my code I get the error
ValueError: No gradients provided for any variable, check your graph for ops that do not support gradients, between variables ["<tf.Variable 'scope0/rnn/while/lstm_cell/kernel:0' shape=(3, 512) dtype=float32>", "<tf.Variable 'scope0/rnn/while/lstm_cell/recurrent_kernel:0' shape=(128, 512) dtype=float32>", "<tf.Variable 'scope0/rnn/while/lstm_cell/bias:0' shape=(512,) dtype=float32>", "<tf.Variable 'scope0/my_dense/kernel:0' shape=(128, 1) dtype=float32>", "<tf.Variable 'scope0/my_dense/bias:0' shape=(1,) dtype=float32>"] and loss Tensor("Sum:0", shape=(), dtype=float32).
I am putting the condition inside the call function where the output checked against a condition i.e. if<= 0.001 then the output should be one otherwise 0.0. The Dense layer I am using is just a copy of Keras Dense layer with some modifications in the call method which implement the above condition.
class MyDense(Layer):
def __init__(self,
units,
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
apply_cond = False,
**kwargs):
if 'input_shape' not in kwargs and 'input_dim' in kwargs:
kwargs['input_shape'] = (kwargs.pop('input_dim'),)
super(MyDense, self).__init__(
activity_regularizer=regularizers.get(activity_regularizer), **kwargs)
self.units = int(units)
self.activation = activations.get(activation)
self.use_bias = use_bias
self.kernel_initializer = initializers.get(kernel_initializer)
self.bias_initializer = initializers.get(bias_initializer)
self.kernel_regularizer = regularizers.get(kernel_regularizer)
self.bias_regularizer = regularizers.get(bias_regularizer)
self.kernel_constraint = constraints.get(kernel_constraint)
self.bias_constraint = constraints.get(bias_constraint)
self.apply_cond = apply_cond
self.supports_masking = True
self.input_spec = InputSpec(min_ndim=2)
def build(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape)
if tensor_shape.dimension_value(input_shape[-1]) is None:
raise ValueError('The last dimension of the inputs to `Dense` '
'should be defined. Found `None`.')
last_dim = tensor_shape.dimension_value(input_shape[-1])
self.input_spec = InputSpec(min_ndim=2,
axes={-1: last_dim})
self.kernel = self.add_weight(
'kernel',
shape=[last_dim, self.units],
initializer=self.kernel_initializer,
regularizer=self.kernel_regularizer,
constraint=self.kernel_constraint,
dtype=self.dtype,
trainable=True)
if self.use_bias:
self.bias = self.add_weight(
'bias',
shape=[self.units,],
initializer=self.bias_initializer,
regularizer=self.bias_regularizer,
constraint=self.bias_constraint,
dtype=self.dtype,
trainable=True)
else:
self.bias = None
self.built = True
def call(self, inputs):
# print('in start of call apply_cond is: ', self.apply_cond)
inputs = ops.convert_to_tensor(inputs)
rank = common_shapes.rank(inputs)
if rank > 2:
# Broadcasting is required for the inputs.
outputs = standard_ops.tensordot(inputs, self.kernel, [[rank - 1], [0]])
# Reshape the output back to the original ndim of the input.
if not context.executing_eagerly():
shape = inputs.get_shape().as_list()
output_shape = shape[:-1] + [self.units]
outputs.set_shape(output_shape)
else:
outputs = gen_math_ops.mat_mul(inputs, self.kernel)
if self.use_bias:
outputs = nn.bias_add(outputs, self.bias)
if self.activation is not None:
outputs = self.activation(outputs) # pylint: disable=not-callable
if self.apply_cond:
cond = tf.less_equal(outputs, tf.constant(0.00001), name='mycondition')
return tf.where(cond, tf.ones_like(outputs), tf.zeros_like(outputs), name='mywhere')
return outputs
def compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape)
input_shape = input_shape.with_rank_at_least(2)
if tensor_shape.dimension_value(input_shape[-1]) is None:
raise ValueError(
'The innermost dimension of input_shape must be defined, but saw: %s'
% input_shape)
return input_shape[:-1].concatenate(self.units)
How can I make the above code work?