How to fix TypeError: x and y must have the same dtype, got tf.int32 != tf.float32 with tensorflow using PyGad? - tensorflow

I have defined a new layer to be put as an input layer using Keras. The code is:
class layer(tensorflow.keras.layers.Layer):
def __init__(self):
super(layer, self).__init__()
H_init = tf.random_normal_initializer()
self.H = tf.Variable(
initial_value=H_init(shape=(1,), dtype="float32"),
trainable=True,
)
b_init = tf.zeros_initializer()
self.b = tf.Variable(
initial_value=b_init(shape=(1,), dtype="float32"), trainable=True
)
n_init = tf.zeros_initializer()
self.n = tf.Variable(
initial_value=n_init(shape=(1,), dtype="float32"), trainable=True
)
def call(self, z):
return self.H**2 / (1+(1/self.b)**(2/self.n)) *(1+((1+z)/self.b)**(2/self.n))
I intend to put this layer as input in my generation callback function, which is
`def callback_generation(ga_instance):
print("Generation"= {generation}".format(generation=ga_instance.generations_completed))
print("Fitness =
{fitness}".format(fitness=ga_instance.best_solution()[1]))
inputs = tensorflow.keras.Input(shape=(1,), name="inputs")
targets = tensorflow.keras.Input(shape=(1,), name="targets")
logits = tensorflow.keras.layers.Dense(15)(inputs)
predictions = layer(name="predictions")(logits, targets)
model = keras.Model(inputs=[inputs, targets],
outputs=predictions)
data = {
"inputs": z,
"targets": H_z,
}
model = tensorflow.keras.Sequential(inputs=input_layer,
outputs=output_layer)
weights_vector =
tensorflow.pygad.kerasga.model_weights_as_vector(model=model)
keras_ga = pygad.kerasga.KerasGA(model=model,
num_solutions=12)
model.summary()`
This gives me an error reporting that the tf__call() method takes 2 positional arguments but 3 were given.
This is the detailed error traceback:
TypeError Traceback (most
recent call last)
<ipython-input-101-e09c7d4f3228> in <module>
20 targets = tensorflow.keras.Input(shape=(1,),
name="targets")
21 logits = tensorflow.keras.layers.Dense(15)(inputs)
---> 22 predictions = layer(name="predictions")(logits,
targets)
23
24 model = keras.Model(inputs=[inputs, targets],
outputs=predictions)
~/anaconda3/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py in
__call__(self, *args, **kwargs)
950 if _in_functional_construction_mode(self, inputs,
args, kwargs, input_list):
951 return self._functional_construction_call(inputs,
args, kwargs,
--> 952
input_list)
953
954 # Maintains info about the `Layer.call` stack.
~/anaconda3/lib/python3.7/site-
packages/tensorflow/python/keras/engine/base_layer.py in
_functional_construction_call(self, inputs, args, kwargs,
input_list)
1089 # Check input assumptions set after layer
building, e.g. input shape.
1090 outputs = self._keras_tensor_symbolic_call(
-> 1091 inputs, input_masks, args, kwargs)
1092
1093 if outputs is None:
~/anaconda3/lib/python3.7/site-
packages/tensorflow/python/keras/engine/base_layer.py in
_keras_tensor_symbolic_call(self, inputs, input_masks, args,
kwargs)
820 return
nest.map_structure(keras_tensor.KerasTensor, output_signature)
821 else:
--> 822 return self._infer_output_signature(inputs, args,
kwargs, input_masks)
823
824 def _infer_output_signature(self, inputs, args,
kwargs, input_masks):
~/anaconda3/lib/python3.7/site-
packages/tensorflow/python/keras/engine/base_layer.py in
_infer_output_signature(self, inputs, args, kwargs,
input_masks)
861 # TODO(kaftan): do we maybe_build here, or
have we already done it?
862 self._maybe_build(inputs)
--> 863 outputs = call_fn(inputs, *args, **kwargs)
864
865 self._handle_activity_regularization(inputs,
outputs)
~/anaconda3/lib/python3.7/site-
packages/tensorflow/python/autograph/impl/api.py in
wrapper(*args, **kwargs)
668 except Exception as e: # pylint:disable=broad-
except
669 if hasattr(e, 'ag_error_metadata'):
--> 670 raise e.ag_error_metadata.to_exception(e)
671 else:
672 raise
TypeError: in user code:
TypeError: tf__call() takes 2 positional arguments but 3 were given

Related

Tokenize dataset using map on tf.data.Dataset.from_tensor_slices(....)

