2017-01-28 4 views
2

J'ai un réseau lstm dans tflearn qui prédit le mot suivant dans une séquence donnée dans un contexte de mots précédents. Les mots sont introduits dans le réseau en tant qu'indices d'un vocabulaire de taille donnée et sont sortis en classes binaires, par exemple:tflearn fonction de perte personnalisée pour la similitude de cosinus

contexte: [45, 243, 1, 1906, 4, 2, 0, 0, 0 , 0]

étiquette

: [0,0,0 ....... 1,0,0, 0,0,0 ......] (longueur de VOCAB_SIZE)

Cependant , le modèle apprend à prédire presque le même mot à chaque fois parce que j'utilise la fonction objective "categorical_crossentropy" dans la couche de régression.

Je voudrais essayer d'évaluer la perte basée sur les plongées de mots (word2vec), que j'ai déjà générées pour l'ensemble de données. Ainsi, le modèle prédisant «bonjour» où la vérité au sol est «salut» aurait une perte beaucoup plus faible que la prévision de «pizza». Le plan consiste à calculer le cosinus entre deux vecteurs d'inclusion pour obtenir la "similarité" entre les mots.

J'ajoute cette fonction de perte personnalisée au fichier objectifs.py dans l'installation de tflearn, mais j'ai rencontré un roadblock lorsque j'ai essayé de convertir les prédictions en vecteurs d'incorporation.

tflearn/objectives.py:

vocab = np.loadtxt('/home/vocab.txt',dtype='str') 
embedding_model = gensim.models.Word2Vec.load('/home/embedding') 

def embedded_similarity(y_pred, y_true): 
    global vocab, embedding_model 
    with tf.name_scope("Similarity"): 
     #convert one-hot format to indices of max values (predictions) 
     pred_max = tf.argmax(y_pred,dimension=1) 
     true_max = tf.argmax(y_true,dimension=1) 

     #convert indices into embedded vectors 
     pred_vectors = tf.map_fn(lambda x: embedding_model[vocab[x]], pred_max) 
     true_vectors = tf.map_fn(lambda x: embedding_model[vocab[x]], true_max) 

     #calc dot product 
     dot_products = tf.reduce_sum(tf.mul(pred_vectors,true_vectors),axis=1) 

     #return inverse mean of dot products 
     return -1*(tf.reduce_mean(dot_products)) 

L'erreur renvoyée est:

ValueError: Index out of range using input dim 0; input has only 0 dims for 'Similarity/map/while/strided_slice' (op: 'StridedSlice') with input shapes: [], [1], [1], [1]. 

Cela indique que je ne peux pas utiliser un tenseur pour indexer dans vocab (un tableau numpy). Cependant, je ne peux pas utiliser eval() pour saisir la valeur du tenseur car celle-ci n'est pas exécutée dans une session. J'ai donc besoin d'un moyen de mettre en place la transformation d'un tenseur d'indices 1D en un tenseur contenant les vecteurs mots correspondants, afin de calculer la perte.

Toute aide concernant ce problème, ou une autre façon d'évaluer mon modèle, est grandement appréciée.

+0

aussi: l'erreur se produit sur la ligne avec tf.map_fn, et pointe vers où je indexe en vocab avec x – etc

Répondre

1

J'ai utilisé tf.gather pour résoudre ce problème. De plus, j'ai ajouté la mise à l'échelle par la confiance de la classification de l'algorithme, pour corriger un bogue dans lequel les dégradés ne pouvaient pas être calculés. Voici le code:

Code

à l'en-tête de objectives.py:

import numpy as np 
import gensim 
vocab = np.genfromtxt('/home/vocab.txt',dtype='str') 
embedding_model = gensim.models.Word2Vec.load('/home/embedding') 
i2v = [] 
for v in vocab: 
i2v.append(embedding_model[v]) 

embedded_similarity (y_pred, y_true):

global i2v 
with tf.name_scope("Similarity"): 

    i2v_tensors = [ tf.cast(tf.constant(iv), tf.float32) for iv in i2v ] 
    i2v_tensorarray = tf.pack(i2v_tensors) 

    #convert one-hot to indices 
    pred_max = tf.cast(tf.argmax(y_pred,dimension=1), tf.int32) 
    true_max = tf.cast(tf.argmax(y_true,dimension=1), tf.int32) 

    #extract probabilities for scaling later 
    pred_iter = tf.concat(tf.constant(1),[y_pred,tf.pack([tf.cast(pred_max,tf.float32)],axis=1)]) 
    confidence_scaler = 1/tf.map_fn(lambda x: tf.gather(x, tf.cast(tf.gather(x,tf.constant(5002)),tf.int32)), pred_iter, tf.float32) 

    #convert indices into vectors (of type tensor) 
    pred_vectors = tf.map_fn(lambda x: tf.gather(i2v_tensorarray, x), pred_max, tf.float32) 
    true_vectors = tf.map_fn(lambda x: tf.gather(i2v_tensorarray, x), true_max, tf.float32) 

    #calc dot product 
    dot_products = tf.reduce_sum(tf.mul(pred_vectors,true_vectors),axis=1) 

    #divide by magnitudes 
    pred_magnitudes = tf.sqrt(tf.reduce_sum(tf.mul(pred_vectors,pred_vectors),axis=1)) 
    true_magnitudes = tf.sqrt(tf.reduce_sum(tf.mul(true_vectors,true_vectors),axis=1)) 

    cosines = dot_products/tf.mul(pred_magnitudes,true_magnitudes) 
    loss = -1*tf.cast(cosines, tf.float32) + 2 #min loss is 1, max is 3 
    scaled_loss = tf.multiply(loss, confidence_scaler) 
    # loss = -1*cosines + 1 

    # return inverse sum of dot products 
    return tf.reduce_mean(scaled_loss) 

Cependant, je rencontre un bug étrange. Lorsque je tente d'adapter le modèle, le code fonctionne parfaitement bien jusqu'à ce qu'il indique le nombre d'échantillons de formation et de validation, comme ci-dessous:

--------------------------------- 
Training samples: 800 
Validation samples: 200 

Ensuite, la sortie se fige simplement, mais pas tout l'ordinateur. Je suis incapable de Ctrl-C le code, et dois commencer un autre terminal. Il ne semble pas non plus y avoir de ralentissement significatif dans le système, et j'ai essayé de réduire à la fois les tailles d'ensembles d'entraînement et les tailles de lots pour obtenir des chiffres ridiculement bas, sans résultat.

Je vais marquer ce problème comme résolu parce que j'ai répondu au problème principal que j'avais, mais si quelqu'un a rencontré ce type de comportement avant s'il vous plaît commenter. Merci!