如何合并具有相同输入的keras顺序模型?
How to merge keras sequential models with same input?
我正在尝试在 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)
。我认为这是一个不必要的步骤,而不是两次传递输入,我想为我的集成模型提供一个公共输入节点。我该怎么做?
Keras functional API 似乎更适合您的用例,因为它在计算图中提供了更大的灵活性。例如:
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)
备注:
- Keras 版本(pre- 和 post- 版本 2)之间的 API 可能略有不同
- 上面的例子为每个模型指定了不同的优化器和损失函数。然而,由于 fit() 仅被调用一次(在 model3 上),相同的设置 - model3 的设置 - 将应用于整个模型。为了在训练子模型时有不同的设置,它们必须分别 fit() -
请参阅@Daniel 的评论。
编辑:根据评论更新注释
etov 的回答是一个不错的选择。
但是假设您已经准备好 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)
定义新的输入层并直接使用模型输出(适用于函数 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)])
我正在尝试在 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)
。我认为这是一个不必要的步骤,而不是两次传递输入,我想为我的集成模型提供一个公共输入节点。我该怎么做?
Keras functional API 似乎更适合您的用例,因为它在计算图中提供了更大的灵活性。例如:
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)
备注:
- Keras 版本(pre- 和 post- 版本 2)之间的 API 可能略有不同
- 上面的例子为每个模型指定了不同的优化器和损失函数。然而,由于 fit() 仅被调用一次(在 model3 上),相同的设置 - model3 的设置 - 将应用于整个模型。为了在训练子模型时有不同的设置,它们必须分别 fit() - 请参阅@Daniel 的评论。
编辑:根据评论更新注释
etov 的回答是一个不错的选择。
但是假设您已经准备好 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)
定义新的输入层并直接使用模型输出(适用于函数 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)])