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.