首页 > 解决方案 > 尝试重新配置在三元组上训练的连体网络以对对进行操作时出现 ValueError

问题描述

我的问题

我正在尝试[anchor_input, similar_input, different_input]在 Keras中实现一个 Siamese 网络,该网络经过三元组训练——并成对执行——[input_a, input_b]告诉我它们是相似还是不同。我能够很好地训练三元组,甚至已经训练和测试了对,但是当我训练三元组并尝试创建我的成对网络时,我收到以下错误:

ValueError:logits 和标签必须具有相同的形状 (() vs (?, ?))

当前网络概览

我的三元组网络是使用以下代码定义的,对于本示例,我已将其缩减为非常小的内容:

def siamese_triplet(in_shape, feature_dim):
    input_a = Input(shape=in_shape)  # input is a series, n_samples by n_features
    input_b = Input(shape=in_shape)
    input_c = Input(shape=in_shape)
    base_network = create_model()  # makes my Siamese kernel network
    processed_a = base_network(input_a)  # base_network outputs a vector, say 50 elements long
    processed_b = base_network(input_b)
    processed_c = base_network(input_c)
    l1_distance = lambda x: K.abs(x[0] - x[1])  # vector, 50 elements long
    p_distance = Lambda(l1_distance,
                        output_shape=lambda x: x[0])([processed_a, processed_b])
    n_distance = Lambda(l1_distance,
                        output_shape=lambda x: x[0])([processed_a, processed_c])
    triplet_loss = Lambda(lambda x: K.mean(K.maximum(0, x[0] - x[1] + 1)),
                          output_shape=(1,))([p_distance, n_distance])  # scalar
    model = Model([input_a, input_b, input_c], triplet_loss)
    optimizer = SGD()
    model.compile(optimizer=optimizer,
                  loss=lambda x, y: y)  # passes triplet loss through

我训练网络并得到一个合适的model对象。然后,我尝试使用围绕输入对构建的结构重新创建网络,并将base_network从 my 中提取的层传递给它model,最终结果是model.layers[3]

# triplet_net = siamese_triplet(...)
# model = triplet_net.fit(...)
pair_net = siamese_pair(input_shape, model.layers[3])

siamese_pair定义为:

def siamese_pair(in_shape, base_network):
    input_a = Input(shape=in_shape)
    input_b = Input(shape=in_shape)
    processed_a = base_network(input_a)  # vector, 50 elements
    processed_b = base_network(input_b)
    distance = Lambda(lambda x: K.abs(x[0] - x[1]),
                      output_shape=lambda x: x[0])([processed_a, processed_b])  # vector, 50 elements
    prediction = Lambda(lambda x: K.mean(x),
                        output_shape=(1,))(distance)  # scalar
    model = Model([input_a, input_b], prediction)
    optimizer = SGD()
    model.compile(optimizer=optimizer,
                  loss='binary_crossentropy')  # for evaluation purposes

model.compile(...)行引发错误。

请注意,对于相同的对象(类),三元组损失应该将距离推向接近零,对于0不同的对象(类),将它们推向 1 1,因此设置prediction = K.mean(distance)应该非常接近这些类标签之一,我会思考。

我从三元组损失训练到成对评估的过渡对我来说似乎有点笨拙,我很想找出最好的方法,所以我愿意接受改进设计的建议。同时,我很高兴能克服这个错误,这样我至少可以运行并评估我的性能,将输入对分类为相似或不同。

我的问题

  1. 为什么我会收到上述错误?似乎对损失函数完全没有期望y_true 这对我来说很奇怪。
  2. 如何解决上述错误?
  3. 有没有更好的方法可以将我的训练传递base_layer到不同的连体网络结构中?
  4. base_layer有没有更好的方法可以从我接受不同网络结构的训练中获得成对预测?

只回答前两个会很好,但如果有人对后两个也有建议,我会全神贯注。

标签: pythontensorflowmachine-learningneural-networkkeras

解决方案


推荐阅读