Другой обходной путь:
- Создайте массив кортежей и передайте его методу потока ImageDataGenerator.
- Создайте метод итератора, который принимает итератор, созданный на предыдущем шаге , Этот итератор преобразует обратно массив кортежей в список массивов.
Вот методы для реализации описанных выше шагов:
def make_array_of_tuple(tuple_of_arrays):
array_0 = tuple_of_arrays[0]
array_of_tuple = np.empty(array_0.shape[0], dtype=np.object)
for i, tuple_of_array_elements in enumerate(zip(*tuple_of_arrays)):
array_of_tuple[i] = tuple_of_array_elements
return array_of_tuple
def convert_to_list_of_arrays(array_of_tuple):
array_length = array_of_tuple.shape[0]
tuple_length = len(array_of_tuple[0])
array_list = [
np.empty(array_length, dtype=np.uint8) for i in range(tuple_length) ]
for i, array_element_tuple in enumerate(array_of_tuple):
for array, tuple_element in zip(array_list, array_element_tuple):
array[i] = tuple_element
return array_list
def tuple_of_arrays_flow(original_flow):
while True:
(X, array_of_tuple) = next(original_flow)
list_of_arrays = convert_to_list_of_arrays(array_of_tuple)
yield X, list_of_arrays
Чтобы вызвать метод ImageDataGenerator flow () и получить поток, используемый для модели:
y_train = make_array_of_tuple((y_train_1, y_train_2, y_train_3))
orig_image_flow = train_image_generator.flow(X_train, y=y_train)
train_image_flow = tuple_of_arrays_flow(orig_image_flow)
Размер y_train такой же, как у X_train, поэтому его следует принять. 'train_image_flow' возвращает список массивов, которые должны быть приняты мульти-выходной моделью Keras.
ДОБАВЛЕНО (2019/01/26)
Еще одна идея, проще чем выше:
- Передать массив индексов, который содержит 0, 1, 2, ..., в ImageDataGenerator.flow ().
- В итераторе выберите элементы в массивах для множественного вывода с использованием возвращенного массива индексов из исходного потока.
Вот реализация:
def make_multi_output_flow(image_gen, X, y_list, batch_size):
y_item_0 = y_list[0]
y_indices = np.arange(y_item_0.shape[0])
orig_flow = image_gen.flow(X, y=y_indices, batch_size=batch_size)
while True:
(X, y_next_i) = next(orig_flow)
y_next = [ y_item[y_next_i] for y_item in y_list ]
yield X, y_next
Это пример вызова метода выше.
y_train = [y_train_1, y_train_2, y_train_3]
multi_output_flow = make_multi_output_flow(
image_data_generator, X_train, y_train, batch_size)