如何在Tensorflow RNN中构建嵌入层?

时间:2018-09-04 14:10:14

标签: python tensorflow rnn word-embedding

我正在建立一个RNN LSTM网络,以根据作者的年龄对文本进行分类(二进制分类-年轻/成人)。

似乎网络无法学习,突然开始过度拟合:

rnn_overfitting
红色:火车
蓝色:验证

一种可能是数据表示不够好。我只是按单词的出现频率对其排序,并给它们加索引。例如:

unknown -> 0
the     -> 1
a       -> 2
.       -> 3
to      -> 4

所以我试图用单词嵌入代替它。 我看到了两个示例,但无法在代码中实现。大多数示例如下所示:

embedding = tf.Variable(tf.random_uniform([vocab_size, hidden_size], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, input_data)

这是否意味着我们正在构建一个学习嵌入的图层?我认为应该下载一些Word2Vec或Glove,然后使用它。

无论如何,我想构建此嵌入层...
如果在代码中使用这两行,则会出现错误:

  

TypeError:传递给参数'indices'的值的数据类型float32不在允许的值列表中:int32,int64

所以我想我必须将input_data类型更改为int32。所以我这样做(毕竟是所有索引),我明白了:

  

TypeError:输入必须为序列

我尝试用this answer中的建议将inputs(与tf.contrib.rnn.static_rnn的参数)包装在一起,并使用以下列表:[inputs],但这又产生了另一个错误:

  

ValueError:必须通过以下命令访问输入大小(输入的维度0)   形状推断,但看到值None。


更新

在将张量x传递到embedding_lookup之前,我正在对其进行堆叠。嵌入后,我移动了卸货堆。

更新的代码:

MIN_TOKENS = 10
MAX_TOKENS = 30
x = tf.placeholder("int32", [None, MAX_TOKENS, 1])
y = tf.placeholder("float", [None, N_CLASSES]) # 0.0 / 1.0
...
seqlen = tf.placeholder(tf.int32, [None]) #list of each sequence length*
embedding = tf.Variable(tf.random_uniform([VOCAB_SIZE, HIDDEN_SIZE], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, x) #x is the text after converting to indices
inputs = tf.unstack(inputs, MAX_POST_LENGTH, 1)
outputs, states = tf.contrib.rnn.static_rnn(lstm_cell, inputs, dtype=tf.float32, sequence_length=seqlen) #---> Produces error

* seqlen:我对序列进行了零填充,因此所有序列都具有相同的列表大小,但是由于实际大小不同,我准备了一个列表来描述长度而没有填充。

新错误:

  

ValueError:basic_lstm_cell_1层的输入0与   层:预期ndim = 2,找到的ndim = 3。收到的完整图形:[无,   1,64]

64是每个隐藏层的大小。

很明显,我在尺寸方面有问题...嵌入后如何使输入适合网络?

2 个答案:

答案 0 :(得分:3)

tf.nn.static_rnn中,我们可以看到inputs参数是:

  

长度为T的输入列表,每个输入为张量为[batch_size,input_size]的张量

所以您的代码应类似于:

x = tf.placeholder("int32", [None, MAX_TOKENS])
...
inputs = tf.unstack(inputs, axis=1)

答案 1 :(得分:1)

tf.squeeze是一种从张量中删除大小为1的尺寸的方法。如果最终目标是使输入形状为[None,64],则放置类似于inputs = tf.squeeze(inputs)的线,这将解决您的问题。