我目前正在使用生成RNN来对序列中的索引进行分类(有点像判断某物是否为噪声)。
我的输入是连续的(即介于0到1之间的实数),而我的输出要么是0,要么是1。
例如,如果模型对大于0.5的数字标记为1,否则标记为0,
[.21, .35, .78, .56, ..., .21] => [0, 0, 1, 1, ..., 0]:
0 0 1 1 0 ^ ^ ^ ^ ^ | | | | |o->L1 ->L2 ->L3 ->L4 ->... ->L10 ^ ^ ^ ^ ^ | | | | | .21 .35 .78 .56 ... .21
使用
n_steps = 10n_inputs = 1n_neurons = 7X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])y = tf.placeholder(tf.float32, [None, n_steps, n_outputs])cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons, activation=tf.nn.relu)rnn_outputs, states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
rnn_outputs变成形状为(?, 10, 7)的张量,大概是每个10个时间步的7个输出。
之前,我在包装了rnn_outputs
的输出投影上运行了以下代码片段,以获得每个序列的分类标签。
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y,logits=logits)loss = tf.reduce_mean(xentropy)
我如何在rnn_outputs上运行类似的操作来获得一个序列?
具体来说,
1. 我可以从每个步骤获取rnn_output并将其输入到softmax中吗?
curr_state = rnn_outputs[:,i,:]logits = tf.layers.dense(states, n_outputs)xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
2. 我应该使用什么损失函数?它应该应用于每个序列的每个值吗?(对于序列i和步骤j,loss = y_{ij} (true) - y_{ij}(predicted)
)
我的损失应该为loss = tf.reduce_mean(np.sum(xentropy))
吗?
编辑看起来我试图实现的与https://machinelearningmastery.com/develop-bidirectional-lstm-sequence-classification-python-keras/中的类似内容在TensorFlow中实现类似的东西。
在Keras中,有一个TimeDistributed
函数:
然后你可以使用TimeDistributed将Dense层独立地应用于10个时间步中的每一个
我如何在Tensorflow中实现类似的功能?
回答:
首先,看起来你在做序列到序列的建模。在这种问题中,通常最好使用编码器-解码器架构,而不是用同一个RNN来预测序列。Tensorflow有一个名为“Neural Machine Translation (seq2seq) Tutorial”的大型教程,我建议你查看一下。
然而,你所询问的架构也是可能的,前提是n_steps
是静态已知的(尽管使用了dynamic_rnn
)。在这种情况下,可以计算每个单元输出的交叉熵,然后将所有损失相加。如果RNN长度是动态的也是可能的,但会更加复杂。以下是代码:
n_steps = 2n_inputs = 3n_neurons = 5X = tf.placeholder(dtype=tf.float32, shape=[None, n_steps, n_inputs], name='x')y = tf.placeholder(dtype=tf.int32, shape=[None, n_steps], name='y')basic_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=n_neurons)outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)# 重塑以使`time`成为0轴time_based_outputs = tf.transpose(outputs, [1, 0, 2])time_based_labels = tf.transpose(y, [1, 0])losses = []for i in range(n_steps): cell_output = time_based_outputs[i] # 获取输出,可以根据需要应用更多的密集层 labels = time_based_labels[i] # 获取标签(稀疏) loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=cell_output) losses.append(loss) # 收集所有损失total_loss = tf.reduce_sum(losses) # 计算总损失