3

我在 tflearn 中有一个 lstm 网络,它在给定前面单词的上下文的情况下预测序列中的下一个单词。这些词作为特定大小词汇表的索引输入网络,并以二进制类的形式输出,例如:

上下文:[45, 243, 1, 1906, 4, 2, 0, 0, 0, 0]

标签:[0,0,0.......1,0,0,......0,0,0](VOCAB_SIZE 的长度)

但是,该模型每次都学会预测几乎相同的单词,因为我在回归层中使用了“categorical_crossentropy”目标函数。

我想尝试根据我已经为数据集生成的词嵌入(word2vec)来评估损失。因此,预测“你好”的模型,其中基本事实是“嗨”,其损失将比预测“披萨”低得多。计划是计算两个嵌入向量之间的余弦,以获得单词之间的“相似度”。

我将此自定义损失函数添加到 tflearn 安装中的 objects.py 文件中,但在尝试将预测转换为嵌入向量时遇到了障碍。

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))

返回的错误是:

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].

这表明我不能使用张量来索引 vocab(一个 numpy 数组)。但是,我不能使用 eval() 来获取张量的值,因为它不是在会话中运行的。所以我需要一种方法来设置索引的一维张量到包含相应词向量的张量的转换,以便计算损失。

非常感谢有关此问题的任何帮助,或评估我的模型的其他方式。

4

1 回答 1

1

我使用 tf.gather 解决了这个问题。此外,我通过算法分类的置信度添加了缩放,以修复我遇到的无法计算梯度的错误。下面是代码:

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])

嵌入式相似度(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)

但是,我遇到了一个奇怪的错误。当我尝试拟合模型时,代码运行得非常好,直到它列出了训练和验证样本的数量,如下所示:

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

然后输出只是冻结,但不是整个计算机。我无法 Ctrl-C 代码,必须启动另一个终端。系统似乎也没有显着放缓,我尝试将训练集大小和批量大小都减少到可笑的低数字,但没有结果。

我将此问题标记为已解决,因为我回答了我遇到的主要问题,但是如果有人在此之前遇到过这种行为,请发表评论。谢谢!

于 2017-01-30T20:43:34.137 回答