Implementação da perda de WARP em Keras

Estou tentando implementar a perda de urdidura (tipo de função de classificação em pares) com a API Keras. Estou meio preso como isso pode ser bem sucedido.

A definição de perda de urdidura é retirada dedoc lightFM.:

Para um determinado (usuário, par de itens positivos), faça uma amostra aleatória de um item negativo de todos os itens restantes. Calcular previsões para os dois itens; se a previsão do item negativo exceder a do item positivo mais uma margem, execute uma atualização gradiente para classificar o item positivo mais alto e o item negativo mais baixo. Se não houver violação de classificação, continue a amostrar itens negativos até que uma violação seja encontrada.

A função Warp é usada, por exemplo, emincorporação semântica de #hashtags, um artigo publicado no Facebook AI research. Neste artigo, eles tentam prever as hashtags mais representáveis para textos curtos. Onde'user' é considerado o texto breve,'positive item' é a hashtag do texto curto enegative items são algumas hashtags aleatórias amostradas uniformemente na 'pesquisa de hashtag'.

Estou seguindo a implementação de outra perda de trigêmeo para criar a deformação:github

Meu entendimento é que, para cada ponto de dados, terei 3 entradas. Exemplo com incorporação (pseudocódigo 'semi'):

sequence_input = Input(shape=(100, ), dtype='int32') # 100 features per data point
positive_example = Input(shape=(1, ), dtype='int32', name="positive") # the one positive example
negative_examples = Input(shape=(1000,), dtype='int32', name="random_negative_examples") # 1000 random negative examples.

#map data points to already created embeddings
embedded_seq_input = embedded_layer(sequence_input)
embedded_positive = embedded_layer(positive_example)
embedded_negatives = embedded_layer(negative_examples)

conv1 = Convolution1D(...)(embeddded_seq_input)
               .
               .
               .
z = Dense(vector_size_of_embedding,activation="linear")(convN)

loss = merge([z, embedded_positive, embedded_negatives],mode=warp_loss)
                         .
                         .
                         .

Ondewarp_loss é (onde eu suponho obter 1000 negativos aleatórios em vez de pegar todos eles e as pontuações provêm do cosinus similatiry):

def warp_loss(X):
    # pseudocode
    z, positive, negatives = X
    positive_score = cosinus_similatiry(z, positive)
    counts = 1
    loss = 0
    for negative in negatives:
        score = cosinus_similatiry(z, negative)
        if score > positive_score:
           loss = ((number_of_labels - 1) / counts) * (score + 1 - positive_score
        else:
           counts += 1
    return loss

Como calcular o warp é bem descrito:postar

Não tenho certeza se é a maneira correta de fazê-lo, mas não consegui encontrar uma maneira de implementar owarp_loss pseudo função. Eu posso calcular cosinus usandomerge([x,u],mode='cos') mas isso assume as mesmas dimensões. Então, eu não tenho certeza de como usarmerge modo cos para os vários exemplos negativos, então eu estou tentando criar o meu própriowarp_loss.

Quaisquer informações, exemplos semelhantes implementados, comentários são úteis.

questionAnswers(1)

yourAnswerToTheQuestion