我在尝试一次在同一个网络中传递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个值:锚点、正样本、负样本的方式编写。适当地计算损失。
当然,你可以传入多个锚点、正样本和负样本,你只需要在损失函数中更复杂地处理这些情况,尽管这完全可行。不过,我的三元组损失函数已经变得相当复杂了,所以我建议开始时保持简单。