Sorry that I can only test on tensorflow2.9, and I havn't used tf.keras.utils.image_dataset_from_directory since its high integration.
Do you mean the lables that class_a, class_b, etc. in the image_dataset_from_directory's sample ?
If so, in tf2.9, you can use attr element_spec to check, which will be determined by from_tensor_slices and maintained for ever in next procedures.
Additionally, attr class_names can be set arbitrarily since it is not internally maintained by tf.data.dataset.
I have checked the source codes in tf2.4.0 and find it had implemented attr element_spec already. So I think you can use it.
Here is sample code:
import tensorflow as tf
dataset = {
"class_a": [tf.constant(v) for v in range(10)],
"class_b": [tf.constant(v) for v in range(10,20)]
}
a = tf.data.Dataset.from_tensor_slices(dataset)
print(a.element_spec)
# {'class_a': TensorSpec(shape=(), dtype=tf.int32, name=None), 'class_b': TensorSpec(shape=(), dtype=tf.int32, name=None)}
a.class_names = "alielie"
print(a.class_names,a.element_spec)
# alielie {'class_a': TensorSpec(shape=(), dtype=tf.int32, name=None), 'class_b': TensorSpec(shape=(), dtype=tf.int32, name=None)}
a = a.map(lambda x:x)
a.class_names = "alielie1"
print(a.class_names,a.element_spec)
# alielie1 {'class_a': TensorSpec(shape=(), dtype=tf.int32, name=None), 'class_b': TensorSpec(shape=(), dtype=tf.int32, name=None)}
a = a.batch(5)
a.class_names = "alielie2"
print(a.class_names,a.element_spec)
# alielie2 {'class_a': TensorSpec(shape=(), dtype=tf.int32, name=None), 'class_b': TensorSpec(shape=(), dtype=tf.int32, name=None)}
And the following is my test for image_dataset_from_directory's class_names, where class_names just works when building the dataset, and dynamic modification is not supported originally. More precisely, dynamic modification on class_names is not forbidden but does not work as we expected.
import tensorflow as tf
import pathlib
dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
data_dir = pathlib.Path(data_dir)
batch_size = 1
img_height = 180
img_width = 180
#1 the labele will be [0]
train_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
labels='inferred',
class_names = ['daisy','dandelion', 'sunflowers', 'tulips','roses'],
image_size=(img_height, img_width),
shuffle=False,
seed=None,
batch_size=batch_size)
for item in train_ds.take(5):
print(tf.reduce_mean(item[0]),item[1])
#2 the labele will be [1]
train_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
labels='inferred',
class_names = ['dandelion','daisy','sunflowers', 'tulips','roses'],
image_size=(img_height, img_width),
shuffle=False,
seed=None,
batch_size=batch_size)
for item in train_ds.take(5):
print(tf.reduce_mean(item[0]),item[1])
#3 the labele will still be [0], dynamic modification does not work
train_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
labels='inferred',
class_names = ['daisy','dandelion','sunflowers','tulips','roses'],
image_size=(img_height, img_width),
shuffle=False,
seed=None,
batch_size=batch_size)
train_ds.class_names = ['dandelion','daisy','sunflowers', 'tulips','roses']
for item in train_ds.take(5):
print(tf.reduce_mean(item[0]),item[1])
So, if you just want to show such like class_names in Dataset.from_tensor_slices, element_spec is the supported attr, as long as giving Dataset.from_tensor_slices the data in Typing dict[str,list[tf.Tensor]]. This attr will not be cut off
by calling .batch or .map.
If you want to modify class_names dinamicly, unfortunately,
dynamic modification does not work in image_dataset_from_directory. Meanwhile, Dataset.from_tensor_slices does not support this feature too.