在 Keras 层内实现三元组损失
Implementing Triplet Loss inside Keras Layers
在此博客 post 中,他在 Kears 层之外实现了三重损失。他从网络中获取anchor_out
、pos_out
和neg_out
,然后将它们传递给他定义的triplet_loss()
函数。
我想知道是否可以通过定义自己的 Lambda
层来计算 Keras 层内的 triplet_loss。
这是我的网络设计:
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)
但是,它给我错误:
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], []
错误来自 Triplet_loss
层。在 K.max()
函数中,第一个数字 loss[0] - loss[1] + margin
的形状为 (None,1)
。然而第二个数字 0 的形状为 (1)
。这两个数字的形状不同,因此 K.max()
函数会报错。
我的问题是,如何解决这个错误?
我尝试用 K.constant(0,shape=(1,))
和 K.constant(0,shape=(None,1))
替换 0
,但它们不起作用。
这个有用吗?
Triplet_loss = Lambda(lambda loss: K.maximum(loss[0] - loss[1] + margin, 0.0),
name='Triplet_loss')
我认为这条线有问题
Triplet_loss = Lambda(lambda loss:K.max([(loss[0] - loss[1] + margin), 0],
axis=0),name='Triplet_loss')
是你将 loss[0]-loss[1]+margin
张量和 0
放在列表括号中,keras 将其解释为连接两个张量。由于大小不匹配而失败; 0
是一个标量,秩为 0,而第一个是二维数组。这就是错误的意思。
要按元素比较张量和单个值,请使用 K.maximum
,当其中一个参数是标量时会自动广播。
在此博客 post 中,他在 Kears 层之外实现了三重损失。他从网络中获取anchor_out
、pos_out
和neg_out
,然后将它们传递给他定义的triplet_loss()
函数。
我想知道是否可以通过定义自己的 Lambda
层来计算 Keras 层内的 triplet_loss。
这是我的网络设计:
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)
但是,它给我错误:
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], []
错误来自 Triplet_loss
层。在 K.max()
函数中,第一个数字 loss[0] - loss[1] + margin
的形状为 (None,1)
。然而第二个数字 0 的形状为 (1)
。这两个数字的形状不同,因此 K.max()
函数会报错。
我的问题是,如何解决这个错误?
我尝试用 K.constant(0,shape=(1,))
和 K.constant(0,shape=(None,1))
替换 0
,但它们不起作用。
这个有用吗?
Triplet_loss = Lambda(lambda loss: K.maximum(loss[0] - loss[1] + margin, 0.0),
name='Triplet_loss')
我认为这条线有问题
Triplet_loss = Lambda(lambda loss:K.max([(loss[0] - loss[1] + margin), 0],
axis=0),name='Triplet_loss')
是你将 loss[0]-loss[1]+margin
张量和 0
放在列表括号中,keras 将其解释为连接两个张量。由于大小不匹配而失败; 0
是一个标量,秩为 0,而第一个是二维数组。这就是错误的意思。
要按元素比较张量和单个值,请使用 K.maximum
,当其中一个参数是标量时会自动广播。