在TensorFlow中通过同一个前馈网络传递多个值

我在尝试一次在同一个网络中传递3个值,因为我需要所有3个向量的值来计算三元组损失。但当我传递第二个值时,它会报错。

代码片段如下:

# 运行孪生网络
def forward_prop(x):
    w1 = tf.get_variable("w1", [n1, 2048], initializer=tf.contrib.layers.xavier_initializer()) * 0.01
    b1 = tf.get_variable("b1", [n1, 1], initializer=tf.zeros_initializer())*0.01
    z1 = tf.add(tf.matmul(w1, x), b1)   # n1*2048 x 2048*batch_size = n1*batch_size
    a1 = tf.nn.relu(z1)    # n1*batch_size
    w2 = tf.get_variable("w2", [n2, n1], initializer=tf.contrib.layers.xavier_initializer()) * 0.01
    b2 = tf.get_variable("b2", [n2, 1], initializer=tf.zeros_initializer()) * 0.01
    z2 = tf.add(tf.matmul(w2, a1), b2)   # n2*n1 x n1*batch_size = n2*batch_size
    a2 = tf.nn.relu(z2)    # n2*batch_size
    w3 = tf.get_variable("w3", [n3, n2], initializer=tf.contrib.layers.xavier_initializer()) * 0.01
    b3 = tf.get_variable("b3", [n3, 1], initializer=tf.zeros_initializer()) * 0.01
    z3 = tf.add(tf.matmul(w3, a2), b3)   # n3*n2 x n2*batch_size = n3*batch_size
    a3 = tf.nn.relu(z3)    # n3*batch_size
    w4 = tf.get_variable("w4", [n4, n3], initializer=tf.contrib.layers.xavier_initializer()) * 0.01
    b4 = tf.get_variable("b4", [n4, 1], initializer=tf.zeros_initializer()) * 0.01
    z4 = tf.add(tf.matmul(w4, a3), b4)   # n4*n3 x n3*batch_size = n4*batch_size
    a4 = tf.nn.relu(z4)    # n4*batch_size = 128*batch_size (128 feature vectors for all training examples)
    return a4

def back_prop():
    anchor_embeddings = forward_prop(x1)
    positive_embeddings = forward_prop(x2)
    negative_embeddings = forward_prop(x3)
    # 计算距离的平方和
    distance_positive = tf.reduce_sum(tf.square(anchor_embeddings - positive_embeddings), 0)
    distance_negative = tf.reduce_sum(tf.square(anchor_embeddings - negative_embeddings), 0)
    # 应用三元组损失方程
    triplet_loss = tf.maximum(0., distance_positive - distance_negative + margin)
    triplet_loss = tf.reduce_mean(triplet_loss)
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(triplet_loss)
    with tf.Session as sess:
        sess.run(tf.global_variables_initializer())
        feed_dict = {
        x1: anchors,
        x2: positives,
        x3: negatives
        }
        print("开始运行孪生网络...")
        for epoch in range(total_epochs_net_1):
            for _ in range(len(anchors)):
                _, triplet_loss = sess.run([optimizer, triplet_loss], feed_dict=feed_dict)
            print("第", epoch, "个周期完成,共", total_epochs_net_1, "个周期")
        saver = tf.train.Saver()
        saver.save(sess, 'face_recognition_model')

我在以下这行代码中遇到了错误:

positive_embeddings = forward_prop(x2)

forward_prop()函数中的tf.get_variable引发了错误。

错误信息如下:

ValueError: Variable w1 already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope?

我认为这是因为在第一次调用forward_prop()函数时定义了变量w1,如下所示:

anchor_embeddings = forward_prop(x1)

如何解决这个问题?我不能单独传递这三个值,因为我需要这三个值来计算三元组损失。任何帮助都将不胜感激。谢谢!


回答:

你在这里错误地配置了你的网络:

def back_prop():
    anchor_embeddings = forward_prop(x1)
    positive_embeddings = forward_prop(x2)
    negative_embeddings = forward_prop(x3)

你应该只定义一个网络,你错误地为每个输入定义了三组变量,实际上这里定义了三个神经网络。

对于三元组损失,你应该将3个输入作为一个批次输入到单个网络中(所有3个输入由同一个网络处理),而不是作为单独的变量。对于这个讨论,我假设你的输入是图像,并且你在每个训练步骤上训练一组3个输入。

如果你的图像大小为256x256x1(灰度),那么一个三元组批次的形状将是[3 x 256 x 256 x 1]。现在你的输出将是[3 x size_of_your_output_layer]的形状。你的损失函数现在应该以理解第一个轴代表你的3个值:锚点、正样本、负样本的方式编写。适当地计算损失。

当然,你可以传入多个锚点、正样本和负样本,你只需要在损失函数中更复杂地处理这些情况,尽管这完全可行。不过,我的三元组损失函数已经变得相当复杂了,所以我建议开始时保持简单。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注