Note: I am using the free TPU provided on Kaggle.
I want to tokenize the text using transformers such that I tokenize only the batch while training the model instead of first tokenizing the whole dataset and then creating batches from the tokenized dataset as it flows OOM and is also inefficient. Below is a basic overview of what I want
tokenizer = transformers.RobertaTokenizerFast.from_pretrained('roberta-base')
def tokenize(text, labels):
tokenized = tokenizer(text, padding=True, truncation=True, max_length=MAX_LEN)
ids = tokenized['input_ids']
mask = tokenized['attention_mask']
return (ids, mask), labels
train_dataset = tf.data.Dataset.from_tensor_slices((text, train_label_chunk)).batch(BATCH_SIZE)
train_dataset = train_dataset.map(tokenize)
Below is the error it gives. I won't share the whole trace as the error is pretty clear
ValueError: text input must of type `str` (single example), `List[str]` (batch or single pretokenized example) or `List[List[str]]` (batch of pretokenized examples)
while should be solved by something like this
for i in train_dataset:
sample = i[0]
break
sample.numpy()[0].decode()
which gives a proper string but decoding every single tf.string is not possible. Also, it gives an error anyway when I try this
def tokenize(text, labels):
text = text.numpy()
tokenized = tokenizer(text, padding=True, truncation=True, max_length=MAX_LEN)
ids = tokenized['input_ids']
mask = tokenized['attention_mask']
return (ids, mask), labels
error
AttributeError: in user code:
<ipython-input-37-857b904b7110>:2 tokenize *
text = text.numpy()
AttributeError: 'Tensor' object has no attribute 'numpy'
I am not sure why is it there but in any case, this can't be done. The following GitHub trace can also be seen on the same topic here
Below are some other things that I tried. First I created a new dataset class
class TrainDataset():
def __init__(self, text, label, batch_size):
self.text = text
self.label = label
self.batch_size = batch_size
def __len__(self):
return len(self.text) // self.batch_size
def __getitem__(self, idx):
text = self.text[idx*self.batch_size:(idx+1)*self.batch_size]
label = self.label[idx*self.batch_size:(idx+1)*self.batch_size]
return text, label
ds = TrainDataset()
def train_loop(train_dataset):
with strategy.scope():
for step, (x, y) in enumerate(train_dataset):
train_data = tokenizer(x, padding=True, truncation=True, max_length=MAX_LEN, return_tensors='tf')
inputs = (train_data['input_ids'], train_data['attention_mask'])
with tf.GradientTape() as tape:
preds = model(inputs, training=True)
loss_value = loss_fun(y, preds)
grads = tape.gradient(loss_value, model.trainable_weights)
optimizer.apply_gradients(zip(grads, model.trainable_weights))
break
train_loop(ds)
which yields the following error
ValueError: Please use `tf.keras.losses.Reduction.SUM` or `tf.keras.losses.Reduction.NONE` for loss reduction when losses are used with `tf.distribute.Strategy` outside of the built-in training loops. You can implement `tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE` using global batch size like:
with strategy.scope():
loss_obj = tf.keras.losses.CategoricalCrossentropy(reduction=tf.keras.losses.Reduction.NONE)
....
loss = tf.reduce_sum(loss_obj(labels, predictions)) * (1. / global_batch_size)
Please see https://www.tensorflow.org/tutorials/distribute/custom_training for more details.
After which, I changed loss_fun to loss_object as below (Also changed the activation of the last layer to get the logits)
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)
which gives the below mentioned error
RuntimeError: `apply_gradients() cannot be called in cross-replica context. Use `tf.distribute.Strategy.run` to enter replica context.
At this point I wrote all custom function
def train_step(inputs):
x, y = inputs
with tf.GradientTape() as tape:
predictions = model(x, training=True)
loss = compute_loss(y, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
train_accuracy.update_state(y, predictions)
return loss
#tf.function
def distributed_train_step(dataset_inputs):
x, y = dataset_inputs
train_data = tokenizer(x, padding=True, truncation=True, max_length=MAX_LEN, return_tensors='tf')
inputs = (train_data['input_ids'], train_data['attention_mask'])
dataset_inputs = (inputs, y)
per_replica_losses = strategy.run(train_step, args=(dataset_inputs,))
return strategy.reduce(tf.distribute.ReduceOp.SUM, per_replica_losses,
axis=None)
for epoch in range(2):
# TRAIN LOOP
total_loss = 0.0
num_batches = 0
for x in tqdm(ds):
total_loss += distributed_train_step(x)
num_batches += 1
train_loss = total_loss / num_batches
template = ("Epoch {}, Loss: {}, Accuracy: {}")
print(template.format(epoch+1, train_loss, train_accuracy.result()*100))
train_accuracy.reset_states()
which fortunately did ran but gave the below error
StagingError Traceback (most recent call last)
<ipython-input-24-2cda132cf9fa> in <module>
4 num_batches = 0
5 for x in tqdm(ds):
----> 6 total_loss += distributed_train_step(x)
7 num_batches += 1
8 train_loss = total_loss / num_batches
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in __call__(self, *args, **kwds)
826 tracing_count = self.experimental_get_tracing_count()
827 with trace.Trace(self._name) as tm:
--> 828 result = self._call(*args, **kwds)
829 compiler = "xla" if self._experimental_compile else "nonXla"
830 new_tracing_count = self.experimental_get_tracing_count()
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in _call(self, *args, **kwds)
860 # In this case we have not created variables on the first call. So we can
861 # run the first trace but we should fail if variables are created.
--> 862 results = self._stateful_fn(*args, **kwds)
863 if self._created_variables:
864 raise ValueError("Creating variables on a non-first call to a function"
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in __call__(self, *args, **kwargs)
2939 with self._lock:
2940 (graph_function,
-> 2941 filtered_flat_args) = self._maybe_define_function(args, kwargs)
2942 return graph_function._call_flat(
2943 filtered_flat_args, captured_inputs=graph_function.captured_inputs) # pylint: disable=protected-access
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _maybe_define_function(self, args, kwargs)
3359
3360 self._function_cache.missed.add(call_context_key)
-> 3361 graph_function = self._create_graph_function(args, kwargs)
3362 self._function_cache.primary[cache_key] = graph_function
3363
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
3204 arg_names=arg_names,
3205 override_flat_arg_shapes=override_flat_arg_shapes,
-> 3206 capture_by_value=self._capture_by_value),
3207 self._function_attributes,
3208 function_spec=self.function_spec,
/opt/conda/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
988 _, original_func = tf_decorator.unwrap(python_func)
989
--> 990 func_outputs = python_func(*func_args, **func_kwargs)
991
992 # invariant: `func_outputs` contains only Tensors, CompositeTensors,
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in wrapped_fn(*args, **kwds)
632 xla_context.Exit()
633 else:
--> 634 out = weak_wrapped_fn().__wrapped__(*args, **kwds)
635 return out
636
/opt/conda/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
975 except Exception as e: # pylint:disable=broad-except
976 if hasattr(e, "ag_error_metadata"):
--> 977 raise e.ag_error_metadata.to_exception(e)
978 else:
979 raise
StagingError: in user code:
<ipython-input-19-9d8bdb5f7f7c>:4 distributed_train_step *
train_data = tokenizer(x, padding=True, truncation=True, max_length=MAX_LEN, return_tensors='tf')
/opt/conda/lib/python3.7/site-packages/transformers/tokenization_utils_base.py:2305 __call__ *
**kwargs,
/opt/conda/lib/python3.7/site-packages/transformers/tokenization_utils_base.py:2490 batch_encode_plus *
**kwargs,
/opt/conda/lib/python3.7/site-packages/transformers/models/gpt2/tokenization_gpt2_fast.py:163 _batch_encode_plus *
return super()._batch_encode_plus(*args, **kwargs)
/opt/conda/lib/python3.7/site-packages/transformers/tokenization_utils_fast.py:418 _batch_encode_plus *
for key in tokens_and_encodings[0][0].keys():
IndexError: list index out of range
The IndexError: list index out of range might be solved but the speed of training was really really slow and hence I think something is wrong.
At this point, any help will be highly appreciated.

tf.data input pipeline, dynamic shaped tensors and slicing: NotImplementedError: Cannot convert a symbolic Tensor (args_0:0) to a numpy array

I am trying to write an efficient data input using tensorflow and tf.data.
I want to replicate the functionality of PIL.Image.Image.crop, where one can pass negative bounding box values such that the crop is expanded with zeros.
For example, if I call PIL.Image.Image.crop([-10, 0, img_height, img_width]), the image has 10 additional rows at the beginning filled with zeros.
As far as I understood, using python functions in the tf.data input pipeline can slow down the code significantly, therefore I try to write everything using tensorflow functions. I also want to use prefetching, batching, shuffling etc. which is already provided by the API.
My plan to implement the PIL crop using tensorflow functions is to preallocate a (dynamically shaped) zero tensor and assign the cropped values using slicing.
This is the error I ran into: NotImplementedError: Cannot convert a symbolic Tensor (args_2:0) to a numpy array. This error may indicate that you're trying to pass a Tensor to a NumPy call, which is not supported
Here is minimal code to replicate the issue:
import tensorflow as tf
ds2 = tf.data.Dataset.from_tensor_slices(np.arange(10))
def preproc(number):
o = tf.zeros((number,number))
# ...
ds2.map(preproc)
Question 1: How can I solve that issue?
Question 2: I am coming from a PyTorch background and I am confused about the complexity of the whole tf.data pipeline. Why am I restricted to tensorflow functions in order to use all the nice features?
For reference, here is my complete code so far.
class MyPreprocessing:
def __call__(self, *data):
# Complete code omitted for simplicity.
# This is called somewhere:
self._crop(...)
def _crop(self, img, center, body_size, res):
tl = tf.cast(center - body_size/2, dtype=tf.int32)
br = tf.cast(center + body_size/2, dtype=tf.int32)
height, width = tf.shape(img)[0], tf.shape(img)[1]
crop_tl = tf.stack([
tf.cond(tl[0] < 0, lambda: tf.constant(0, dtype=tf.int32), lambda: tl[0]),
tf.cond(tl[1] < 0, lambda: tf.constant(0, dtype=tf.int32), lambda: tl[1])])
crop_br = tf.stack([
tf.cond(br[0] > height, lambda: height, lambda: br[0]),
tf.cond(br[1] > width, lambda: width, lambda: br[1])])
crop = tf.image.crop_to_bounding_box(
img,
crop_tl[0],
crop_tl[1],
crop_br[0] - crop_tl[1],
crop_br[1] - crop_tl[1])
new_tl = crop_tl - tl
new_br = crop_br - tl
# Error:
new_img = tf.zeros((body_size, body_size, tf.constant(3)), dtype=tf.float32)
new_img[new_tl[0]:new_br[0], new_tl[1]:new_br[1]].assign(crop)
return tf.image.resize(new_img, (res, res))
Edit: Full Stacktrace
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-2-84d20c31b9c9> in <module>
8 # ...
9
---> 10 ds2.map(preproc)
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/data/ops/dataset_ops.py in map(self, map_func, num_parallel_calls, deterministic)
1923 warnings.warn("The `deterministic` argument has no effect unless the "
1924 "`num_parallel_calls` argument is specified.")
-> 1925 return MapDataset(self, map_func, preserve_cardinality=True)
1926 else:
1927 return ParallelMapDataset(
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, input_dataset, map_func, use_inter_op_parallelism, preserve_cardinality, use_legacy_function)
4481 self._use_inter_op_parallelism = use_inter_op_parallelism
4482 self._preserve_cardinality = preserve_cardinality
-> 4483 self._map_func = StructuredFunctionWrapper(
4484 map_func,
4485 self._transformation_name(),
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, func, transformation_name, dataset, input_classes, input_shapes, input_types, input_structure, add_to_graph, use_legacy_function, defun_kwargs)
3710 resource_tracker = tracking.ResourceTracker()
3711 with tracking.resource_tracker_scope(resource_tracker):
-> 3712 self._function = fn_factory()
3713 # There is no graph to add in eager mode.
3714 add_to_graph &= not context.executing_eagerly()
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/eager/function.py in get_concrete_function(self, *args, **kwargs)
3132 or `tf.Tensor` or `tf.TensorSpec`.
3133 """
-> 3134 graph_function = self._get_concrete_function_garbage_collected(
3135 *args, **kwargs)
3136 graph_function._garbage_collector.release() # pylint: disable=protected-access
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/eager/function.py in _get_concrete_function_garbage_collected(self, *args, **kwargs)
3098 args, kwargs = None, None
3099 with self._lock:
-> 3100 graph_function, _ = self._maybe_define_function(args, kwargs)
3101 seen_names = set()
3102 captured = object_identity.ObjectIdentitySet(
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/eager/function.py in _maybe_define_function(self, args, kwargs)
3442
3443 self._function_cache.missed.add(call_context_key)
-> 3444 graph_function = self._create_graph_function(args, kwargs)
3445 self._function_cache.primary[cache_key] = graph_function
3446
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
3277 arg_names = base_arg_names + missing_arg_names
3278 graph_function = ConcreteFunction(
-> 3279 func_graph_module.func_graph_from_py_func(
3280 self._name,
3281 self._python_function,
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
997 _, original_func = tf_decorator.unwrap(python_func)
998
--> 999 func_outputs = python_func(*func_args, **func_kwargs)
1000
1001 # invariant: `func_outputs` contains only Tensors, CompositeTensors,
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/data/ops/dataset_ops.py in wrapped_fn(*args)
3685 attributes=defun_kwargs)
3686 def wrapped_fn(*args): # pylint: disable=missing-docstring
-> 3687 ret = wrapper_helper(*args)
3688 ret = structure.to_tensor_list(self._output_structure, ret)
3689 return [ops.convert_to_tensor(t) for t in ret]
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/data/ops/dataset_ops.py in wrapper_helper(*args)
3615 if not _should_unpack(nested_args):
3616 nested_args = (nested_args,)
-> 3617 ret = autograph.tf_convert(self._func, ag_ctx)(*nested_args)
3618 if _should_pack(ret):
3619 ret = tuple(ret)
~/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/autograph/impl/api.py in wrapper(*args, **kwargs)
693 except Exception as e: # pylint:disable=broad-except
694 if hasattr(e, 'ag_error_metadata'):
--> 695 raise e.ag_error_metadata.to_exception(e)
696 else:
697 raise
NotImplementedError: in user code:
<ipython-input-2-84d20c31b9c9>:7 preproc *
o = tf.zeros((number,number))
/home/benjs/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/util/dispatch.py:206 wrapper **
return target(*args, **kwargs)
/home/benjs/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/ops/array_ops.py:2911 wrapped
tensor = fun(*args, **kwargs)
/home/benjs/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/ops/array_ops.py:2960 zeros
output = _constant_if_small(zero, shape, dtype, name)
/home/benjs/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/ops/array_ops.py:2896 _constant_if_small
if np.prod(shape) < 1000:
<__array_function__ internals>:5 prod
/home/benjs/Documents/projects/hpe/venv/lib/python3.8/site-packages/numpy/core/fromnumeric.py:3030 prod
return _wrapreduction(a, np.multiply, 'prod', axis, dtype, out,
/home/benjs/Documents/projects/hpe/venv/lib/python3.8/site-packages/numpy/core/fromnumeric.py:87 _wrapreduction
return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
/home/benjs/Documents/projects/hpe/venv/lib/python3.8/site-packages/tensorflow/python/framework/ops.py:867 __array__
raise NotImplementedError(
NotImplementedError: Cannot convert a symbolic Tensor (args_0:0) to a numpy array. This error may indicate that you're trying to pass a Tensor to a NumPy call, which is not supported

Resize image and create tfexample for tensorflow 2 dataset results in error

I'm using Tensorflow 2.2, and trying to convert a model into TensorRT. I am following an example, which successfully works for models that accept images as input. Unfortunately, I froze a model which accepts TF Example as input instead of image. Now, trying to create the tf dataset pipeline has become a nightmare.
My code is:
def get_dataset(images_dir,
annotation_path,
batch_size,
input_size,
dtype=tf.float32):
image_ids = None
coco = COCO(annotation_file=annotation_path)
image_ids = coco.getImgIds()
image_paths = []
for image_id in image_ids:
coco_img = coco.imgs[image_id]
image_paths.append(os.path.join(images_dir, coco_img['file_name']))
dataset = tf.data.Dataset.from_tensor_slices(image_paths)
def conv_jpeg_to_tfexample_tensor(input_img_):
feature_dict = {
'image/encoded': dataset_util.bytes_feature(input_img_)
}
temp_var = tf.train.Features(feature=feature_dict)
file_ex = tf.train.Example(features=temp_var).SerializeToString()
return tf.convert_to_tensor(file_ex)
def preprocess_fn(path):
image = tf.io.read_file(path)
if input_size is not None:
image = tf.image.decode_jpeg(image, channels=3)
image = tf.image.convert_image_dtype(image, tf.float32)
image = tf.image.resize(image, size=(input_size, input_size))
image = tf.cast(image, tf.uint8)
image = tf.image.encode_jpeg(image) #.numpy()
return image
dataset = dataset.map(map_func=preprocess_fn, num_parallel_calls=3)
dataset = dataset.map(map_func=conv_jpeg_to_tfexample_tensor, num_parallel_calls=3)
dataset = dataset.batch(batch_size)
dataset = dataset.repeat(count=1)
return dataset, image_ids
This results in error with this usage:
dataset, image_ids = get_dataset(
images_dir=args.data_dir,
annotation_path=args.annotation_path,
batch_size=args.batch_size,
input_size=args.input_size)
Error
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-152-193739a79a8a> in <module>
5 batch_size=args.batch_size,
----> 6 input_size=args.input_size)
<ipython-input-151-1d1f15019758> in get_dataset(images_dir, annotation_path, batch_size, input_size, dtype)
76 dataset = dataset.map(map_func=preprocess_fn, num_parallel_calls=3)
---> 77 dataset = dataset.map(map_func=conv_jpeg_to_tfexample_tensor, num_parallel_calls=3)
78 dataset = dataset.batch(batch_size)
/opt/conda/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in map(self, map_func, num_parallel_calls, deterministic)
1626 num_parallel_calls,
1627 deterministic,
-> 1628 preserve_cardinality=True)
1629
1630 def flat_map(self, map_func):
/opt/conda/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, input_dataset, map_func, num_parallel_calls, deterministic, use_inter_op_parallelism, preserve_cardinality, use_legacy_function)
4018 self._transformation_name(),
4019 dataset=input_dataset,
-> 4020 use_legacy_function=use_legacy_function)
4021 if deterministic is None:
4022 self._deterministic = "default"
/opt/conda/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, func, transformation_name, dataset, input_classes, input_shapes, input_types, input_structure, add_to_graph, use_legacy_function, defun_kwargs)
3219 with tracking.resource_tracker_scope(resource_tracker):
3220 # TODO(b/141462134): Switch to using garbage collection.
-> 3221 self._function = wrapper_fn.get_concrete_function()
3222
3223 if add_to_graph:
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in get_concrete_function(self, *args, **kwargs)
2530 """
2531 graph_function = self._get_concrete_function_garbage_collected(
-> 2532 *args, **kwargs)
2533 graph_function._garbage_collector.release() # pylint: disable=protected-access
2534 return graph_function
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _get_concrete_function_garbage_collected(self, *args, **kwargs)
2494 args, kwargs = None, None
2495 with self._lock:
-> 2496 graph_function, args, kwargs = self._maybe_define_function(args, kwargs)
2497 if self.input_signature:
2498 args = self.input_signature
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _maybe_define_function(self, args, kwargs)
2775
2776 self._function_cache.missed.add(call_context_key)
-> 2777 graph_function = self._create_graph_function(args, kwargs)
2778 self._function_cache.primary[cache_key] = graph_function
2779 return graph_function, args, kwargs
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
2665 arg_names=arg_names,
2666 override_flat_arg_shapes=override_flat_arg_shapes,
-> 2667 capture_by_value=self._capture_by_value),
2668 self._function_attributes,
2669 # Tell the ConcreteFunction to clean up its graph once it goes out of
/opt/conda/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
979 _, original_func = tf_decorator.unwrap(python_func)
980
--> 981 func_outputs = python_func(*func_args, **func_kwargs)
982
983 # invariant: `func_outputs` contains only Tensors, CompositeTensors,
/opt/conda/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in wrapper_fn(*args)
3212 attributes=defun_kwargs)
3213 def wrapper_fn(*args): # pylint: disable=missing-docstring
-> 3214 ret = _wrapper_helper(*args)
3215 ret = structure.to_tensor_list(self._output_structure, ret)
3216 return [ops.convert_to_tensor(t) for t in ret]
/opt/conda/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in _wrapper_helper(*args)
3154 nested_args = (nested_args,)
3155
-> 3156 ret = autograph.tf_convert(func, ag_ctx)(*nested_args)
3157 # If `func` returns a list of tensors, `nest.flatten()` and
3158 # `ops.convert_to_tensor()` would conspire to attempt to stack
/opt/conda/lib/python3.7/site-packages/tensorflow/python/autograph/impl/api.py in wrapper(*args, **kwargs)
263 except Exception as e: # pylint:disable=broad-except
264 if hasattr(e, 'ag_error_metadata'):
--> 265 raise e.ag_error_metadata.to_exception(e)
266 else:
267 raise
TypeError: in user code:
<ipython-input-143-1d1f15019758>:53 conv_jpeg_to_tfexample_tensor *
feature_dict = {
/opt/conda/lib/python3.7/site-packages/object_detection/utils/dataset_util.py:34 bytes_feature *
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
TypeError: <tf.Tensor 'args_0:0' shape=() dtype=string> has type Tensor, but expected one of: bytes
I was to able to reproduce the error you are facing using a simple bird image.
Code to recreate the error -
%tensorflow_version 2.x
import tensorflow as tf
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array, array_to_img
from matplotlib import pyplot as plt
import numpy as np
from object_detection.utils import dataset_util
def load_file_and_process(path):
image = tf.io.read_file(path)
image = tf.image.decode_jpeg(image, channels=3)
image = tf.image.central_crop(image, np.random.uniform(0.50, 1.00))
image = tf.cast(image, tf.uint8)
image = tf.image.encode_jpeg(image)
return image
train_dataset = tf.data.Dataset.list_files('/content/bird.jpg')
train_dataset = train_dataset.map(load_file_and_process)
def conv_jpeg_to_tfexample_tensor(input_img_):
feature_dict = {
'image/encoded': dataset_util.bytes_feature(input_img_)
}
temp_var = tf.train.Features(feature=feature_dict)
file_ex = tf.train.Example(features=temp_var).SerializeToString()
return tf.convert_to_tensor(file_ex)
train_dataset = train_dataset.map(map_func=conv_jpeg_to_tfexample_tensor, num_parallel_calls=3)
Output -
<MapDataset shapes: (), types: tf.string>
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-44-89ae6292ad21> in <module>()
28 return tf.convert_to_tensor(file_ex)
29
---> 30 train_dataset = train_dataset.map(map_func=conv_jpeg_to_tfexample_tensor, num_parallel_calls=3)
10 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/autograph/impl/api.py in wrapper(*args, **kwargs)
256 except Exception as e: # pylint:disable=broad-except
257 if hasattr(e, 'ag_error_metadata'):
--> 258 raise e.ag_error_metadata.to_exception(e)
259 else:
260 raise
TypeError: in user code:
<ipython-input-44-89ae6292ad21>:23 conv_jpeg_to_tfexample_tensor *
feature_dict = {
/usr/local/lib/python3.6/dist-packages/object_detection/utils/dataset_util.py:30 bytes_feature *
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
TypeError: <tf.Tensor 'args_0:0' shape=() dtype=string> has type Tensor, but expected one of: bytes
Would recommend you to refer this tutorial that explains end-to-end example of how to read and write image data using TFRecords.
Referring the tutorial, I have written the TFRecord for a single image.
Code -
# This is an example, just using the bird image.
image_string = open('/content/bird.jpg', 'rb').read()
def _bytes_feature(value):
"""Returns a bytes_list from a string / byte."""
if isinstance(value, type(tf.constant(0))):
value = value.numpy() # BytesList won't unpack a string from an EagerTensor.
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def _int64_feature(value):
"""Returns an int64_list from a bool / enum / int / uint."""
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
# Create a dictionary with features that may be relevant.
def image_example(image_string):
image_shape = tf.image.decode_jpeg(image_string).shape
feature = {
'height': _int64_feature(image_shape[0]),
'width': _int64_feature(image_shape[1]),
'depth': _int64_feature(image_shape[2]),
'image_raw': _bytes_feature(image_string),
}
return tf.train.Example(features=tf.train.Features(feature=feature))
for line in str(image_example(image_string)).split('\n')[:15]:
print(line)
record_file = 'images.tfrecords'
with tf.io.TFRecordWriter(record_file) as writer:
image_string = open('/content/bird.jpg', 'rb').read()
tf_example = image_example(image_string)
writer.write(tf_example.SerializeToString())
Output -
features {
feature {
key: "depth"
value {
int64_list {
value: 3
}
}
}
feature {
key: "height"
value {
int64_list {
value: 426
}

unexpected keyword argument 'sample_weight' when sub-classing tensor-flow loss class (categorical_crossentropy) to created a weighted loss function

Struggling to get a sub-classed loss function to work in Tensorflow (2.2.0).
Initially tried this code (which I know has worked for others - see https://github.com/keras-team/keras/issues/2115#issuecomment-530762739):
import tensorflow.keras.backend as K
from tensorflow.keras.losses import CategoricalCrossentropy
class WeightedCategoricalCrossentropy(CategoricalCrossentropy):
def __init__(self, cost_mat, name='weighted_categorical_crossentropy', **kwargs):
assert(cost_mat.ndim == 2)
assert(cost_mat.shape[0] == cost_mat.shape[1])
super().__init__(name=name, **kwargs)
self.cost_mat = K.cast_to_floatx(cost_mat)
def __call__(self, y_true, y_pred):
return super().__call__(
y_true=y_true,
y_pred=y_pred,
sample_weight=get_sample_weights(y_true, y_pred, self.cost_mat),
)
def get_sample_weights(y_true, y_pred, cost_m):
num_classes = len(cost_m)
y_pred.shape.assert_has_rank(2)
y_pred.shape[1].assert_is_compatible_with(num_classes)
y_pred.shape.assert_is_compatible_with(y_true.shape)
y_pred = K.one_hot(K.argmax(y_pred), num_classes)
y_true_nk1 = K.expand_dims(y_true, 2)
y_pred_n1k = K.expand_dims(y_pred, 1)
cost_m_1kk = K.expand_dims(cost_m, 0)
sample_weights_nkk = cost_m_1kk * y_true_nk1 * y_pred_n1k
sample_weights_n = K.sum(sample_weights_nkk, axis=[1, 2])
return sample_weights_n
Used as follows:
model.compile(optimizer='adam',
loss={'simple_Class': 'categorical_crossentropy',
'soundClass': 'binary_crossentropy',
'auxiliary_soundClass':'binary_crossentropy',
'auxiliary_class_training': WeightedCategoricalCrossentropy(cost_matrix),
'class_training':WeightedCategoricalCrossentropy(cost_matrix)
},
loss_weights={'simple_Class': 1.0,
'soundClass': 1.0,
'auxiliary_soundClass':0.7,
'auxiliary_class_training': 0.7,
'class_training':0.4})
(where cost_matrix is a 2-dimensional numpy array). Training trough model.fit() with batch_size=512.
However, this results in the following error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-21-3428d6d8967a> in <module>()
82 'class_training': class_lables_test}),
83
---> 84 epochs=nb_epoch, batch_size=batch_size, initial_epoch=initial_epoch, verbose=0, shuffle=True, callbacks=[se, tb, cm, mc, es, rs])
85
86 #model.save(save_version_dir,save_format='tf')
10 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _method_wrapper(self, *args, **kwargs)
64 def _method_wrapper(self, *args, **kwargs):
65 if not self._in_multi_worker_mode(): # pylint: disable=protected-access
---> 66 return method(self, *args, **kwargs)
67
68 # Running inside `run_distribute_coordinator` already.
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
846 batch_size=batch_size):
847 callbacks.on_train_batch_begin(step)
--> 848 tmp_logs = train_function(iterator)
849 # Catch OutOfRangeError for Datasets of unknown size.
850 # This blocks until the batch has finished executing.
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/def_function.py in __call__(self, *args, **kwds)
578 xla_context.Exit()
579 else:
--> 580 result = self._call(*args, **kwds)
581
582 if tracing_count == self._get_tracing_count():
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/def_function.py in _call(self, *args, **kwds)
625 # This is the first call of __call__, so we have to initialize.
626 initializers = []
--> 627 self._initialize(args, kwds, add_initializers_to=initializers)
628 finally:
629 # At this point we know that the initialization is complete (or less
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/def_function.py in _initialize(self, args, kwds, add_initializers_to)
504 self._concrete_stateful_fn = (
505 self._stateful_fn._get_concrete_function_internal_garbage_collected( # pylint: disable=protected-access
--> 506 *args, **kwds))
507
508 def invalid_creator_scope(*unused_args, **unused_kwds):
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py in _get_concrete_function_internal_garbage_collected(self, *args, **kwargs)
2444 args, kwargs = None, None
2445 with self._lock:
-> 2446 graph_function, _, _ = self._maybe_define_function(args, kwargs)
2447 return graph_function
2448
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py in _maybe_define_function(self, args, kwargs)
2775
2776 self._function_cache.missed.add(call_context_key)
-> 2777 graph_function = self._create_graph_function(args, kwargs)
2778 self._function_cache.primary[cache_key] = graph_function
2779 return graph_function, args, kwargs
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
2665 arg_names=arg_names,
2666 override_flat_arg_shapes=override_flat_arg_shapes,
-> 2667 capture_by_value=self._capture_by_value),
2668 self._function_attributes,
2669 # Tell the ConcreteFunction to clean up its graph once it goes out of
/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
979 _, original_func = tf_decorator.unwrap(python_func)
980
--> 981 func_outputs = python_func(*func_args, **func_kwargs)
982
983 # invariant: `func_outputs` contains only Tensors, CompositeTensors,
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/def_function.py in wrapped_fn(*args, **kwds)
439 # __wrapped__ allows AutoGraph to swap in a converted function. We give
440 # the function a weak reference to itself to avoid a reference cycle.
--> 441 return weak_wrapped_fn().__wrapped__(*args, **kwds)
442 weak_wrapped_fn = weakref.ref(wrapped_fn)
443
/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
966 except Exception as e: # pylint:disable=broad-except
967 if hasattr(e, "ag_error_metadata"):
--> 968 raise e.ag_error_metadata.to_exception(e)
969 else:
970 raise
TypeError: in user code:
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:571 train_function *
outputs = self.distribute_strategy.run(
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:951 run **
return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2290 call_for_each_replica
return self._call_for_each_replica(fn, args, kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2649 _call_for_each_replica
return fn(*args, **kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:533 train_step **
y, y_pred, sample_weight, regularization_losses=self.losses)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/compile_utils.py:205 __call__
loss_value = loss_obj(y_t, y_p, sample_weight=sw)
TypeError: __call__() got an unexpected keyword argument 'sample_weight'
This problem is resolved when I replace the __call__() magic methods with call() and implement some of the underlying logic manually. This works, with the same usage. The __call__ method is changed to:
def call(self, y_true, y_pred):
return super().call(y_true, y_pred) * get_sample_weights(y_true, y_pred, self.cost_mat)
i.e. we calculate a categorical cross-entropy loss on y_true and y_pred and then multiply against our weight matrix directly, rather than passing y_true, y_pred and self-cost_mat to the categorical cross-entropy call method and use the inherited method's own logic for multiplying the loss by the weights. This isn't a massive problem, as the code does work - but I can't figure out why I was unable to use the inherited class' own __call__ implementation properly (as per the original code).
Also I changed y_pred.shape[1].assert_is_compatible_with(num_classes) to assert(y_pred.shape[1] == num_classes) - this was because y_pred.shape[1] was returning an int. I have no idea why, as, inspecting y_pred, it is, of course, a tf.Tensor, and so, .shape[1] should return a tf.TesnorShape object, upon which .assert_is_compatible_with() could be called on.
This is the whole class implementation that I've used successfully.
Note - it includes from_config and get_config methods, alongside an explicit assignment to the Keras loss namespace (last line) to enable whole-model + optimizer state saving through model.save(save_format='tf'). Some of this functionality was challenging to get working: I had to implement an explicit cast to a NumPy array (see the first line of __init__ method).
class WeightedCategoricalCrossentropy(tensorflow.keras.losses.CategoricalCrossentropy):
def __init__(self, cost_mat, name='weighted_categorical_crossentropy', **kwargs):
cost_mat = np.array(cost_mat)
## when loading from config, self.cost_mat returns as a list, rather than an numpy array.
## Adding the above line fixes this issue, enabling .ndim to call sucessfully.
## However, this is probably not the best implementation
assert(cost_mat.ndim == 2)
assert(cost_mat.shape[0] == cost_mat.shape[1])
super().__init__(name=name, **kwargs)
self.cost_mat = K.cast_to_floatx(cost_mat)
def call(self, y_true, y_pred):
return super().call(y_true, y_pred) * get_sample_weights(y_true, y_pred, self.cost_mat)
def get_config(self):
config = super().get_config().copy()
# Calling .update on the line above, during assignment, causes an error with config becoming None-type.
config.update({'cost_mat': (self.cost_mat)})
return config
#classmethod
def from_config(cls, config):
# something goes wrong here and changes self.cost_mat to a list variable.
# See above for temporary fix
return cls(**config)
def get_sample_weights(y_true, y_pred, cost_m):
num_classes = len(cost_m)
y_pred.shape.assert_has_rank(2)
assert(y_pred.shape[1] == num_classes)
y_pred.shape.assert_is_compatible_with(y_true.shape)
y_pred = K.one_hot(K.argmax(y_pred), num_classes)
y_true_nk1 = K.expand_dims(y_true, 2)
y_pred_n1k = K.expand_dims(y_pred, 1)
cost_m_1kk = K.expand_dims(cost_m, 0)
sample_weights_nkk = cost_m_1kk * y_true_nk1 * y_pred_n1k
sample_weights_n = K.sum(sample_weights_nkk, axis=[1, 2])
return sample_weights_n
tf.keras.losses.WeightedCategoricalCrossentropy = WeightedCategoricalCrossentropy
Finally, saving the model is implemented like so:
model.save(save_version_dir,save_format='tf')
and loading the model as follows:
model = tf.keras.models.load_model(
save_version_dir,
compile=True,
custom_objects={
'WeightedCategoricalCrossentropy': WeightedCategoricalCrossentropy(cost_matrix)
}
)
As per the comments; the issue here is that TensorFlow is now enforcing inheriting from the original method signature.
The following has been tested (by comparing equal weighting in the cost_matrix to weighting all but a single category to nothing) on a toy problem and works:
class WeightedCategoricalCrossentropy(tf.keras.losses.CategoricalCrossentropy):
def __init__(self, cost_mat, name='weighted_categorical_crossentropy', **kwargs):
cost_mat = np.array(cost_mat)
## when loading from config, self.cost_mat returns as a list, rather than an numpy array.
## Adding the above line fixes this issue, enabling .ndim to call sucessfully.
## However, this is probably not the best implementation
assert(cost_mat.ndim == 2)
assert(cost_mat.shape[0] == cost_mat.shape[1])
super().__init__(name=name, **kwargs)
self.cost_mat = K.cast_to_floatx(cost_mat)
def __call__(self, y_true, y_pred, sample_weight=None):
assert sample_weight is None, "should only be derived from the cost matrix"
return super().__call__(
y_true=y_true,
y_pred=y_pred,
sample_weight=get_sample_weights(y_true, y_pred, self.cost_mat),
)
def get_config(self):
config = super().get_config().copy()
# Calling .update on the line above, during assignment, causes an error with config becoming None-type.
config.update({'cost_mat': (self.cost_mat)})
return config
#classmethod
def from_config(cls, config):
# something goes wrong here and changes self.cost_mat to a list variable.
# See above for temporary fix
return cls(**config)
def get_sample_weights(y_true, y_pred, cost_m):
num_classes = len(cost_m)
y_pred.shape.assert_has_rank(2)
assert(y_pred.shape[1] == num_classes)
y_pred.shape.assert_is_compatible_with(y_true.shape)
y_pred = K.one_hot(K.argmax(y_pred), num_classes)
y_true_nk1 = K.expand_dims(y_true, 2)
y_pred_n1k = K.expand_dims(y_pred, 1)
cost_m_1kk = K.expand_dims(cost_m, 0)
sample_weights_nkk = cost_m_1kk * y_true_nk1 * y_pred_n1k
sample_weights_n = K.sum(sample_weights_nkk, axis=[1, 2])
return sample_weights_n
# Register the loss in the Keras namespace to enable loading of the custom object.
tf.keras.losses.WeightedCategoricalCrossentropy = WeightedCategoricalCrossentropy
Usage
Where cost_matrix is a 2D NumPy array, eg:
[
[ Weight Category 1 predicted as Category 1,
Weight Category 1 predicted as Category 2,
Weight Category 1 predicted as Category 3 ]
[ Weight Category 2 predicted as Category 1,
...,
... ]
[ ...,
...,
Weight Category 3 predicted as Category 3 ]
]
model.compile(
optimizer='adam',
loss=WeightedCategoricalCrossentropy(cost_matrix)
)
Model Saving
model.save(save_version_dir,save_format='tf')
Model Loading
model = tf.keras.models.load_model(
save_version_dir,
compile=True,
custom_objects={
'WeightedCategoricalCrossentropy': WeightedCategoricalCrossentropy(cost_matrix)
}
)

Using tf.data.Dataset with tf Hub Modules

How do I feed a tf.keras model, that includes a 1D input TF Hub module, with a tf.data.Dataset?
(Ultimately, the aim is to use a single tf.data.Dataset with a multi-input, multi-output keras funtional api model.)
Tried this:
import tensorflow as tf
import tensorflow_hub as hub
embed = "https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1"
hub_layer = hub.KerasLayer(embed, output_shape=[20], input_shape=[],
dtype=tf.string, trainable=True, name='hub_layer')
# From tf hub webpage: "The module takes a batch of sentences in a 1-D tensor of strings as input."
input_tensor = tf.keras.Input(shape=(), dtype=tf.string)
hub_tensor = hub_layer(input_tensor)
x = tf.keras.layers.Dense(16, activation='relu')(hub_tensor)#(x)
main_output = tf.keras.layers.Dense(units=4, activation='softmax', name='main_output')(x)
model = tf.keras.models.Model(inputs=[input_tensor], outputs=[main_output])
# This works as expected.
X_tensor = tf.constant(['Hello World', 'The Quick Brown Fox'])
model(X_tensor)
# This fails
X_ds = tf.data.Dataset.from_tensors(X_tensor)
X_ds.element_spec
model(X_ds)
Expectation was that the 1D tensor in the dataset would be automatically extracted and consumed by the model.
Error message:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in
21 X_ds = tf.data.Dataset.from_tensors(X_tensor)
22 X_ds.element_spec
---> 23 model(X_ds)
24
25
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/base_layer.py in __call__(self, *args, **kwargs)
966 with base_layer_utils.autocast_context_manager(
967 self._compute_dtype):
--> 968 outputs = self.call(cast_inputs, *args, **kwargs)
969 self._handle_activity_regularization(inputs, outputs)
970 self._set_mask_metadata(inputs, outputs, input_masks)
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py in call(self, inputs, training, mask)
717 return self._run_internal_graph(
718 inputs, training=training, mask=mask,
--> 719 convert_kwargs_to_constants=base_layer_utils.call_context().saving)
720
721 def compute_output_shape(self, input_shape):
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py in _run_internal_graph(self, inputs, training, mask, convert_kwargs_to_constants)
835 tensor_dict = {}
836 for x, y in zip(self.inputs, inputs):
--> 837 y = self._conform_to_reference_input(y, ref_input=x)
838 x_id = str(id(x))
839 tensor_dict[x_id] = [y] * self._tensor_usage_count[x_id]
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py in _conform_to_reference_input(self, tensor, ref_input)
959 # Dtype handling.
960 if isinstance(ref_input, (ops.Tensor, composite_tensor.CompositeTensor)):
--> 961 tensor = math_ops.cast(tensor, dtype=ref_input.dtype)
962
963 return tensor
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/util/dispatch.py in wrapper(*args, **kwargs)
178 """Call target, and fall back on dispatchers if there is a TypeError."""
179 try:
--> 180 return target(*args, **kwargs)
181 except (TypeError, ValueError):
182 # Note: convert_to_eager_tensor currently raises a ValueError, not a
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/ops/math_ops.py in cast(x, dtype, name)
785 # allows some conversions that cast() can't do, e.g. casting numbers to
786 # strings.
--> 787 x = ops.convert_to_tensor(x, name="x")
788 if x.dtype.base_dtype != base_type:
789 x = gen_math_ops.cast(x, base_type, name=name)
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in convert_to_tensor(value, dtype, name, as_ref, preferred_dtype, dtype_hint, ctx, accepted_result_types)
1339
1340 if ret is None:
-> 1341 ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
1342
1343 if ret is NotImplemented:
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/framework/constant_op.py in _constant_tensor_conversion_function(v, dtype, name, as_ref)
319 as_ref=False):
320 _ = as_ref
--> 321 return constant(v, dtype=dtype, name=name)
322
323
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/framework/constant_op.py in constant(value, dtype, shape, name)
260 """
261 return _constant_impl(value, dtype, shape, name, verify_shape=False,
--> 262 allow_broadcast=True)
263
264
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/framework/constant_op.py in _constant_impl(value, dtype, shape, name, verify_shape, allow_broadcast)
268 ctx = context.context()
269 if ctx.executing_eagerly():
--> 270 t = convert_to_eager_tensor(value, ctx, dtype)
271 if shape is None:
272 return t
~/projects/email_analysis/email_venv/lib/python3.6/site-packages/tensorflow/python/framework/constant_op.py in convert_to_eager_tensor(value, ctx, dtype)
94 dtype = dtypes.as_dtype(dtype).as_datatype_enum
95 ctx.ensure_initialized()
---> 96 return ops.EagerTensor(value, ctx.device_name, dtype)
97
98
ValueError: Attempt to convert a value () with an unsupported type () to a Tensor.
The point of a dataset is to provide a sequence of tensors, like here:
all_data = tf.constant([['Hello', 'World'], ['Brown Fox', 'lazy dog']])
ds = tf.data.Dataset.from_tensor_slices(all_data)
for tensor in ds:
print(tensor)
which outputs
tf.Tensor([b'Hello' b'World'], shape=(2,), dtype=string)
tf.Tensor([b'Brown Fox' b'lazy dog'], shape=(2,), dtype=string)
Instead of just printing tensor, you can compute with it:
for tensor in ds:
print(hub_layer(tensor))
which outputs 2 tensors of shape (2,20) each.
For more, see https://www.tensorflow.org/guide/data.