Tensorflow通过循环神经网络反向传播时出现ValueError错误

3
我正在使用tensorflow中的BasicLSTMCells来构建循环神经网络。我的输入序列是单词ID,我将每个ID转换成单词嵌入,然后逐个单词地通过rnn,并在读取整个序列后对单个单词进行预测。我的嵌入矩阵的维度为V x H,其中V是我的词汇表大小,H是我rnn中隐藏单元的数量。为了预测下一个单词,我将隐藏向量乘以大小为H x V的权重矩阵,然后计算softmax。使用我描述的设置,一切似乎都按预期工作。我能够训练一些例子并做出合理的预测。 然而,我注意到如果我尝试使用嵌入矩阵的转置,它将是一个大小为H x V的矩阵,而不是一个单独的softmax层矩阵,tensorflow会引发值错误,声称某些未指定的东西的维度没有相同的秩。我已经验证了我的嵌入矩阵(其转置)的维度与我创建的单独softmax矩阵的维度相同。仅仅改变一行代码,从使用我的嵌入矩阵到使用单独的softmax权重矩阵就会导致错误。 我创建了一个相对较小的程序来演示我想做什么,并展示了什么导致了错误。当我尝试使用单个隐藏层网络进行测试时,无法在更小的网络上发生错误。
import sys
import time
import tensorflow as tf
from tensorflow.models.rnn import rnn
from tensorflow.models.rnn import rnn_cell
from tensorflow.models.rnn.rnn_cell import BasicLSTMCell
import numpy as np

INPUT_LENGTH = 17
BATCH_SIZE = 20
VOCAB_SIZE = 11
NUM_EPOCHS = 1000
HIDDEN_UNITS = 100

class Model(object):
    def __init__(self, is_training):
        initializer = tf.random_uniform_initializer(-1.0, 1.0)

        self._target = tf.placeholder(tf.float32, [BATCH_SIZE, VOCAB_SIZE])
        self._input_data=tf.placeholder(tf.int32,[BATCH_SIZE, INPUT_LENGTH])

        self.embedding = tf.get_variable("embedding",
                                    [VOCAB_SIZE, HIDDEN_UNITS],
                                    initializer=initializer)

        self.inputs = tf.split(1, INPUT_LENGTH,
                          tf.nn.embedding_lookup(self.embedding, self._input_data))

        self.inputs2 = [tf.squeeze(input_, [1]) for input_ in self.inputs]

        cell = rnn_cell.BasicLSTMCell(num_units=HIDDEN_UNITS)

        initial_state = cell.zero_state(BATCH_SIZE, tf.float32)
        outputs, states = rnn.rnn(cell, self.inputs2,
                                  initial_state=initial_state)

        self._outputs = outputs[-1]

        self.soft_w = tf.get_variable("softmax_w",
                                 [HIDDEN_UNITS, VOCAB_SIZE],
                                 initializer=initializer)


        prod = tf.matmul(self._outputs, self.soft_w)
#uncommenting out the following line causes the error
#        prod = tf.matmul(self._outputs, self.embedding, False, True)
        soft_b = tf.get_variable("softmax_b", [VOCAB_SIZE],
                                 initializer=initializer)
        self._logits = tf.nn.bias_add(prod,soft_b)
        self._loss = tf.nn.softmax_cross_entropy_with_logits(self._logits,
                                                             self._target)

        if not is_training:
            return

        learning_rate = .010001
        optimizer = tf.train.GradientDescentOptimizer(learning_rate)
        self._train_op = optimizer.minimize(self._loss)

    def train(self, sess, inputs, targets):
        t = np.zeros((BATCH_SIZE, VOCAB_SIZE))
        for i, target in enumerate(targets):
            t[i,target] = 1.0

        inputs = np.array(inputs)
        inputs = inputs.reshape(BATCH_SIZE,INPUT_LENGTH)

        fd = {self._target:t,
              self._input_data:inputs}
        o = sess.run([self._train_op, self._loss, self._outputs, self.embedding, self.soft_w], feed_dict = fd)
        print o[2].shape
        print o[3].shape
        print o[4].shape
        sys.exit()
        return np.mean(o[1])

#this just generates dummy data
def read_data_rows(count):
    ret = []
    for i in range(count):
        inputs = [4] * INPUT_LENGTH
        output = 1
        ret.append((inputs, output))
    return ret


def main():
    start = time.time()
    tf.set_random_seed(1)

    print "creating model",time.time()-start
    m = Model(is_training=True)

    with tf.Session() as sess:
        print "initializing variables", time.time()-start
        tf.initialize_all_variables().run()

        for epoch in range(NUM_EPOCHS):
            train_rows = read_data_rows(100)
            for row_num in range(0, len(train_rows), BATCH_SIZE):
                qs = []
                ans = []
                batch = train_rows[row_num:row_num+BATCH_SIZE]
                for b in batch:
                    qs.append(b[0])
                    ans.append(b[1])
                m.train(sess, qs, ans)

if __name__ == "__main__":
    main()

我看到的错误是ValueError:当取消注释我上面提到的那一行时,形状TensorShape([Dimension(100)])和TensorShape([Dimension(17),Dimension(100)])必须具有相同的秩。我看到的错误的原因是什么?为什么嵌入矩阵没有像self.soft_w矩阵一样处理?
1个回答

4
TensorFlow的0.6.0版本(以及之前版本)在实现tf.nn.embedding_lookup()tf.gather()梯度时存在一个错误,当indices参数(即您代码中的self._input_data)具有多个维度时会出现问题。
升级到最新的源代码版本应该可以解决此错误。否则,此提交包含了相关更改(对于array_grad.py),可以使您的程序正常工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接