我有两个预先训练的模型。假设它们是model_A和model_B。在此,model_A是CNN + LSTM网络,而model_B是GCN。
Model_A:
Model_A需要1个输入,如下所示。
X_in = Input(shape=(None, 150), name='X_in', dtype=int32)
Model_B:
Model_B需要3个输入,如下所示。
X_in = Input(shape=(X_train_B[0].shape[-1], ), name='X_in', dtype=tf.float64)
A_in = Input(shape=(None,), sparse=True, dtype=tf.float64)
I_in = Input(shape=(), name='segment_ids_in', dtype=tf.int32)
我需要通过获取最后一层之前的输出来合并这两个模型。下面是我定义新模型的方式。
model_A = load_model('model_A.h5')
model_A = Model(inputs=model_A.inputs, outputs=model_A.layers[-2].output)
model_B = load_model('model_B.h5', custom_objects={'GraphConvSkip': GraphConvSkip, 'MinCutPool': MinCutPool,
'GlobalAvgPool': GlobalAvgPool})
model_B = Model(inputs=model_B.inputs, outputs=model_B.layers[-2].output)
def final_model():
X_in = Input(shape=(X_train_B[0].shape[-1] ), name='X_in', dtype=tf.float64)
A_in = Input(shape=(None,), sparse=True, dtype=tf.float64)
I_in = Input(shape=(), name='segment_ids_in', dtype=tf.int32)
merged = Concatenate(axis=1)([X_in, A_in, I_in])
concat = concatenate([model_A.output, model_B.output], axis=-1)
concat = Dense(1, activation='sigmoid')(concat)
model = Model(inputs=[model_A.input, merged], outputs=concat)
adam = tf.keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
model.compile(optimizer=adam, loss='binary_crossentropy', metrics=['acc'])
return model
model = final_model()
model.fit([X_train_A,[X_train_B, A_train_B, I_]], [y_train_A], verbose=1)
执行此代码后,出现以下错误。
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-54-8c7e818acc11> in <module>
----> 1 model = final_model()
2
3 print('Fitting model')
4 batches = batch_iterator([A_train_B, X_train_B, y_train_B, X_train_A, y_train_A], batch_size=1, epochs=2)
5 for b in batches:
<ipython-input-53-5c9278e5efb8> in final_model()
3 A_in = Input(shape=(None,), sparse=True, dtype=tf.float64)
4 I_in = Input(shape=(), name='segment_ids_in', dtype=tf.int32)
----> 5 merged = Concatenate(axis=1)([X_in, A_in, I_in])
6
7 concat = concatenate([model_A.output, model_B.output], axis=-1)
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
746 # Build layer if applicable (if the `build` method has been
747 # overridden).
--> 748 self._maybe_build(inputs)
749 cast_inputs = self._maybe_cast_inputs(inputs)
750
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/base_layer.py in _maybe_build(self, inputs)
2114 # operations.
2115 with tf_utils.maybe_init_scope(self):
-> 2116 self.build(input_shapes)
2117 # We must set self.built since user defined build functions are not
2118 # constrained to set self.built.
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/utils/tf_utils.py in wrapper(instance, input_shape)
304 if input_shape is not None:
305 input_shape = convert_shapes(input_shape, to_tuples=True)
--> 306 output_shape = fn(instance, input_shape)
307 # Return shapes from `fn` as TensorShapes.
308 if output_shape is not None:
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/layers/merge.py in build(self, input_shape)
380 shape_set = set()
381 for i in range(len(reduced_inputs_shapes)):
--> 382 del reduced_inputs_shapes[i][self.axis]
383 shape_set.add(tuple(reduced_inputs_shapes[i]))
384
IndexError: list assignment index out of range
有人可以帮助我解决如何将这些输入值传递给两个不同的模型吗?
----编辑01 ----
根据Andrea的建议修改代码后,出现以下错误。我也尝试使用np.array()传递输入,但是仍然遇到相同的错误。您能检查我在哪里弄错了吗?
此外,这是我要传递给模型B的值。由于它是图形,所以X_是N*d
特征向量,A_是N*N
邻接矩阵,I_是segment_ids通过致电get('XAI')
。
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-71-22f819a7a9cd> in <module>
18 return model
19
---> 20 model = final_model()
21 print('Fitting model')
22 batches = batch_iterator([A_train_B, X_train_B, y_train_B, X_train_A, y_train_A], batch_size=1, epochs=2)
<ipython-input-71-22f819a7a9cd> in final_model()
7
8 def final_model():
----> 9 concat = Concatenate(-1)([model_A.outputs, model_B.outputs]) # merge outputs
10 concat = Dense(1, activation='sigmoid')(concat)
11
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
771 not base_layer_utils.is_in_eager_or_tf_function()):
772 with auto_control_deps.AutomaticControlDependencies() as acd:
--> 773 outputs = call_fn(cast_inputs, *args, **kwargs)
774 # Wrap Tensors in `outputs` in `tf.identity` to avoid
775 # circular dependencies.
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/layers/merge.py in call(self, inputs)
179 return y
180 else:
--> 181 return self._merge_function(inputs)
182
183 @tf_utils.shape_type_conversion
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/layers/merge.py in _merge_function(self, inputs)
402
403 def _merge_function(self, inputs):
--> 404 return K.concatenate(inputs, axis=self.axis)
405
406 @tf_utils.shape_type_conversion
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/backend.py in concatenate(tensors, axis)
2671 """
2672 if axis < 0:
-> 2673 rank = ndim(tensors[0])
2674 if rank:
2675 axis %= rank
~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/backend.py in ndim(x)
1200
1201 """
-> 1202 dims = x.shape._dims
1203 if dims is not None:
1204 return len(dims)
AttributeError: 'list' object has no attribute 'shape'
答案 0 :(得分:0)
问题出在您的I_in = Input(shape=(), name='segment_ids_in', dtype=tf.int32)
上,此输入层的形状为(None,)
(等级为1),而其他输入的等级为2,则转换为(None, 2)
之类的形状。您可以在模型摘要中看到这一点。您正在尝试通过第二个维度(axis=1)
进行连接,但此操作无法完成,因为I_in
没有第二个维度,只有批量维度。
尝试将I_in
扩展为第二个维度,例如:
def final_model():
X_in = Input(shape=(X_train_B[0].shape[-1] ), name='X_in', dtype=tf.float64)
A_in = Input(shape=(None,), sparse=True, dtype=tf.float64)
I_in = Input(shape=(), name='segment_ids_in', dtype=tf.int32)
I_in = Lambda(lambda x: tf.expand_dims(x, -1))(I_in)
merged = Concatenate(axis=1)([X_in, A_in, I_in])
concat = concatenate([model_A.output, model_B.output], axis=-1)
concat = Dense(1, activation='sigmoid')(concat)
model = Model(inputs=[model_A.input, merged], outputs=concat)
adam = tf.keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
model.compile(optimizer=adam, loss='binary_crossentropy', metrics=['acc'])
return model
经OP澄清后进行编辑:
您没有在代码中通过模型传递输入。如果我理解正确,您有4个输入,想要将第一个输入通过model_A,其余输入通过model_B。最后,您要输出连接的第二层到最后一层的输出。为此,您不需要连接model_B的输入。 由于我没有完整的代码,因此无法尝试,但是我认为这应该可行:
model_A = load_model('model_A.h5')
model_B = load_model('model_B.h5', custom_objects={'GraphConvSkip': GraphConvSkip, 'MinCutPool': MinCutPool,
'GlobalAvgPool': GlobalAvgPool})
def final_model():
concat = Concatenate(-1)([model_A.get_layer(-2).output, model_B.get_layer(-2).output]) # merge outputs
concat = Dense(1, activation='sigmoid')(concat)
model = Model(inputs=[model_A.inputs, model_B.inputs], # the inputs do not change!
outputs=concat)
adam = tf.keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999,
epsilon=1e-08, decay=0.0)
model.compile(optimizer=adam, loss='binary_crossentropy', metrics=
['acc'])
return model
model = final_model()
model.fit([X_train_A, X_train_B, A_train_B, I_], # notice how the inner list disappeared!
[y_train_A], verbose=1)
请确保您的y_train_A
的形状(BATCH_NUM,64),因为您要通过最后一个轴(第二到最后一层输出)连接两个(BATCH_NUM,32)张量。
答案 1 :(得分:0)
我找到了以下针对我问题的解决方案。
# Constructing the model
concat = Concatenate(-1)([model_A.output, model_B.output]) # merge outputs
concat = Dense(2, activation='sigmoid', name='output')(concat)
model = Model(inputs=[model_A.inputs, model_B.inputs], outputs=concat)
model.compile(optimizer='adam',
loss='binary_crossentropy')
# Training setup
opt = tf.keras.optimizers.Adam(learning_rate=learning_rate)
loss_fn = model.loss_functions[0]
acc_fn = lambda x, y: K.mean(tf.keras.metrics.categorical_accuracy(x, y))
# Training function
@tf.function(experimental_relax_shapes=True)
def train_step(inputs, targets):
with tf.GradientTape() as tape:
predictions = model(inputs, training=True)
loss = loss_fn(targets, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
opt.apply_gradients(zip(gradients, model.trainable_variables))
return loss, acc_fn(targets, predictions)
# Training the model
batches = batch_iterator([A_train_B, X_train_B, y_train_B, X_train_A], batch_size=batch_size, epochs=epochs)
for b in batches:
X_, A_, I_ = Batch(b[0], b[1]).get('XAI')
A_ = sp_matrix_to_sp_tensor(A_)
y_ = b[2]
X_A_ = b[3]
outs = train_step([X_A_, X_, A_, I_], y_)