4

I am trying to implement a custom data generator for a model with 3 inputs and a single output that deals with textual data as follows:

# dummy model
input_1 = Input(shape=(None,))
input_2 = Input(shape=(None,))
input_3 = Input(shape=(None,))     
combined = Concatenate(axis=-1)([input_1, input_2, input_3])
...
dense_1 = Dense(10, activation='relu')(combined)
output_1 = Dense(1, activation='sigmoid')(dense_1)

model = Model([input_1, input_2, input_3], output_1)
print(model.summary())

#Compile and fit_generator
model.compile(optimizer='adam', loss='binary_crossentropy')

train_data_gen = Generator([x1_train, x2_train, x3_train], y_train, batch_size)
test_data_gen = Generator([x1_test, x2_test, x3_test], y_test, batch_size)

model.fit_generator(generator=train_data_gen, validation_data = test_data_gen, epochs=epochs, verbose=1)

The data generator code I found here, I wonder how to modify it to accept multiple input tensors.

class Generator(Sequence):
    # Class is a dataset wrapper for better training performance
    def __init__(self, x_set, y_set, batch_size=256):
        self.x, self.y = x_set, y_set
        self.batch_size = batch_size
        self.indices = np.arange(self.x.shape[0])

    def __len__(self):
        return math.floor(self.x.shape[0] / self.batch_size)

    def __getitem__(self, idx):
        inds = self.indices[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_x = self.x[inds]
        batch_y = self.y[inds]
        return batch_x, batch_y

    def on_epoch_end(self):
        np.random.shuffle(self.indices)
giser_yugang
  • 6,058
  • 4
  • 21
  • 44
Daisy
  • 847
  • 3
  • 13
  • 34
  • Possible duplicate of [Keras: How to use fit_generator with multiple inputs](https://stackoverflow.com/questions/49404993/keras-how-to-use-fit-generator-with-multiple-inputs) – user202729 Feb 11 '21 at 06:30

1 Answers1

4

All you need to do is modify Generator class as follows.

class Generator(Sequence):
    # Class is a dataset wrapper for better training performance
    def __init__(self, x_set, y_set, batch_size=256):
        self.x, self.y = x_set, y_set
        self.batch_size = batch_size
        self.indices = np.arange(self.x[0].shape[0])

    def __len__(self):
        return math.floor(self.x[0].shape[0] / self.batch_size)

    def __getitem__(self, idx):
        inds = self.indices[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_x = [self.x[0][inds],self.x[1][inds],self.x[2][inds]]
        batch_y = self.y[inds]
        return batch_x, batch_y

    def on_epoch_end(self):
        np.random.shuffle(self.indices)
giser_yugang
  • 6,058
  • 4
  • 21
  • 44