Reputation: 1122
I'm trying to use the tf.data
API for the first time with help from this example, I have 3D volume data, i.e instead of (height, width, channel), I have (depth, height, width, channel).
def readfile(filenames):
name = filenames[0]
string = tf.read_file(name)
image = tf.image.decode_image(string, channels=3)
bunch = image
for name in filenames[1:]:
string = tf.read_file(name)
image = tf.image.decode_image(string, channels=3)
bunch = tf.concat([bunch,image],1)
return bunch
with tf.device("/cpu:0"):
#read data file paths, shape [5,100] (five elements each with 100 frames)
train_dataset = tf.data.Dataset.from_tensor_slices(train_files)
#train_dataset.element_spec gives shape=(100,)
train_dataset = train_dataset.map(readfile, num_parallel_calls=16)
#readfile function takes element of shape (1,100) and
#reads each frame and appends to a tensor which is returned
#train_dataset.element_spec gives shape=<unknown>
train_dataset = train_dataset.map(lambda x: tf.random_crop(x, (100, 256, 256, 3)))
#train_dataset.element_spec gives shape=(100, 256, 256, 3)
train_dataset = train_dataset.batch(1)
x = train_dataset.make_one_shot_iterator().get_next()
Error:
Traceback (most recent call last):
File "/anaconda3/envs/myenv/lib/python3.6/site-packages/tensorflow_core/python/client/session.py", line 1365, in _do_call
return fn(*args)
File "/anaconda3/envs/myenv/lib/python3.6/site-packages/tensorflow_core/python/client/session.py", line 1350, in _run_fn
target_list, run_metadata)
File "/anaconda3/envs/myenv/lib/python3.6/site-packages/tensorflow_core/python/client/session.py", line 1443, in _call_tf_sessionrun
run_metadata)
tensorflow.python.framework.errors_impl.InvalidArgumentError: {{function_node __inference_Dataset_map_<lambda>_258}} Incompatible shapes: [3] vs. [4]
[[{{node random_crop/GreaterEqual}}]]
[[IteratorGetNext]]
I can't understand the error. I think it means the tf.random_crop
is giving a 3D tensor shape while .get_next()
part is giving a 4D tensor? I have doubt with the shape of train_dataset
after readfile
function is applied, why is the shape <unknown>
, I would expect something like (?,100,256,256,3). Where am I going wrong?
Is there a way to visualise the frames in train_dataset so I know I'm doing it right? I have always used feed_dict
and there it's easy to visualise the numpy frames so I know exactly what I'm feeding.
Upvotes: 1
Views: 1895
Reputation: 5743
Based upon the limited information i see both fundamental and technical errors in your code:
I assume you have (equivalent of) 5 directories with 100 frames. You have a tensor train_dataset with 5 rows and 100 columns with each element being a directory and each value in the element being a path
Fundamental:
train_dataset = train_dataset.map(readfile, num_parallel_calls=16)
you are actually sending in tensors of shape (100,) instead of (1,100) that you thought but, your function is written right and is handling (100,) the right waybunch = tf.concat([bunch,image],1)
. This will concatenate your images along dimension 1. If your images are (100,100,3) then you are creating (100,100*100,3) as the output of readfile. So, you are effectively getting (5,100,100*100,3) as the return value of train_dataset.map(readfile, num_parallel_calls=16)
. Maybe you want to use stack here. Also, 'MapDataset' object has no attribute 'elem_spec' so how you are getting unknown as the output of elem_spec of train_dataset beats meTechnical:
train_dataset = train_dataset.map(lambda x: tf.random_crop(x, (100, 256, 256, 3)))
. x
is shaped (5,100,100*100,3) so each element that random_crop is taking is (100,100*100,3) and you cannot crop it to (100,256,256,3). This is how cropping is used effectivelyimage = tf.image.random_crop(image, size=[28, 28, 1]) # Random crop back to 28x28
Here image is a batch of images of shape (34,34,1)
All things considered i think Your issue is generating from using tf.concat
where you wanted to use tf.stack
Upvotes: 1