Проблема при попытке объединить входы и выходы двух моделей

Я пытаюсь объединить 2 модели, обученные с разными наборами данных и количеством классов, чтобы получить окончательную модель с уникальным вводом и уникальным выводом.

Окончательный результат должен быть примерно таким:

схема финальной модели

На самом деле мой код такой:

[...]
stuffs with imports, tensorboard and imageDataGenerator
[...]    

model_simple = load_model("model_simple.h5")
model_simple.name = 'model_simple'
for layer in model_simple.layers:
    layer.trainable = False
    layer.name = layer.name + str("_simple")

model_complexe = load_model("model_complexe.h5")
model_complexe.name = 'model_complexe'
for layer in model_complexe.layers:
    layer.trainable = False
    layer.name = layer.name + str("_complexe")


model_simple.layers.pop(0)
model_complexe.layers.pop(0)

input_common = Input(shape=(299, 299, 3), name = "input_common")

model_simple_output = model_simple(input_common)
model_complexe_output = model_complexe(input_common)


x = concatenate([model_simple_output, model_complexe_output])
x = Dense((2 * NB_CLASSES), activation='relu')(x)
x = Dense((2 * NB_CLASSES)*2, activation='relu')(x)
x = Dense((2 * NB_CLASSES)*2, activation='relu')(x)
x = Dense(NB_CLASSES, activation='relu')(x)
output = Dense(NB_CLASSES, activation='sigmoid')(x)


model = Model(inputs=input_common, outputs=output)

model.compile(optimizer=Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-8, amsgrad=True), loss='categorical_crossentropy', metrics=['acc'])



model.fit_generator(
        train_generator,
        steps_per_epoch=NB_FIC_TRAIN // BATCH_SIZE,
        epochs=1,
        validation_data=validation_generator,
        validation_steps=NB_FIC_VAL // BATCH_SIZE,
        callbacks = [tensorboard]
        )

model.save("modele_final.h5")

Когда я запускаю его, он не падает и тренируется, но когда я присматриваюсь, он кажется большим беспорядком (и он выдает ошибки, когда я пытаюсь преобразовать его в .pb, говоря, что модель имеет 0 тензорных входов) .

Конечный файл имеет почти такой же размер, как файл model_simple.h5, и когда я смотрю на файл с помощью netron, разные части (2 модели и плотные слои) не кажутся связанными:

Вход ни к чему не подключен

(слои "простой" модели слева, слои "сложной" модели справа)

И слой конкатенации имеет модели в качестве входных данных вместо выходных данных моделей:

Странные входные данные для слоя конкатенации

И то же самое, если я использую «.output» следующим образом:

[...]

model_simple_output = model_simple(input_common)
model_complexe_output = model_complexe(input_common)

new_model_simple = Model(input_common, model_simple_output)
new_model_complexe = Model(input_common, model_complexe_output)

x = concatenate([new_model_simple.output, new_model_complexe.output])

[...]

Я думаю, что я делаю что-то не так, но я не узнаю, что :/

Вы распечатали свой model.summary()? Просто попробуйте поэкспериментировать с 3 очень простыми моделями и проверьте summary().

Anakin 09.04.2019 13:15

Также, возможно, вам стоит использовать слой Concatenate([first, second]). Не уверен, что это имеет значение. Ваша окончательная модель определенно не подключена прямо сейчас.

Anakin 09.04.2019 13:19

для model.summary() вот результат: i.gyazo.com/38b06fa4c449779d3683f145e6d412b8.png Я пробовал с keras.layers.Concatenate вот так: x = Concatenate()([model_simple_output, model_complexe_output]) но результат тот же :/

Enzo Dutra 09.04.2019 13:52

Являются ли формы именно такими, как вы ожидали?

Anakin 09.04.2019 13:58

Да, мне это кажется правильным, просто входные данные конкатенации должны быть выходными данными двух моделей, но это должно дать это: model_simple_output = model_simple(input_common) нет?

Enzo Dutra 09.04.2019 14:12

Я не понимаю, в чем на самом деле проблема или вопрос, вы говорите, что он тренируется, но затем вы получаете ошибки (какие?), а затем вы используете какой-то инструмент для визуализации, но затем видите бессмысленные результаты (может быть, инструмент сломан?). Резюме вашей модели выглядит правильно, поэтому я вообще не вижу проблемы.

Dr. Snoopy 09.04.2019 14:39

Ах, может быть, я неправильно истолковал проблему, да, когда я пытаюсь преобразовать окончательную модель, она также говорит, что указанный входной файл содержит только веса, но я думал, что это вызвано неправильной структурой, потому что я использую model.save(""), а не model.save_weights(""). Вот полная ошибка: i.gyazo.com/c51c82f839607bc2653c85fec99c3588.jpg

