Реализация тройной потери внутри слоев Keras - PullRequest
0 голосов
/ 13 сентября 2018

В этом блоге post он реализует тройную потерю за пределами слоев Kears.Он получает anchor_out, pos_out и neg_out из сети, а затем передает их в определенную им функцию triplet_loss().

Интересно, смогу ли я вычислить triplet_loss в слоях Keras, определивмои собственные Lambda слои.

Вот мой проект сети:

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() выдает ошибку.

Моя проблема в том, как решить эту ошибку?Я пытался заменить 0 на K.constant(0,shape=(1,)) и K.constant(0,shape=(None,1)), но они не работают.

1 Ответ

0 голосов
/ 13 сентября 2018

Это работает?

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 в скобку списка,Керас интерпретирует как объединение двух тензоров.Это терпит неудачу из-за несоответствия размера;0 является скаляром и имеет ранг 0, а первый - двумерный массив.Вот что означает ошибка.

Для поэлементного сравнения тензора с одним значением используйте K.maximum, который автоматически транслирует, когда один из аргументов является скалярным.

...