Tensorflow: train multiple models in parallel with the same ImageDataGenerator

Viewed 609

I'm doing HPO on a small custom CNN. During training the GPU is under-utilised and I'm finding a bottleneck in the CPU: the data augmentation process is too slow. Looking online, I found that I could use multiple CPU cores for the generator and speedup the process. I set up workers=n_cores and this did improve things, but not as much as I'd like.

So I though that I could train multiple models simultaneously on the GPU, and feed the same augmented data to the models. However, I can't come up with some idea on how to do this and I couldn't find any similar question.

Here's a minimal example (I'm leaving out imports for brevity):

# load model and set only last layer as trainable
def create_model(learning_rate, alpha, dropout):
  model_path = '/content/drive/My Drive/Progetto Advanced Machine Learning/Model Checkpoints/Custom Model 1 2020-06-01 10:56:21.010759.hdf5'
  model = tf.keras.models.load_model(model_path)
  x = model.layers[-2].output
  x = Dropout(dropout)(x)
  predictions = Dense(120, activation='softmax', name='prediction', kernel_regularizer=tf.keras.regularizers.l2(alpha))(x)
  model = Model(inputs=model.inputs, outputs=predictions)
  for layer in model.layers[:-2]:
    layer.trainable = False
  model.compile(loss='categorical_crossentropy', optimizer=Adam(learning_rate), metrics=['accuracy']) 
  return model

#declare the search space
SEARCH_SPACE = [skopt.space.Real(0.0001, 0.1, name='learning_rate', prior='log-uniform'),
                skopt.space.Real(1e-9, 1, name='alpha', prior='log-uniform'),
                skopt.space.Real(0.0001, 0.95, name='dropout', prior='log-uniform')]

# declare generator
train_datagenerator = ImageDataGenerator(rescale=1. / 255, rotation_range=30, zoom_range=0.2, horizontal_flip=True, validation_split=0.2, data_format='channels_last')

# training function to be called by the optimiser
@use_named_args(SEARCH_SPACE)
def fitness(learning_rate, alpha, dropout):
  model = create_model(learning_rate, alpha, dropout)
  #compile generators
  train_batches = train_datagenerator.flow_from_directory(train_out_path, target_size=image_size, color_mode="rgb", class_mode="categorical" ,  batch_size=32, subset='training', seed = 20052020)
  val_batches = train_datagenerator.flow_from_directory(directory=train_out_path, target_size=image_size, color_mode="rgb", class_mode="categorical" ,  batch_size=32, subset='validation', shuffle=False, seed = 20052020)
  #train
  early_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)
  training_results = model.fit(train_batches, epochs=5, verbose=1, shuffle=True, validation_data=val_batches, workers=2)
  history[hyperpars] = training_results.history
  with open(dict_save_path, 'wb') as f:
    pickle.dump(history, f)
  return training_results.history['val_accuracy'][-1]

# HPO
result = skopt.forest_minimize(fitness, SEARCH_SPACE, n_calls=10, callback=checkpoint_saver)
0 Answers
Related