How to convert MapDataset variable into np.array? - python

Environment
Ubuntu 18.04
Python 3.6.8
Tensorflow 1.12.0
The problem
I want to convert the data with MapDataset class into numpy.array to check the contents.
Data detail
I have data as TFRecord. This data contains images (150x150x3) and labels (1 or 0). This TFRecord was created from the following code.
def int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def bytes_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
np.random.seed(42)
rnd_index = np.random.permutation(len(image_paths))
X_train, y_train = image_paths[rnd_index[:-1000]], labels[rnd_index[:-1000]]
X_test, y_test = image_paths[rnd_index[-1000:]], labels[rnd_index[-1000:]]
writer = tf.python_io.TFRecordWriter('training.tfrecord')
for image_path, label in zip(X_train, y_train):
image = cv2.imread(image_path)
image = cv2.resize(image, (150, 150)) / 255.0
img_raw = image.tostring()
ex = tf.train.Example(features=tf.train.Features(feature={
'image': bytes_feature(img_raw),
'label': int64_feature(label)
}))
writer.write(ex.SerializeToString())
writer.close()
Parsing data
I parsed the data by following code.
def parse(example_proto):
features = {
'label' : tf.FixedLenFeature((), tf.int64),
'image' : tf.FixedLenFeature((), tf.string)
}
parsed_features = tf.parse_single_example(example_proto, features)
img_shape = tf.stack([150, 150, 3])
image = tf.decode_raw(parsed_features['image'], tf.float32)
image = tf.reshape(image, img_shape)
label = tf.cast(parsed_features['label'], tf.int32)
return image, label
with tf.Session() as sess:
dataset = tf.data.TFRecordDataset('training.tfrecord')
dataset = dataset.map(parse)
I want to get the image from 'dataset' variable, but I don't know how to do.
I tried running the following code on the jupyter notebook.
with tf.Session() as sess:
dataset = tf.data.TFRecordDataset('training.tfrecord')
dataset = dataset.map(parse)
iterator = dataset.make_initializable_iterator()
sess.run(iterator.initializer)
next_element = iterator.get_next()
elem = next_element[0].eval()
dataset
But I got the error message.
InvalidArgumentError: Feature: image (data type: string) is required but could not be found.
[[{{node ParseSingleExample/ParseSingleExample}} = ParseSingleExample[Tdense=[DT_STRING, DT_INT64], dense_keys=["image", "label"], dense_shapes=[[], []], num_sparse=0, sparse_keys=[], sparse_types=[]](arg0, ParseSingleExample/Const, ParseSingleExample/Const_1)]]
[[node IteratorGetNext (defined at <ipython-input-3-350cc5050691>:19) = IteratorGetNext[output_shapes=[[150,150,3], []], output_types=[DT_FLOAT, DT_INT32], _device="/job:localhost/replica:0/task:0/device:CPU:0"](IteratorV2)]]
I'm a beginner of Tensorflow, so I cannot understand what this message means, and how to deal with it.

Related

TFRecords InvalidArgumentError: Key: x_img_shape. Can't parse serialized Example

I'd like to make TFRecords into TFRecordsDataset. And unpack the data while feeding it. This is my function for parsing.
def read_tfrecord(tfrecord, epochs, batch_size):
dataset = tf.data.TFRecordDataset(tfrecord)
def parse(record):
features = {
"x_img": tf.io.FixedLenFeature([], tf.string),
"x_img_shape": tf.io.FixedLenFeature([], tf.int64),
"x_spectrogram": tf.io.FixedLenFeature([], tf.string),
"x_spec_shape": tf.io.FixedLenFeature([], tf.int64),
"x_wave": tf.io.FixedLenFeature([], tf.string),
"x_wave_shape": tf.io.FixedLenFeature([], tf.int64),
"y":tf.io.FixedLenFeature([], tf.string),
"y_shape": tf.io.FixedLenFeature([], tf.int64)}
example = tf.io.parse_single_example(record, features)
x_image = tf.io.decode_image(example["x_img"])
x_spec = tf.io.decode_image(example["x_spectrogram"])
x_wave = tf.cast(example["x_wave"], tf.string)
y = tf.io.decode_image(example["y"])
return x_image, x_spec, x_wave, y
dataset = dataset.map(parse)
dataset = dataset.shuffle(buffer_size=5)
dataset = dataset.prefetch(buffer_size=batch_size) #
dataset = dataset.batch(batch_size, drop_remainder=True)
dataset = dataset.repeat(epochs)
return dataset
I made an iterator to do the task:
train_files = path + "train.tfrecords"
EPOCHS = 100
BATCH_SIZE = 5
train_dataset = read_tfrecord(tfrecord=train_files,
epochs=EPOCHS,
batch_size=BATCH_SIZE)
iterator = iter(train_dataset)
x_img, x_spec, x_wave, y = next(iterator)
But I got this error:
InvalidArgumentError: Key: x_img_shape. Can't parse serialized Example.
[[{{node ParseSingleExample/ParseExample/ParseExampleV2}}]]
The code that serializes the data:
with tf.io.TFRecordWriter(tfrcpath) as file_writer:
for video in sorted(video_list):
print(video)
x_img = frame_extraction(raw_loc, video, interval)
x_spec, x_wave = audio_extraction(raw_loc, video, interval)
y = ground_truth_extraction(raw_loc, video, ground_truth, interval)
record_bytes = tf.train.Example(
features= tf.train.Features(
feature={
"x_img": tf.train.Feature(float_list=tf.train.FloatList(value= x_img.flatten())),
"x_img_shape": tf.train.Feature(int64_list=tf.train.Int64List(value= x_img.shape)),
"x_spec": tf.train.Feature(float_list=tf.train.FloatList(value= x_spec.flatten())),
"x_spec_shape": tf.train.Feature(int64_list=tf.train.Int64List(value= x_spec.shape)),
"x_wave": tf.train.Feature(float_list=tf.train.FloatList(value= x_wave.flatten())),
"x_wave_shape": tf.train.Feature(int64_list=tf.train.Int64List(value= x_wave.shape)),
"y": tf.train.Feature(float_list=tf.train.FloatList(value= y.flatten())),
"y_shape": tf.train.Feature(float_list=tf.train.FloatList(value= y.shape)),
})).SerializeToString()
file_writer.write(record_bytes)
What I have tried:
Solution in link suggests adding the shape of the data. So I tried update it as "x_img_shape": tf.io.FixedLenFeature([3], tf.int64), but didn't solve my issue.
My questions are:
What is the error meaning?
Why is the error only shows at x_img_shape but not x_img? x_img_shape is only used to record the shape of the images
Since I did flatten the images when writing theam as TFRecords, do I need to reshape the training images back? If so, how do I do that?

Loading TF Records into Keras

