Контекст
Я использую генератор изображений tensorflow.keras.preprocessing.image ImageDataGenerator.
from tensorflow.keras.preprocessing.image import ImageDataGenerator
Я изо всех сил пытался найти пример пользовательского генератора multi_output, который передает вектор с плавающей запятой (например, 4 вектора, представляющий ограничивающую рамку) в качестве метки для одной из двух сетевых головок и вектор с горячим кодированием (например, 3 класса ) в качестве метки к другой головке.
Первая головка сети выполнит регрессию на ограничивающей рамке из 4 векторов.
а вторая головка сети выполнит классификацию по одному горячему 3-вектору.
У меня есть структура, очень похожая на найденную здесь.
Единственная разница в том, что я не хочу загружать все изображения в память сразу, отсюда мое желание использовать генератор.
Я думаю, что мой код близок, но множество примеров, которые я нашел, не совсем то, что мне нужно.
Это то, что у меня было сначала (см. Дополнительные сведения ниже о том, что у меня есть сейчас):
def generate_image_generator(generator, data_directory, data_items, target_size, classes, batch_size, shuffle, class_mode):
frames=[]
for di in data_items:
df = pd.read_csv(data_directory+di["file"])
#df["cls"] = df["cls"].apply(lambda x: x.split(","))
frames.append(df)
df = pd.concat(frames)
a = pd.get_dummies(df['cls'], prefix='cls')
df = pd.concat([df, pd.get_dummies(df['cls'], prefix='cls')], axis=1)
df.head()
# y_col=(['sxu', 'syu', 'exu', 'eyu'], 'cls'),
genImages = generator.flow_from_dataframe(dataframe=df, directory=data_directory, target_size=target_size,
x_col="file",
y_col=[('sxu', 'syu', 'exu', 'eyu'), ('cls_airplane', 'cls_face', 'cls_motorcycle')],
class_mode="multi_output",
classes=classes, batch_size=batch_size, shuffle=shuffle, seed=2)
Обратите особое внимание на следующие две строки:
y_col=[('sxu', 'syu', 'exu', 'eyu'), ('cls_airplane', 'cls_face', 'cls_motorcycle')],
class_mode="multi_output",
В первой строке должен быть указан список с двумя элементами метки (по одному для каждой из двух головок в моей модели, головка 4-векторной регрессии и головка классификации 3 векторов)
Образец из CSV-файла, загруженного в кадр данных pandas, показан ниже.
id,file,sx,sy,ex,ey,cls,sxu,syu,exu,eyu,w,h
0,motorcycle.0001.jpg,31,19,233,141,motorcycle,0.1183206106870229,0.11801242236024845,0.8893129770992366,0.8757763975155279,262,161
1,motorcycle.0002.jpg,32,15,232,142,motorcycle,0.12167300380228137,0.09259259259259259,0.8821292775665399,0.8765432098765432,263,162
Обратите внимание, что в приведенном выше коде я добавляю дополнительные горячие столбцы (cls_motorcycle, cls_face, cls_airplane) в кадр данных pandas. Это столбцы, на которые ссылается второй кортеж в моем массиве y_col.
Дополненный кадр данных pandas, который включает в себя мои горячие столбцы
Ошибка
Я использую реализацию keras tensorflow. Ошибка, которую я получаю, является ключевой ошибкой в кадре данных pandas.
Ясно, что keras tensorflow не нравится список кортежей, которые я передаю для меток multi_output. Он считает, что первый кортеж в списке на самом деле является одним ключом в один столбец, а не четырьмя ключами в четыре столбца.
Вопрос
Как настроить flow_from_dataframe с multi_output метка регрессии для одной головы и метка классификации для второй головы?
Дополнительная информация
Теперь я попытался сделать следующее (обратите внимание, что теперь я получаю 2-кортеж для метки - это последнее состояние моих усилий), и я думаю, что продвинулся дальше. Однако я пока не думаю, что это правильно (трассировка стека ниже фрагмент кода):
def generate_image_generator(generator, data_directory, data_items, target_size, classes, batch_size, shuffle, class_mode):
frames=[]
for di in data_items:
df = pd.read_csv(data_directory+di["file"])
frames.append(df)
df = pd.concat(frames)
labels = ['sxu', 'syu', 'exu', 'eyu', 'cls_onehot']
df['cls_onehot'] = df['cls'].str.get_dummies().values.tolist()
genImages = generator.flow_from_dataframe(dataframe=df, directory=data_directory, target_size=target_size,
x_col="file",
y_col=labels,
class_mode="multi_output",
classes=classes, batch_size=batch_size, shuffle=shuffle, seed=2)
while True:
images, labels = genImages.next()
yield images[0], ([labels[0], labels[1], labels[2], labels[3]], labels[4])
Я иду дальше, так что, возможно, мой генератор сейчас в порядке, но теперь я вижу следующую трассировку (когда я начинаю тренировать модель):
Новая трассировка стека во время первой эпохи обучения
В следующем представлении отладки pycharm вы можете видеть изображения и метки в том виде, в каком они существуют в той точке, которую дает генератор. Обратите внимание, мой размер партии составляет 5.