Tensorflow dataset with variable number of elements

Question:

I need a dataset structured to handle a variable number of input images (a set of images) to regress against an integer target variable.

The code I am using to source the images is like this:

import tensorflow as tf
from tensorflow import convert_to_tensor


def read_image_tf(path: str) -> tf.Tensor:
    image = tf.keras.utils.load_img(path)
    return tf.keras.utils.img_to_array(image)

def read_image_list(x, y):
    return tf.map_fn(read_image_tf, x), y


paths_list = [['image_1', 'image_2', 'image_3'], ['image_6'], ['image_4', 'image_5', 'image_8', 'image_19']]

x = tf.ragged.constant(paths_list)
y = tf.constant([1,2,3])

dataset = tf.data.Dataset.from_tensor_slices((x, y))
dataset = dataset.map(lambda x,y: read_image_list(x,y))

This code breaks with TypeError (TypeError: path should be path-like or io.BytesIO, not <class 'tensorflow.python.framework.ops.Tensor'>), as it seems that the map operation is not extracting the paths correctly from the original RaggedTensor. I have also tried to use a generator with similar results. Any help would be much appreciated

Asked By: Alberto

||

Answers:

Maybe something like this:

import tensorflow as tf

def read_image_tf(path: str) -> tf.Tensor:
    img = tf.io.read_file(path)
    return tf.io.decode_png(img, channels=3) # more generic: tf.io.decode_image

def read_image_list(x, y):
    return tf.map_fn(read_image_tf, x, dtype=tf.uint8), y

paths_list = [['/content/image1.png', '/content/image1.png', '/content/image1.png'], ['/content/image1.png'], ['/content/image1.png', '/content/image1.png', '/content/image1.png', '/content/image1.png']]

x = tf.ragged.constant(paths_list)
y = tf.constant([1,2,3])

dataset = tf.data.Dataset.from_tensor_slices((x, y))
dataset = dataset.map(lambda x, y: read_image_list(x, y))

for x, y in dataset:
  print(x.shape, y)
(3, 100, 100, 3) tf.Tensor(1, shape=(), dtype=int32)
(1, 100, 100, 3) tf.Tensor(2, shape=(), dtype=int32)
(4, 100, 100, 3) tf.Tensor(3, shape=(), dtype=int32)

You can also convert x back to a ragged tensor if you want.

Answered By: AloneTogether