具有第三个组件错误的连体网络

Siamese network with third component error

我能够创建类似于 siamese 的网络:

https://github.com/aspamers/siamese/

如果我尝试将第三个模型作为输入添加到我的网络头部,就会出现问题。 我将收到以下错误:

ValueError: Shape must be rank 2 but is rank 3 for '{{node head/concatenate/concat}} = ConcatV2[N=3, T=DT_FLOAT, Tidx=DT_INT32](simple/Identity, simple_1/Identity, different/Identity, head/concatenate/concat/axis)' with input shapes: [?,?], [?,?], [?,?,1], [].

这是下面的代码,我不满意的一件事是行 processed_a = base_model1(input_a) 以及它在检查 Keras 模型文档后的作用.我明白,如果我不这样做,我将无法获得所需的形状,也无法为最终网络提供必要的输入。

请注意,如果我将代码替换为注释内容并仅使用纯暹罗网络,它就可以正常工作。 知道需要更改什么以解决上述错误以及 base_model1(input_a) 的作用。

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.python.keras.layers import *

def getModel1(input_shape):
    model_input = Input(shape=input_shape)
    layer = layers.Dense(32, activation='relu')(model_input)
    layer = layers.Flatten()(layer)
    return tf.keras.Model(inputs=model_input, outputs= layer, name="simple")

def getModel3(input_shape):
    model_input = Input(shape=input_shape)
    layer = layers.Dense(1, activation='relu')(model_input)
    return tf.keras.Model(inputs=model_input, outputs=layer, name="different")

def outputModel(models):
    inputs = []
    for model in models:
        inputs.append(Input(shape=model.output_shape))
    layer = layers.Concatenate()(inputs)
    layer = layers.Dense(1)(layer)
    return tf.keras.Model(inputs=inputs, outputs=layer, name="head")

dataset = []
inputs1 = []
for i in range(0, 128):
    dataset.append([0.0, 1.0, 2.0])
train_dataset1 = np.asarray(dataset)
base_model1 = getModel1(train_dataset1.shape)

dataset3 = [0.0, 1.0, 2.0]
train_dataset3 = np.asarray(dataset3)
base_model3 = getModel3(train_dataset3.shape)


input_a = Input(shape=base_model1.input_shape)
input_b = Input(shape=base_model1.input_shape)
input_c = Input(shape=base_model3.input_shape)

oModel = outputModel([base_model1, base_model1, base_model3])
#oModel = outputModel([base_model1, base_model1])

processed_a = base_model1(input_a)
processed_b = base_model1(input_b)
processed_c = base_model3(input_c)

head = oModel([processed_a, processed_b, processed_c])
model = tf.keras.Model(inputs=[input_a, input_b, input_c], outputs=head, name="model")
#head = oModel([processed_a, processed_b])
#model = tf.keras.Model(inputs=[input_a, input_b], outputs=head, name="model")
optimizer = tf.keras.optimizers.RMSprop(0.001)
model.compile(loss='mse',
              optimizer=optimizer,
              metrics=['mae', 'mse'])

model.predict([np.asarray([train_dataset1]), np.asarray([train_dataset1]), np.asarray([train_dataset3])])
#model.predict([np.asarray([train_dataset1]), np.asarray([train_dataset1])])
model.fit([np.asarray([train_dataset1]), np.asarray([train_dataset1]), np.asarray([train_dataset3])], np.asarray([1.0]), epochs=1000, validation_split=0, verbose=0, callbacks=[])
#model.fit([np.asarray([train_dataset1]), np.asarray([train_dataset1])], np.asarray([1.0]), epochs=1000, validation_split=0, verbose=0, callbacks=[])

请注意您在初始化模型输入和输出时定义的维度。第一个维度始终是批量大小 (None),这可能会给您带来一些问题。这里是正确的例子:

def getModel1(input_shape):
    model_input = Input(shape=input_shape)
    layer = Dense(32, activation='relu')(model_input)
    layer = Flatten()(layer)
    return Model(inputs=model_input, outputs= layer, name="simple")

def getModel3(input_shape):
    model_input = Input(shape=input_shape)
    layer = Dense(1, activation='relu')(model_input)
    return Model(inputs=model_input, outputs=layer, name="different")

def outputModel(models):
    inputs = []
    for model in models:
        inputs.append(Input(shape=model.output_shape[1:]))
    layer = Concatenate()(inputs)
    layer = Dense(1)(layer)
    return Model(inputs=inputs, outputs=layer, name="head")

base_model1 = getModel1((128,3))
base_model3 = getModel3((3))

input_a = Input(shape=base_model1.input_shape[1:])
input_b = Input(shape=base_model1.input_shape[1:])
input_c = Input(shape=base_model3.input_shape[1:])

oModel = outputModel([base_model1, base_model1, base_model3])

processed_a = base_model1(input_a)
processed_b = base_model1(input_b)
processed_c = base_model3(input_c)

head = oModel([processed_a, processed_b, processed_c])
model = Model(inputs=[input_a, input_b, input_c], outputs=head, name="model")

optimizer = tf.keras.optimizers.RMSprop(0.001)
model.compile(loss='mse',
              optimizer=optimizer,
              metrics=['mae', 'mse'])

# create dummy data
n_sample = 5
train_dataset1 = np.random.uniform(0,1, (n_sample,128,3))
train_dataset3 = np.random.uniform(0,1, (n_sample,3))
y = np.random.uniform(0,1, n_sample)

model.fit([train_dataset1, train_dataset1, train_dataset3], y, epochs=3)
model.predict([train_dataset1, train_dataset1, train_dataset3]).shape