Enzo Dutra 09.04.2019 15:04

@EnzoDutra Итак, как вы показали ошибку, ваш вопрос заключается в том, как преобразовать файл .h5 в файл .pb или какой-то другой вопрос? Потому что model.summary() выглядит нормально. С вашей моделью проблем нет, она идеально сцеплена.

Krunal V 09.04.2019 16:05

Я не знаю, потому что у меня никогда не было проблем с преобразованием файла .h5 в файл .pb, я просто преобразовал другую модель, чтобы быть уверенным, и она работает отлично, но, похоже, есть проблема с моделью, которую я создаю здесь. Может быть, это сохраняет структуру плотных слоев, которые я добавляю, но не структуру двух моделей? У меня также есть странная структура графа на тензорной доске, где все части не кажутся связанными. (вот файл, который я получаю, если вы хотите проверить его desfichesdescartes.fr/projet/modele_total_3.h5)

Enzo Dutra 09.04.2019 16:24

@EnzoDutra, я думаю, у вас есть некоторые пользовательские вещи внутри вашей модели, которые создают проблему, может быть какой-то пользовательский слой. Это правильно или нет?

Krunal V 09.04.2019 16:55

Я так не думаю, я пробовал с 2 официальными моделями Inception V3, которые у меня есть, например, i.gyazo.com/5adf6927c143461fed17a0c5367f078b.png, и проблемы точно такие же. Вот полная версия приведенного выше кода, если вы хотите попробовать pastebin.com/uqChMnVc

Enzo Dutra 09.04.2019 17:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
11
404
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я попытался создать ваш вариант использования с помощью VGG16 и VGG19 следующим образом:

from keras.layers import *
from keras.models import *
from keras.applications.vgg16 import VGG16
from keras.applications.vgg19 import VGG19

model_1 = VGG16(include_top=True, weights='imagenet')
model_2 = VGG19(include_top=True, weights='imagenet')

А потом я использовал часть вашего скрипта, чтобы связать модель.

NB_CLASSES = 73

input_common = Input(shape=(224, 224, 3), name = "input_common")

model_simple_output = model_1(input_common)
model_complexe_output = model_2(input_common)

x = concatenate([model_simple_output, model_complexe_output])
x = Dense((2 * NB_CLASSES), activation='relu')(x)
x = Dense((2 * NB_CLASSES)*2, activation='relu')(x)
x = Dense((2 * NB_CLASSES)*2, activation='relu')(x)
x = Dense(NB_CLASSES, activation='relu')(x)
output = Dense(NB_CLASSES, activation='sigmoid')(x)

model = Model(inputs=input_common, outputs=output)

Чтобы сохранить модель. Это также должно работать, если вы используете только model.save. Но вы также можете попытаться сохранить свою модель как json, используя model.to_json(), что сохранит модель как строку. И это не сохранит ваши веса, и если вы хотите сохранить веса отдельно, используйте model.save_weights.

model.summary()
model.save('model.h5')

model_json = model.to_json()
with open("model.json", "w") as json_file:
    json_file.write(model_json)

Вероятно, я использовал тот же файл для преобразования .h5 файла в .pb, что и вы.

git clone https://github.com/amir-abdi/keras_to_tensorflow.git

python keras_to_tensorflow/keras_to_tensorflow.py --input_model=model.h5 \
                                                  --input_model_json=model.json \
                                                  --output_model=model.pb

keras_to_tensorflow.py также работает без --input_model_json=model.json, потому что model.h5 содержит и модель, и веса. Но для вашего случая я бы предпочел использовать с --input_model_json. Я думаю, это должно сработать для вас.

Странно, кажется, что он работает с VGG16 и VGG19, но не с InceptionV3 и InceptionResNetV2, из-за этого скрипты преобразования зависают, а размер файла .h5 кажется очень маленьким. Похоже, есть проблема, когда скрипт, который строит модель, сохраняет ее. Как вы думаете, это может быть ошибка? Или, может быть, это потому, что VGG - это последовательные графики, а не начальные, и ими нельзя манипулировать одинаково?

Enzo Dutra 12.04.2019 17:21

Также я не знаю почему, но когда я использую код, который вы дали, но с 2 VGG16 вместо VGG16 и VGG19, у меня возникает эта ошибка при использовании скрипта преобразования i.gyazo.com/68970e4bec3b6f52584f15142027f0cb.png

Enzo Dutra 12.04.2019 17:40

Другие вопросы по теме