In this blog post, he implements the triple loss outside the Kears layers. He gets the anchor_out
, pos_out
and neg_out
from the network and then passes them to the triplet_loss()
function he defined.
I wonder if I can calculate the triplet_loss within the Keras layers by defining my own Lambda
layers.
Here's my network design:
margin=1
anchor_input = Input((600, ), name='anchor')
positive_input = Input((600, ), name='positive_input')
negative_input = Input((600, ), name='negative_input')
# Shared embedding layer for positive and negative items
Shared_DNN = Dense(300)
encoded_anchor = Shared_DNN(anchor_input)
encoded_positive = Shared_DNN(positive_input)
encoded_negative = Shared_DNN(negative_input)
DAP = Lambda(lambda tensors:K.sum(K.square(tensors[0] - tensors[1]),axis=1,keepdims=True),name='DAP_loss') #Distance for Anchor-Positive pair
DAN = Lambda(lambda tensors:K.sum(K.square(tensors[0] - tensors[1]),axis=1,keepdims=True),name='DAN_loss') #Distance for Anchor-Negative pair
Triplet_loss = Lambda(lambda loss:K.max([(loss[0] - loss[1] + margin),0],axis=0),name='Triplet_loss') #Distance for Anchor-Negative pair
DAP_loss = DAP([encoded_anchor,encoded_positive])
DAN_loss = DAN([encoded_anchor,encoded_negative])
#call this layer on list of two input tensors.
Final_loss = Triplet_loss([DAP_loss,DAN_loss])
model = Model(inputs=[anchor_input,positive_input, negative_input], outputs=Final_loss)
However, it gives me the error:
Tried to convert 'input' to a tensor and failed. Error: Shapes must be equal rank, but are 2 and 0
From merging shape 0 with other shapes. for 'Triplet_loss_4/Max/packed' (op: 'Pack') with input shapes: [?,1], []
The error is from the Triplet_loss
layer. In the K.max()
function, the first number loss[0] - loss[1] + margin
has the shape (None,1)
. Yet the second number 0 has the shape (1)
. The two number are not of the same shape and therefore the K.max()
function gives out an error.
My problem is, how to solve this error?
I have tried replacing the 0
with K.constant(0,shape=(1,))
and K.constant(0,shape=(None,1))
, but they doesn't work.
Does this work?
Triplet_loss = Lambda(lambda loss: K.maximum(loss[0] - loss[1] + margin, 0.0),
name='Triplet_loss')
I think the issue with this line
Triplet_loss = Lambda(lambda loss:K.max([(loss[0] - loss[1] + margin), 0],
axis=0),name='Triplet_loss')
is that you are putting loss[0]-loss[1]+margin
tensor and 0
in the list bracket, which keras interprets as concatenating two tensors. This fails due to the size mismatch; 0
is a scalar and has rank 0, while the first one is 2d array. This is what the error means.
To compare a tensor against a single value element-wise, use K.maximum
, which broadcasts automatically when one of the arguments is a scalar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With