Keras: Bug: ImageDataGenerator for multiple output and single input fails

Created on 8 Apr 2019  路  6Comments  路  Source: keras-team/keras

This bug is also referred here but i think there is no fix currently. As i am getting the same problem:
https://github.com/keras-team/keras/issues/3761

The problem is, I can't able to use ImageDataGenerator for single input and multiple output.

tensorflow support

Most helpful comment

@muneeb699 I solved the issue by writing a custom generator like this:

from tensorflow import keras
import numpy as np

class MultiOutputDataGenerator(keras.preprocessing.image.ImageDataGenerator):

    def flow(self,
             x,
             y=None,
             batch_size=32,
             shuffle=True,
             sample_weight=None,
             seed=None,
             save_to_dir=None,
             save_prefix='',
             save_format='png',
             subset=None):

        targets = None
        target_lengths = {}
        ordered_outputs = []
        for output, target in y.items():
            if targets is None:
                targets = target
            else:
                targets = np.concatenate((targets, target), axis=1)
            target_lengths[output] = target.shape[1]
            ordered_outputs.append(output)


        for flowx, flowy in super().flow(x, targets, batch_size=batch_size,
                                         shuffle=shuffle):
            target_dict = {}
            i = 0
            for output in ordered_outputs:
                target_length = target_lengths[output]
                target_dict[output] = flowy[:, i: i + target_length]
                i += target_length

            yield flowx, target_dict

All 6 comments

I still face the same problem, and official modification not come

I have the same issue, is there at least a workaround?

@Anabad I dont have any solution currently. I ask you the same if you know any solution. PLease post it here.

@muneeb699 I solved the issue by writing a custom generator like this:

from tensorflow import keras
import numpy as np

class MultiOutputDataGenerator(keras.preprocessing.image.ImageDataGenerator):

    def flow(self,
             x,
             y=None,
             batch_size=32,
             shuffle=True,
             sample_weight=None,
             seed=None,
             save_to_dir=None,
             save_prefix='',
             save_format='png',
             subset=None):

        targets = None
        target_lengths = {}
        ordered_outputs = []
        for output, target in y.items():
            if targets is None:
                targets = target
            else:
                targets = np.concatenate((targets, target), axis=1)
            target_lengths[output] = target.shape[1]
            ordered_outputs.append(output)


        for flowx, flowy in super().flow(x, targets, batch_size=batch_size,
                                         shuffle=shuffle):
            target_dict = {}
            i = 0
            for output in ordered_outputs:
                target_length = target_lengths[output]
                target_dict[output] = flowy[:, i: i + target_length]
                i += target_length

            yield flowx, target_dict

@Anabad your solution works. <3

Just to add a note.
If the dummy trainY is:

trainY = { 'gender': train_gender, 'ethnicity': train_ethnicity, 'age': train_age }

Make sure that:

type(trainY['gender']) should be numpy array with shape (total_size_data, 1)
type(trainY['ethnicity']) should be numpy array with shape (total_size_data, N_classes)
type(trainY['age']) should be numpy array with shape (total_size_data, N_classes)

A numpy array with shape (total_size_data, ) should be reshaped to (total_size_data,1)

@muneeb699 I solved the issue by writing a custom generator like this:

from tensorflow import keras
import numpy as np

class MultiOutputDataGenerator(keras.preprocessing.image.ImageDataGenerator):

    def flow(self,
             x,
             y=None,
             batch_size=32,
             shuffle=True,
             sample_weight=None,
             seed=None,
             save_to_dir=None,
             save_prefix='',
             save_format='png',
             subset=None):

        targets = None
        target_lengths = {}
        ordered_outputs = []
        for output, target in y.items():
            if targets is None:
                targets = target
            else:
                targets = np.concatenate((targets, target), axis=1)
            target_lengths[output] = target.shape[1]
            ordered_outputs.append(output)


        for flowx, flowy in super().flow(x, targets, batch_size=batch_size,
                                         shuffle=shuffle):
            target_dict = {}
            i = 0
            for output in ordered_outputs:
                target_length = target_lengths[output]
                target_dict[output] = flowy[:, i: i + target_length]
                i += target_length

            yield flowx, target_dict

Can you plese provide it with a docstring? I am facing the same problem. My 250000 images are presented as the rows and the 32332 columns of the pandas Dataframe are the corresponding pixels of 137*236 of each grayscale image and there are 4 labels assigned to each image. Can You add a scikit-image resize method to resize the output images too?

Was this page helpful?
0 / 5 - 0 ratings