Как объединить последовательные модели keras с одним и тем же входом?

Пытаюсь создавать свои первые ансамблевые модели из кераса. У меня есть 3 входных значения и одно выходное значение в моем наборе данных.

from keras.optimizers import SGD,Adam
from keras.layers import Dense,Merge
from keras.models import Sequential

model1 = Sequential()
model1.add(Dense(3, input_dim=3, activation='relu'))
model1.add(Dense(2, activation='relu'))
model1.add(Dense(2, activation='tanh'))
model1.compile(loss='mse', optimizer='Adam', metrics=['accuracy'])

model2 = Sequential()
model2.add(Dense(3, input_dim=3, activation='linear'))
model2.add(Dense(4, activation='tanh'))
model2.add(Dense(3, activation='tanh'))
model2.compile(loss='mse', optimizer='SGD', metrics=['accuracy'])

model3 = Sequential()
model3.add(Merge([model1, model2], mode = 'concat'))
model3.add(Dense(1, activation='sigmoid'))
model3.compile(loss='binary_crossentropy', optimizer='Adam', metrics=['accuracy'])

model3.input_shape

Модель ансамбля (model3) компилируется без каких-либо ошибок, но при подборе модели я должен передать один и тот же ввод два раза model3.fit([X,X],y). Я считаю, что это ненужный шаг, и вместо того, чтобы дважды передавать входные данные, я хочу иметь общие входные узлы для моей модели ансамбля. Как я могу это сделать?


person Eka    schedule 29.08.2017    source источник


Ответы (3)


функциональный API Keras, по-видимому, лучше подходит для вашего варианта использования, поскольку он обеспечивает большую гибкость в графике вычислений. например.:

from keras.layers import concatenate
from keras.models import Model
from keras.layers import Input, Merge
from keras.layers.core import Dense
from keras.layers.merge import concatenate

# a single input layer
inputs = Input(shape=(3,))

# model 1
x1 = Dense(3, activation='relu')(inputs)
x1 = Dense(2, activation='relu')(x1)
x1 = Dense(2, activation='tanh')(x1)

# model 2 
x2 = Dense(3, activation='linear')(inputs)
x2 = Dense(4, activation='tanh')(x2)
x2 = Dense(3, activation='tanh')(x2)

# merging models
x3 = concatenate([x1, x2])

# output layer
predictions = Dense(1, activation='sigmoid')(x3)

# generate a model from the layers above
model = Model(inputs=inputs, outputs=predictions)
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

# Always a good idea to verify it looks as you expect it to 
# model.summary()

data = [[1,2,3], [1,1,3], [7,8,9], [5,8,10]]
labels = [0,0,1,1]

# The resulting model can be fit with a single input:
model.fit(data, labels, epochs=50)

Примечания:

  • Могут быть небольшие различия в API между версиями Keras (до и после версии 2).
  • В приведенном выше примере указаны разные оптимизатор и функция потерь для каждой модели. Однако, поскольку fit () вызывается только один раз (в модели 3), те же настройки - в модели 3 - будут применяться ко всей модели. Чтобы иметь разные настройки при обучении подмоделей, они должны быть fit () отдельно - см. Комментарий @Daniel.

РЕДАКТИРОВАТЬ: обновленные заметки на основе комментариев

person etov    schedule 29.08.2017
comment
Компиляция (оптимизатор и потеря) модели учитывается только тогда, когда вы используете fit для этой конкретной модели. Если вы используете fit в model3, вступит в силу только компиляция для model3. --- Нет необходимости компилировать model1 и model2, если вы не собираетесь обучать их по отдельности (с model1.fit и model2.fit). Веса и прогнозы не требуют compile. - person Daniel Möller; 01.09.2017

Ответ етова - отличный вариант.

Но предположим, что у вас уже есть model1 и model2, и вы не хотите их менять, вы можете создать третью модель следующим образом:

singleInput = Input((3,))

out1 = model1(singleInput)   
out2 = model2(singleInput)
#....
#outN = modelN(singleInput)

out = Concatenate()([out1,out2]) #[out1,out2,...,outN]
out = Dense(1, activation='sigmoid')(out)

model3 = Model(singleInput,out)

И если у вас уже есть все модели, и вы не хотите их менять, у вас может быть что-то вроде этого (не тестировалось):

singleInput = Input((3,))
output = model3([singleInput,singleInput])
singleModel = Model(singleInput,output)
person Daniel Möller    schedule 31.08.2017
comment
Это действительно хороший вариант, и на практике я думаю, что эти два способа почти эквивалентны, за исключением того, что входной слой является встраиванием. В этом случае использование общего входного слоя по сравнению с использованием другого для каждой модели будет иметь значение (оба действительны - правильный выбор будет зависеть от приложения) - person etov; 01.09.2017
comment
да. Но полученная модель не является последовательной. - person Daniel Möller; 26.09.2018

Определите новый входной слой и напрямую используйте выходы модели (работает в функциональном API):

assert model1.input_shape == model2.input_shape # make sure they got same shape

inp = tf.keras.layers.Input(shape=model1.input_shape[1:])
model = tf.keras.models.Model(inputs=[inp], outputs=[model1(inp), model2(inp)])
person Mendi Barel    schedule 19.01.2020