简体   繁体   中英

Keras: How to use fit_generator with multiple outputs of different type

In a Keras model with the Functional API I need to call fit_generator to train on augmented images data using an ImageDataGenerator.
The problem is my model has two outputs: the mask I'm trying to predict and a binary value.
I obviously only want to augment the input and the mask output and not the binary value.
How can I achieve this?

The example below might be self-explanatory! The 'dummy' model takes 1 input (image) and it outputs 2 values. The model computes the MSE for each output.

x = Convolution2D(8, 5, 5, subsample=(1, 1))(image_input)
x = Activation('relu')(x)
x = Flatten()(x)
x = Dense(50, W_regularizer=l2(0.0001))(x)
x = Activation('relu')(x)

output1 = Dense(1, activation='linear', name='output1')(x)
output2 = Dense(1, activation='linear', name='output2')(x)

model = Model(input=image_input, output=[output1, output2])
model.compile(optimizer='adam', loss={'output1': 'mean_squared_error', 'output2': 'mean_squared_error'})

The function below generates batches to feed the model during training. It takes the training data x and the label y where y=[y1, y2]

def batch_generator(x, y, batch_size, is_train):
    sample_idx = 0
    while True:
       X = np.zeros((batch_size, input_height, input_width, n_channels), dtype='float32')
       y1 = np.zeros((batch_size, mask_height, mask_width), dtype='float32')
       y2 = np.zeros((batch_size, 1), dtype='float32')

       # fill up the batch
       for row in range(batch_sz):
           image = x[sample_idx]
           mask = y[0][sample_idx]
           binary_value = y[1][sample_idx]
           # transform/preprocess image
           image = cv2.resize(image, (input_width, input_height))
           if is_train:
               image, mask = my_data_augmentation_function(image, mask)
           X_batch[row, ;, :, :] = image
           y1_batch[row, :, :] = mask
           y2_batch[row, 0] = binary_value
           sample_idx += 1

       # Normalize inputs
       X_batch = X_batch/255.
       yield(X_batch, {'output1': y1_batch, 'output2': y2_batch} ))

Finally, we call the fit_generator()

model.fit_generator(batch_generator(X_train, y_train, batch_size, is_train=1))

If you have separated both mask and binary value you can try something like this:

generator = ImageDataGenerator(rotation_range=5.,
                                width_shift_range=0.1, 
                                height_shift_range=0.1, 
                                horizontal_flip=True,  
                                vertical_flip=True)

def generate_data_generator(generator, X, Y1, Y2):
    genX = generator.flow(X, seed=7)
    genY1 = generator.flow(Y1, seed=7)
    while True:
            Xi = genX.next()
            Yi1 = genY1.next()
            Yi2 = function(Y2)
            yield Xi, [Yi1, Yi2]

So, you use the same generator for both input and mask with the same seed to define the same operation. You may change the binary value or not depending on your needs (Y2). Then, you call the fit_generator():

model.fit_generator(generate_data_generator(generator, X, Y1, Y2),
                epochs=epochs)

实现这一目标的最佳方法似乎是创建一个新的生成器类,扩展 Keras 提供的生成器类,该类解析数据,仅增强图像并产生所有输出。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM