How to parse a tfds.features.Sequence object ? It is not compatible with tf.io.FixedLenSequenceFeature - tensorflow

Recently I was trying to train a model on the Wider-Face Dataset. I found it is prebuilt into tfds (https://www.tensorflow.org/datasets/catalog/wider_face). However I am having difficulty parsing it. It's feature map is of the following form -
FeaturesDict({
'faces': Sequence({
'bbox': BBoxFeature(shape=(4,), dtype=tf.float32),
'blur': tf.uint8,
'expression': tf.bool,
'illumination': tf.bool,
'invalid': tf.bool,
'occlusion': tf.uint8,
'pose': tf.bool,
}),
'image': Image(shape=(None, None, 3), dtype=tf.uint8),
'image/filename': Text(shape=(), dtype=tf.string),})
So I passed the following nested dictionary to tf.io.parse_single_example
feature_description = {'faces': {
'bbox': tf.io.FixedLenFeature([], dtype=tf.float32),
'blur': tf.io.FixedLenFeature([], dtype=tf.uint8),
'expression': tf.io.FixedLenFeature([], dtype=tf.bool),
'illumination': tf.io.FixedLenFeature([], dtype=tf.bool),
'invalid': tf.io.FixedLenFeature([], dtype=tf.bool),
'occlusion': tf.io.FixedLenFeature([], dtype=tf.uint8),
'pose': tf.io.FixedLenFeature([], dtype=tf.bool),
},
'image': tf.io.FixedLenFeature([], dtype=tf.uint8),
'image/filename': tf.io.FixedLenFeature([], dtype=tf.string),}
But it gives me a value error of ValueError: Unsupported dict. Later I also learnt that Sequence does not support features which are of type tf.io.FixedLenSequenceFeature.
Please let me know how can I parse this type of TFRecords. I didn't find much documentation of how to use the object detection datasets that are build into Tensorflow, so providing some links with examples will also be helpful.
Thanks

Related

How to parse an in-house TFRecords dataset when loading it using ImportExampleGen

Following the official tutorial, this is how I should load a TFRecord dataset:
raw_image_dataset = tf.data.TFRecordDataset('images.tfrecords')
# Create a dictionary describing the features.
image_feature_description = {
'height': tf.io.FixedLenFeature([], tf.int64),
'width': tf.io.FixedLenFeature([], tf.int64),
'depth': tf.io.FixedLenFeature([], tf.int64),
'label': tf.io.FixedLenFeature([], tf.int64),
'image_raw': tf.io.FixedLenFeature([], tf.string),
}
def _parse_image_function(example_proto):
# Parse the input tf.train.Example proto using the dictionary above.
return tf.io.parse_single_example(example_proto, image_feature_description)
parsed_image_dataset = raw_image_dataset.map(_parse_image_function)
parsed_image_dataset
The _parse_image_function is where I get the chance to set the type and shape of my loaded tensors.
But then, when I'm loading the same file using ImportExampleGen, I don't see how I can inject my parse function into the mix!
context = InteractiveContext()
example_gen = tfx.components.ImportExampleGen(input_base=_dataset_folder)
context.run(example_gen, enable_cache=True)
Does anyone know what's going to happen to my parse logic when I'm using the ImportExampleGen class instead of loading my dataset directly using TFRecordDataset class?

Using tfrec files in Keras

I feel like this should be simple but cannot for the life of me work it out.
I have this melanoma dataset(https://www.kaggle.com/datasets/cdeotte/melanoma-512x512/code) (in tfrec format) downloaded to my local machine.
import os
import cv2
import numpy as np
import pandas as pd
import albumentations
import tensorflow as tf
from tensorflow import keras
features = {'image': tf.io.FixedLenFeature([], tf.string),
'image_name': tf.io.FixedLenFeature([], tf.string),
'patient_id': tf.io.FixedLenFeature([], tf.int64),
'sex': tf.io.FixedLenFeature([], tf.int64),
'age_approx': tf.io.FixedLenFeature([], tf.int64),
'anatom_site_general_challenge': tf.io.FixedLenFeature([], tf.int64),
'diagnosis': tf.io.FixedLenFeature([], tf.int64),
'target': tf.io.FixedLenFeature([], tf.int64),
'width': tf.io.FixedLenFeature([], tf.int64),
'height': tf.io.FixedLenFeature([], tf.int64)}
train_filepaths=tf.io.gfile.glob(path+'/train*.tfrec')
train_filepaths
this lists all the files:
['\Users\adban\Dissertation\Moles\512\train00-2182.tfrec',
'\Users\adban\Dissertation\Moles\512\train01-2185.tfrec',
'\Users\adban\Dissertation\Moles\512\train02-2193.tfrec', ...]
But I cannot seem to decode them. (Tried 'tf.io.parse_single_example' and 'tf.data.TFRecordDataset' but either get a parse error or an empty array returned.)
I figured it out.
This will add all images to a list as 3d array.
def _parse_image_function(example_proto):
return tf.io.parse_single_example(example_proto, features)
def preprocess_image(image):
image = tf.io.decode_image(image, channels=3)
return image
path = '/Users/adban/Dissertation/Moles/512'
tfimage_set = []
for filename in os.listdir(path):
#change for
train_image_dataset = tf.data.TFRecordDataset(path+'/'+filename)
train_images = train_image_dataset.map(_parse_image_function)
for image_feature in train_images:
image_raw = preprocess_image(image_feature['image'])
image_raw_np = image_raw.numpy()
tfimage_set.append(image_raw_np)

How can I wrap tf.io.parse_single_example with tf.py_function?

First, I was wondering if I should wrap tf.io.parse_single_example with tf.py_function when reading TFRecord data from dataset.map,
N = config.get_num_listings_per_search()
features={
'qf': tf.io.FixedLenFeature([len(config.get_query_continuous_features())], tf.float32),
'qi': tf.io.FixedLenFeature([len(config.get_query_categorical_features())], tf.int64),
}
def _parse_function(example_proto):
parsed_features = tf.io.parse_single_example(example_proto, features)
return parsed_features['qf'], parsed_features['qi']
dataset = tf.data.TFRecordDataset(training_files)
dataset = dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
dataset = dataset.shuffle(buffer_size=1000000)
dataset = dataset.map(_parse_function, num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset = dataset.batch(config.get_batch_size())
becauseThe tf.data guide mentioned that
For performance reasons, we encourage you to use TensorFlow operations for preprocessing your data whenever possible. However, it is sometimes useful to call external Python libraries when parsing your input data. You can use the tf.py_function() operation in a Dataset.map() transformation.
I tried to wrap with
parsed_features = tf.py_function(tf.io.parse_single_example, (example_proto, features),
(tf.float32, tf.int64))
However, running the code gave me the following error:
TypeError: Tensors in list passed to 'input' of 'EagerPyFunc' Op have types [string, <NOT CONVERTIBLE TO TENSOR>] that are invalid.
It seems to me tf.py_function(tf.io.parse_single_example(example_proto, features)) is not supported because example_proto is of type tf.string ?
The primary reason I might want to do this is because the current input data pipeline is slow. Will I get some performance improvement if I wrap tf.io.parse_single_example with tf.py_function?
The above code is run in tensorflow-gpu==2.0
Thank you!
tf.py_function is meant to wrap external Python libraries like PIL or scipy, not TensorFlow operations like tf.io.parse_single_example. Adding tf.py_function here will probably make performance worse by forcing TensorFlow to call into Python instead of doing the parsing in C++.
The TFRecord guide gives an example of using tf.io.parse_single_example:
raw_image_dataset = tf.data.TFRecordDataset('images.tfrecords')
# Create a dictionary describing the features.
image_feature_description = {
'height': tf.io.FixedLenFeature([], tf.int64),
'width': tf.io.FixedLenFeature([], tf.int64),
'depth': tf.io.FixedLenFeature([], tf.int64),
'label': tf.io.FixedLenFeature([], tf.int64),
'image_raw': tf.io.FixedLenFeature([], tf.string),
}
def _parse_image_function(example_proto):
# Parse the input tf.Example proto using the dictionary above.
return tf.io.parse_single_example(example_proto, image_feature_description)
parsed_image_dataset = raw_image_dataset.map(_parse_image_function)

Decoding Training Examples

I am using a ddsm dataset to make a CNN, and the owner of the dataset gave some code to decode the training examples, but I can't figure out what first part of the code is actually doing. Still learning.
For reference: https://www.kaggle.com/skooch/ddsm-mammography/home
The code: features = tf.parse_single_example(
serialized_example,
features={
'label': tf.FixedLenFeature([], tf.int64),
'label_normal': tf.FixedLenFeature([], tf.int64),
'image': tf.FixedLenFeature([], tf.string)
})

TensorFlow - Decoding images in a given shape from TF records

I am trying to read images from TFrecords file. The images vary in shapes. After reading, I want to preserve their shape which is why I pass the height, width and depth parameters appropriately. But the code just doesn't print anything after the set_shape command. I initialized the session in the main function. Is there a way to get the values of height,w,d tensors so that I can pass it to set_shape? How do I fix this? Any suggestions are welcome. Thanks in advance.
def read_and_decode(sess,filename_queue):
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(
serialized_example,
# Defaults are not specified since both keys are required.
features={
'height': tf.FixedLenFeature([], tf.int64),
'width': tf.FixedLenFeature([], tf.int64),
'depth': tf.FixedLenFeature([], tf.int64),
'image_raw': tf.FixedLenFeature([], tf.string),
'label': tf.FixedLenFeature([], tf.int64),
})
# Convert from a scalar string tensor (whose single string has
# length mnist.IMAGE_PIXELS) to a uint8 tensor with shape
# [mnist.IMAGE_PIXELS].
image = tf.decode_raw(features['image_raw'], tf.uint8)
image.set_shape([sess.run(features['height']),sess.run(features['width']),sess.run(features['depth'])])
Here's my main function:
def main(argv=None):
with tf.Graph().as_default():
sess=tf.Session()
pdb.set_trace()
load_inputs(sess,FLAGS.batch_size)
and load_input() function which calls the read_and_decode().
def load_inputs(sess,batch_size):
filenames='/home/dp1248/ICR_TF/original_iam_test_words.tfrecords'
# Create a queue that produces the filenames to read.
filename_queue = tf.train.string_input_producer([filenames],num_epochs=1)
# Even when reading in multiple threads, share the filename
# queue.
image, label = read_and_decode(sess,filename_queue)