TensorFlow:如何将浮点序列嵌入到固定大小的向量中?

TensorFlow: How to embed float sequences to fixed size vectors?

我正在寻找将具有浮点值的可变长度序列嵌入到固定大小向量的方法。输入格式如下:

[f1,f2,f3,f4]->[f1,f2,f3,f4]->[f1,f2,f3,f4]-> ... -> [f1,f2,f3,f4] [f1,f2,f3,f4]->[f1,f2,f3,f4]->[f1,f2,f3,f4]->[f1,f2,f3,f4]-> ... -> [f1,f2,f3,f4] ... [f1,f2,f3,f4]-> ... -> ->[f1,f2,f3,f4]

每一行都是一个可变长度的序列,最大长度为 60。一个序列中的每个单元都是一个包含 4 个浮点值的元组。我已经填充了零以将所有序列填充到相同的长度。

如果我使用与输入相同的输出,以下架构似乎解决了我的问题,我需要中心的 思想向量 作为序列的嵌入。

在tensorflow中,我找到了两个候选方法tf.contrib.legacy_seq2seq.basic_rnn_seq2seq and tf.contrib.legacy_seq2seq.embedding_rnn_seq2seq

不过这两个方法好像是用来解决NLP问题的,而且输入必须是单词的离散值。

请问还有其他功能可以解决我的问题吗?

要将序列编码为固定长度的向量,您通常会使用递归神经网络 (RNN) 或卷积神经网络 (CNN)。

如果您使用循环神经网络,您可以使用最后一个时间步的输出(序列中的最后一个元素)。这对应于您问题中的思想向量。看看 tf.dynamic_rnndynamic_rnn 要求您指定要使用的 RNN 单元的类型。 tf.contrib.rnn.LSTMCelltf.contrib.rnn.GRUCell 是最常见的。

如果你想使用 CNN,你需要使用一维卷积。要构建 CNN,您需要 tf.layers.conv1d and tf.layers.max_pooling1d

你只需要一个 RNN,而不是 seq2seq 模型,因为 seq2seq 带有一个额外的解码器,这在你的情况下是不必要的。

示例代码:

import numpy as np
import tensorflow as tf
from tensorflow.contrib import rnn

input_size = 4
max_length = 60
hidden_size=64
output_size = 4

x = tf.placeholder(tf.float32, shape=[None, max_length, input_size], name='x')
seqlen = tf.placeholder(tf.int64, shape=[None], name='seqlen')

lstm_cell = rnn.BasicLSTMCell(hidden_size, forget_bias=1.0)

outputs, states = tf.nn.dynamic_rnn(cell=lstm_cell, inputs=x, sequence_length=seqlen, dtype=tf.float32)


encoded_states = states[-1]

W = tf.get_variable(
        name='W',
        shape=[hidden_size, output_size],
        dtype=tf.float32, 
        initializer=tf.random_normal_initializer())
b = tf.get_variable(
        name='b',
        shape=[output_size],
        dtype=tf.float32, 
        initializer=tf.random_normal_initializer())

z = tf.matmul(encoded_states, W) + b
results = tf.sigmoid(z)

###########################
## cost computing and training components goes here
# e.g. 
# targets = tf.placeholder(tf.float32, shape=[None, input_size], name='targets')
# cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=targets, logits=z))
# optimizer = tf.train.AdamOptimizer(learning_rate=0.1).minimize(cost)
###############################

init = tf.global_variables_initializer()



batch_size = 4
data_in = np.zeros((batch_size, max_length, input_size), dtype='float32')
data_in[0, :4, :] = np.random.rand(4, input_size)
data_in[1, :6, :] = np.random.rand(6, input_size)
data_in[2, :20, :] = np.random.rand(20, input_size)
data_in[3, :, :] = np.random.rand(60, input_size)
data_len = np.asarray([4, 6, 20, 60], dtype='int64')



with tf.Session() as sess:
    sess.run(init)
    #########################
    # training process goes here
    #########################
    res = sess.run(results, 
            feed_dict={
                x: data_in, 
                seqlen: data_len})

print(res)

我找到了解决我的问题的方法,使用以下架构,

,

下方的 LSTM 层对序列 x1,x2,...,xn 进行编码。最后一个输出,绿色的,被复制到与上面解码 LSTM 层的输入相同的计数。 tensorflow代码如下

series_input = tf.placeholder(tf.float32, [None, conf.max_series, conf.series_feature_num])
print("Encode input Shape", series_input.get_shape())

# encoding layer
encode_cell = tf.contrib.rnn.MultiRNNCell(
  [tf.contrib.rnn.BasicLSTMCell(conf.rnn_hidden_num, reuse=False) for _ in range(conf.rnn_layer_num)]
)
encode_output, _ = tf.nn.dynamic_rnn(encode_cell, series_input, dtype=tf.float32, scope='encode')
print("Encode output Shape", encode_output.get_shape())

# last output
encode_output = tf.transpose(encode_output, [1, 0, 2])
last = tf.gather(encode_output, int(encode_output.get_shape()[0]) - 1)

# duplite the last output of the encoding layer
decoder_input = tf.stack([last for _ in range(conf.max_series)], axis=1)
print("Decoder input shape", decoder_input.get_shape())

# decoding layer
decode_cell = tf.contrib.rnn.MultiRNNCell(
  [tf.contrib.rnn.BasicLSTMCell(conf.series_feature_num, reuse=False) for _ in range(conf.rnn_layer_num)]
)
decode_output, _ = tf.nn.dynamic_rnn(decode_cell, decoder_input, dtype=tf.float32, scope='decode')
print("Decode output", decode_output.get_shape())

# Loss Function
loss = tf.losses.mean_squared_error(labels=series_input, predictions=decode_output)
print("Loss", loss)