Implicación de la pérdida de WARP en Keras

Estoy tratando de implementar la pérdida de deformación (tipo de función de clasificación por pares) con la API de Keras. Estoy un poco atrapado en cómo se puede lograr esto.

La definición de pérdida de urdimbre se toma delightFM doc.:

Para un determinado (usuario, par de elementos positivos), muestree un elemento negativo al azar de todos los elementos restantes. Calcular predicciones para ambos elementos; Si la predicción del elemento negativo excede la del elemento positivo más un margen, realice una actualización de gradiente para clasificar el elemento positivo más alto y el elemento negativo más bajo. Si no hay una infracción de rango, continúe muestreando elementos negativos hasta encontrar una infracción.

La función de deformación se utiliza, por ejemplo, enincrustaciones semánticas de #hashtags, un artículo publicado en Facebook AI research. En este artículo intentan predecir los hashtags más representables para textos cortos. Dónde'user' se considera el texto breve'positive item' es el hashtag del texto breve ynegative items son algunos hashtags aleatorios muestreados uniformemente de la 'búsqueda de hashtag'.

Estoy siguiendo la implicación de otra pérdida de triplete para crear la deformación:github

Entiendo que para cada punto de datos tendré 3 entradas. Ejemplo con incrustaciones (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)
                         .
                         .
                         .

dóndewarp_loss es (donde supongo que obtendré 1000 negativos aleatorios en lugar de tomarlos todos y las puntuaciones provienen del cosinus similartiry):

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

Cómo calcular la deformación se describe muy bien:enviar

No estoy seguro de si es la forma correcta de hacerlo, pero no pude encontrar una manera de implementar elwarp_loss pseudo función. Puedo calcular cosinus usandomerge([x,u],mode='cos') pero esto supone las mismas dimensiones. Así que no estoy seguro de cómo usarmerge modo cos para los múltiples ejemplos negativos, así que estoy tratando de crear mi propiowarp_loss.

Cualquier información, ejemplos similares implementados, comentarios son útiles.

Respuestas a la pregunta(1)

Su respuesta a la pregunta