I am trying to load a custom TFRecord file into my keras model. I attempted to follow this tutorial: https://medium.com/#moritzkrger/speeding-up-keras-with-tfrecord-datasets-5464f9836c36, but adapting for my use.
My goal is to have the functions work similar to ImageDataGenerator from Keras. I cannot use that function because I specific metadata from the images that the generator does not grab. I'm not including that metadata here because I just need the basic network to function first.
I also want to be able to apply this to a transfer learning application.
I keep getting this error: TypeError: Could not build a TypeSpec for None with type NoneType
I am using Tensorflow 2.2
def _parse_function(serialized):
features = \
{
'image': tf.io.FixedLenFeature([], tf.string),
'label': tf.io.FixedLenFeature([], tf.int64),
'shapex': tf.io.FixedLenFeature([], tf.int64),
'shapey': tf.io.FixedLenFeature([], tf.int64),
}
parsed_example = tf.io.parse_single_example(serialized=serialized,
features=features)
shapex = tf.cast(parsed_example['shapex'], tf.int32)
shapey = tf.cast(parsed_example['shapey'], tf.int32)
image_shape = tf.stack([shapex, shapey, 3])
image_raw = parsed_example['image']
# Decode the raw bytes so it becomes a tensor with type.
image = tf.io.decode_raw(image_raw, tf.uint8)
image = tf.reshape(image, image_shape)
# Get labels
label = tf.cast(parsed_example['label'], tf.float32)
return image, label
def imgs_inputs(type, perform_shuffle=False):
records_dir = '/path/to/tfrecord/'
record_paths = [os.path.join(records_dir,record_name) for record_name in os.listdir(records_dir)]
full_dataset = tf.data.TFRecordDataset(filenames=record_paths)
full_dataset = full_dataset.map(_parse_function, num_parallel_calls=16)
dataset_length = (len(list(full_dataset))) #Gets length of datase
iterator = tf.compat.v1.data.make_one_shot_iterator(databatch)
image, label = iterator.get_next()
#labels saved as values ex: [1,2,3], and are now converted to one hot encoded
label = to_categorical(label)
return image, label
image, label = imgs_inputs(type ='Train',perform_shuffle=True)
#Combine it with keras
# base_model = MobileNet(weights='imagenet', include_top=False, input_shape=(200,200,3), dropout=.3)
model_input = Input(shape=[200,200,3])
#Build your network
model_output = Flatten(input_shape=(200, 200, 3))(model_input)
model_output = Dense(19, activation='relu')(model_output)
#Create your model
train_model = Model(inputs=model_input, outputs=model_output)
#Compile your model
optimizer = Adam(learning_rate=.001)
train_model.compile(optimizer=optimizer,loss='mean_squared_error',metrics=['accuracy'],target_tensors=[label])
#Train the model
train_model.fit(epochs=10,steps_per_epoch=2)
image returns array of shape (100,200,200,3) which is a batch of 100 images
label returns array of shape(100,19) which is a batch of 100 labels (there are 19 labels)
The issue related to shapex and shapey but I don't know exactly why.
I set shapex = 200 and shapey=200. Then I rewrote the model to include the transfer learning.
base_model = MobileNet(weights='imagenet', include_top=False, input_shape=(200,200,3), dropout=.3)
x = base_model.output
types = Dense(19,activation='softmax')(x)
model = Model(inputs=base_model.input,outputs=types)
model.compile(
optimizer='adam',
loss = 'sparse_categorical_crossentropy',
metrics=['accuracy']
history = model.fit(get_batches(), steps_per_epoch=1000, epochs=10)
I found everything I needed on this Google Colab:
[https://colab.research.google.com/github/GoogleCloudPlatform/training-data-analyst/blob/master/courses/fast-and-lean-data-science/04_Keras_Flowers_transfer_learning_solution.ipynb#scrollTo=XLJNVGwHUDy1][1]
[1]: https://colab.research.google.com/github/GoogleCloudPlatform/training-data-analyst/blob/master/courses/fast-and-lean-data-science/04_Keras_Flowers_transfer_learning_solution.ipynb#scrollTo=XLJNVGwHUDy1

Read and preprocess image for tensorflow pretrained model

I don't have much experience in Tensorflow. I am trying to use a pretrained ResNet152 model to get the activations of the last layer as output. The images I use for input are stored on my harddrive. So I need to load the images, preprocess them and then get the output from the pretrained model. I found examples for that using URLs of images but when I try it with image paths I can't get it to work. This is what I have so far (only one image for now):
with tf.Graph().as_default():
filename_queue = tf.train.string_input_producer(['./testimg/A_008.jpg'])
reader = tf.WholeFileReader()
key, value = reader.read(filename_queue)
image = tf.image.decode_jpeg(value, channels=3)
preprocessing = preprocessing_factory.get_preprocessing('resnet_v2_152', is_training=False)
processed_image = preprocessing(image, 299,299)
processed_images = tf.expand_dims(processed_image, 0)
with slim.arg_scope(resnet_v2.resnet_arg_scope()):
logits, end_points = resnet_v2.resnet_v2_152(processed_images, is_training=False)
checkpoints_dir='./models/resnet_v2_152'
init_fn = slim.assign_from_checkpoint_fn(
os.path.join(checkpoints_dir, 'resnet_v2_152.ckpt'),
slim.get_variables_to_restore())
with tf.Session() as sess:
init_fn(sess)
np_image, fv = sess.run([image, logits])
I am doing this in a Jupyter Notebook. When I execute the code I don't get an error message, it just keeps running and running until I restart the kernel.
Any ideas what I did wrong? And how would I do it for multiple images?
I found the solution by replacing the tf.WholeFileReader() with tf.read_file():
graph = tf.Graph()
with graph.as_default():
image_path = image = tf.placeholder(tf.string)
image = tf.image.decode_jpeg(tf.read_file(image_path), channels=3)
preprocessing = preprocessing_factory.get_preprocessing('resnet_v2_152', is_training=False)
processed_image = preprocessing(image, image_size, image_size)
processed_images = tf.expand_dims(processed_image, 0)
with slim.arg_scope(resnet_v2.resnet_arg_scope()):
logits, end_points = resnet_v2.resnet_v2_152(processed_images, is_training=False)
checkpoints_dir='./models/resnet_v2_152'
init_fn = slim.assign_from_checkpoint_fn(
os.path.join(checkpoints_dir, 'resnet_v2_152.ckpt'),
slim.get_variables_to_restore())
images = ['./testimg/A_008.jpg', './testimg/logo.jpg']
with tf.Session(graph=graph) as sess:
init_fn(sess)
for img in images:
fv = sess.run(logits, feed_dict={image_path: img})
print(fv)

Inspect the .tfrecords file

I created the images.tfrecoreds file using following code
from PIL import Image
import numpy as np
import tensorflow as tf
import glob
images = glob.glob('E:\Projects/FYPT/vehicle/bus/*.jpg')
def _bytes_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def _int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
tfrecords_filename = 'E:\Projects/FYPT/vehicle/images.tfrecords'
writer = tf.python_io.TFRecordWriter(tfrecords_filename)
original_images = []
for img_path in images:
img = np.array(Image.open(img_path))
height = img.shape[0]
width = img.shape[1]
# Put in the original images into array
# Just for future check for correctness
original_images.append((img))
img_raw = img.tostring()
example = tf.train.Example(features=tf.train.Features(feature={
'height': _int64_feature(height),
'width': _int64_feature(width),
'image_raw': _bytes_feature(img_raw)
}))
writer.write(example.SerializeToString())
writer.close()
Then I tried to Inspect the output of the tf.TFRecordReader() by printing the output of the "serialized_example"
import tensorflow as tf
import skimage.io as io
reader = tf.TFRecordReader()
tfrecords_filename = 'E:\Projects/FYPT/vehicle/images.tfrecords'
filename_queue = tf.train.string_input_producer([tfrecords_filename],num_epochs=10)
_,serialized_example = reader.read(filename_queue)
sess= tf.Session()
print(sess.run(serialized_example))
but it gives me following warning and not give any output of the "serialized_example" this is the screen shot of the command line
What is the mistake have I done and how should I print the output of the "serialized_example"
You get that warning, because you are using tf.train.string_input_producer() which returns a queue, but input pipelines based on QueueRunner API are deprecated and not supported in future versions.
Queue-based solution - not recommended!
serialized_example is just a string object (the same that was written with the tf.python_io.TFRecordWriter to images.tfrecords file for each example).
You need to parse each single example to get its features. In your case:
features = tf.parse_single_example(serialized_example,
features={"image_raw": tf.FixedLenFeature([], tf.string),
"height": tf.FixedLenFeature([], tf.int64) }
img_raw = tf.image.decode_jpeg(features["image_raw"])
img_height = features["height"]
# initialize global and local variables
init_op = tf.group(tf.local_variables_initializer(),
tf.global_variables_initializer())
with tf.Session() as sess:
sess.run(init_op)
# start a number of threads
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
try:
while not coord.should_stop():
img_raw_value, img_height_value = sess.run([img_raw, img_height])
print(img_raw_value.shape)
print(img_height_value)
except tf.errors.OutOfRangeError:
print("End of data")
finally:
coord.request_stop()
# wait for all threads to terminate
coord.join(threads)
sess.close()
Dataset API - highly recommended!
A detailed description how to build a input pipeline can be found here: TensorFlow API.
In your case you should define a _parse_function like this:
def _parse_function(example_proto):
features={"imgage_raw": tf.FixedLenFeature([], tf.string),
"height": tf.FixedLenFeature([], tf.int64),
"width": tf.FixedLenFeature([], tf.int64)}
parsed_features = tf.parse_single_example(example_proto, features)
img_raw = tf.image.decode_jpeg(parsed_features["img_raw"])
height = parsed_features["height"]
width = parsed_features["width"]
return img_raw, height, width
Than create a dataset that reads all of the examples from TFRecord file, and extract the features:
dataset = tf.data.TFRecordDataset([tfrecords_filename])
dataset = dataset.map(_parse_function)
# here you could batch and shuffle
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
while True:
try:
val = sess.run(next_element)
print("img_raw:", val[0].shape)
print("height:", val[1])
print("width:", val[2])
except tf.errors.OutOfRangeError:
print("End of dataset")
break
I hope this helps.

How to read images and text in FSNS datasets?

I just want to read image and text in your tfrecords file: fsns/train/train-00511-of-00512Hi in FSNS datasets.
But when I do the work follow the guide in Tfrecords Guideļ¼š link, it shows error message following:
InvalidArgumentError (see above for traceback): Name: <unknown>, Feature: encoded (data type: string) is required but could not be found.
[[Node: ParseSingleExample/ParseExample/ParseExample = ParseExample[Ndense=4, Nsparse=0, Tdense=[DT_STRING, DT_INT64, DT_STRING, DT_INT64], dense_shapes=[[], [], [], []], sparse_types=[], _device="/job:localhost/replica:0/task:0/cpu:0"](ParseSingleExample/ExpandDims, ParseSingleExample/ParseExample/ParseExample/names, ParseSingleExample/ParseExample/ParseExample/dense_keys_0, ParseSingleExample/ParseExample/ParseExample/dense_keys_1, ParseSingleExample/ParseExample/ParseExample/dense_keys_2, ParseSingleExample/ParseExample/ParseExample/dense_keys_3, ParseSingleExample/ParseExample/Const, ParseSingleExample/ParseExample/Const_1, ParseSingleExample/ParseExample/Const_2, ParseSingleExample/ParseExample/Const_3)]]
It seems that the key name is wrong? My code is attached, could author or any other check my code and help me to fix the bug?
import tensorflow as tf
import skimage.io as io
IMAGE_HEIGHT = 384
IMAGE_WIDTH = 384
tfrecords_filename = '/home/wangjianbo_i/google_model/MyCode/models/attention_ocr/python/datasets/data/fsns/train/train-00511-of-00512'
def read_and_decode(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),
'encoded': tf.FixedLenFeature([], tf.string),
'text':tf.FixedLenFeature([], tf.string)
})
image = tf.decode_raw(features['encoded'], tf.uint8)
text = tf.decode_raw(features['text'], tf.uint8)
height = tf.cast(features['height'], tf.int32)
width = tf.cast(features['width'], tf.int32)
image_shape = tf.stack([height, width, 3])
image = tf.reshape(image, image_shape)
image_size_const = tf.constant((IMAGE_HEIGHT, IMAGE_WIDTH, 3), dtype=tf.int32)
resized_image = tf.image.resize_image_with_crop_or_pad(image=image,
target_height=IMAGE_HEIGHT,
target_width=IMAGE_WIDTH)
images = tf.train.shuffle_batch( [resized_image],
batch_size=2,
capacity=30,
num_threads=2,
min_after_dequeue=10)
return images,text
filename_queue = tf.train.string_input_producer(
[tfrecords_filename], num_epochs=10)
image,text = read_and_decode(filename_queue)
init_op = tf.group(tf.global_variables_initializer(),
tf.local_variables_initializer())
with tf.Session() as sess:
sess.run(init_op)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
# Let's read off 3 batches just for example
for i in xrange(3):
img,text= sess.run([image,text])
print img,text
print(img[0, :, :, :].shape)
print('current batch')
io.imshow(img[0, :, :, :])
io.show()
io.imshow(img[1, :, :, :])
io.show()
coord.request_stop()
coord.join(threads)
To read the FSNS dataset you can use https://github.com/tensorflow/models/blob/master/attention_ocr/python/datasets/fsns.py directly or as a reference.
The feature keys are incorrect in the code snippet you provided - missing the 'image/' prefix. It should be 'image/encoded' instead of just 'encoded', 'image/width' instead of 'image' and so on. Refer to the Table 4 in the paper.

Categories