0

刚开始使用 TensorFlow 构建用于多类分类的 LSTM 网络

给定如下所示的结构:RNN 模型 假设每个节点 A 代表 TensorFlow BasicLSTMcell。

根据网上找到的一些流行的例子,训练的输入准备为[batch_size, timeStep_size, feature_size]

假设 timeStep_size = 5,feature_size = 2,num_class = 4,给定一个训练集:(虚拟数据)

t =     t0  t1  t2  t3  t4

x =   [ [1] [2] [2] [5] [2] ]
      [ [2] [3] [3] [1] [2] ]

y =   [ [0] [1] [1] [0] [0] ]
      [ [1] [0] [0] [0] [0] ]
      [ [0] [0] [0] [0] [1] ]
      [ [0] [0] [0] [1] [0] ]

根据流行的用法:

...
# 1-layer LSTM with n_hidden units.
rnn_cell = rnn.BasicLSTMCell(n_hidden)

# generate prediction
outputs, states = rnn.static_rnn(rnn_cell, x, dtype=tf.float32)

return tf.matmul(outputs[-1], weights['out']) + biases['out']

在我看来,LSTM 单元的训练并没有利用 y 的所有五个输出(y 在 t0 - t3)。与 output[-1] 相比,只有时间 t4 的 y 用于计算损失。

问题1:是不是LSTM自己计算/逼近y_t0,然后输入t1来计算y_t1,依此类推……直到计算出y_t4?

如果是这种情况,

问题 2:如果 t-1 时的 y 非常重要怎么办?

例子:

t =     t-1 t0  t1  t2  t3  t4

x =   [ [1] [2] [2] [2] [2] [2]]
      [ [1] [2] [2] [2] [2] [2]]

y =   [ [0] [1] [1] [1] [1] [1]]
      [ [1] [0] [0] [0] [0] [0]]
      [ [0] [0] [0] [0] [0] [0]]
      [ [0] [0] [0] [0] [0] [0]]

对比:

t =     t-1 t0  t1  t2  t3  t4

x =   [ [3] [2] [2] [2] [2] [2]]
      [ [3] [2] [2] [2] [2] [2]]

y =   [ [0] [0] [0] [0] [0] [0]]
      [ [0] [0] [0] [0] [0] [0]]
      [ [1] [0] [0] [0] [0] [0]]
      [ [0] [1] [1] [1] [1] [1]]

这意味着即使从 t0 到 t4 的输入特征相同,但输出 y 是不同的,因为之前的输出 (y_t-1) 是不同的。

那么如何处理这种情况呢?在计算 t0 的输出时,TensorFlow 如何设置 t-1 的输出?

我想过增加timeStep_Size,但实际情况可能非常大,所以我有点困惑......

任何指针都非常感谢!

先感谢您。

=================更新===============================

回复:jdehesa,再次感谢。

一些额外的背景:我的意图是对一长串x进行分类,如下所示:

t =     t0  t1  t2  t3  t4  t5  t6  t7  ...
x =   [ [3] [2] [2] [2] [2] [2] [1] [2] [2] [2] [2] [2] ...]
      [ [3] [2] [2] [2] [2] [2] [1] [2] [2] [2] [2] [2] ...]

y =   [ c3  c2  c2  c2  c2  c2  c1  c4  c4  c4  c4  c4  ...]
Note: c1: class 1, c2: class2 c3: class 3, c4: class 4

这篇文章背后的主要困惑是手动分类有一些已知的规则。以上面的虚拟数据为例,假设有规则

  1. 如果前面的特征 x 是第 3 类 ([3, 3]),那么所有后面的 [2, 2] 都将是第 2 类,直到它到达第 1 类。

  2. 如果前面的 x 是 1 类 ([1, 1]),那么所有后面的 [2, 2] 都将是 4 类,直到它达到 3 类。

在这种情况下,如果 LSTM 只看到与 t1 到 t4 相同的 [5 by 2] 特征向量 (x),则网络将完全迷失在分类为 2 类或 4 类。所以我的意思是,不仅那些5 个时间步的特征很重要,前一个时间步的输出/标签也很重要。

所以重申这个问题:如果现在训练集是 t1 到 t5,那么除了 x [batch_size, t1:t5, 2] 之外,如何在 t0 处也包含标签/类 y。

以下是我对您的回答的回复。

考虑我使用 GRU 而不是 LSTM,其中单元输出和单元状态都由“h”表示,如在理解 LSTM中一样。

  1. 关于 initial_state 参数:我刚刚发现 dynamic_rnn 和 static_rnn 正如您指出的那样采用此参数:D。如果我要解决刚才提到的问题,我可以在训练之前使用将之前的类/标签(t0 时的 y)分配给 initial_state 参数,而不是使用 zeros_state。

  2. 我突然觉得我完全迷失了 LSTM 记忆的时间跨度。我一直认为内存的时间跨度仅受 timeStep_size 的限制。如果 timeStep_size = 5,网络最多只能召回 4 步,因为每次训练我们只提供 x 特征向量的 [5 x 2]。如果我错了,请纠正我。

再次,谢谢你

4

1 回答 1

1

LSTM 单元,或一般的 RNN 单元,具有在处理每个时间步后更新的内部状态。显然,你不能无限地回到过去,所以你必须从某个时间点开始。一般约定是从一个全零的单元状态开始;事实上,TensorFlow 中的 RNN 单元有一个zero_state方法可以为每个特定的单元类型和大小返回这种状态。如果你对这个起点不满意(例如,因为你已经处理了一半序列,现在你想处理另一半,在与你相同的状态下继续),你可以将initial_state参数传递给tf.nn.dynamic_rnn.

关于训练,我不确定 LSTM 单元最流行的用法是什么,但这完全取决于你。我处理的问题是每个时间样本都有一个标签,因此我的输出与输入的大小相同。但是,在许多情况下,您只需要整个序列的标签(例如“这句话是正面/负面”),因此您只需查看最后一个输出。无论如何,所有先前的输入当然也很重要,因为它们定义了最后一个单元状态,该状态与最后一个输入结合使用以确定最终输出。举个例子,如果你拿一个像“太酷了,伙计”这样的句子并逐字处理它,最后一个词“男人”可能不会告诉你它本身是一个积极的句子还是消极的句子,这是一个肯定的句子(也就是说,之后需要一个明显的否定输入才能使其产生“否定”输出)。

我不确定你对 t-1 的意思是什么......我的意思是如果你的输入从 t0 开始并且你从未见过 t-1,那么你对此无能为力(例如,如果你只有输入“真的很喜欢这种食物”,但原来整个句子是“不是很喜欢这种食物”,你会完全理解错误的)。但是,如果您确实有输入,那么网络将学会考虑它是否真的很重要。LSTM 细胞的全部意义在于它们能够记住很远的过去(即内部状态下输入的影响可以达到很长的时间跨度)。

更新:

关于您的补充意见。

  • 当然,你可以使用任何你想要的作为输入状态。然而,即使使用 GRU,内部状态通常也不匹配输出标签。通常,您会在循环单元之后使用 sigmoid 或 softmax 激活,这将产生与标签相当的输出。

  • 关于时间跨度。使用具有小时间步长的输入将限制循环单元学习长期依赖关系(在较长序列中查找模式)的能力是正确的。正如我所提到的,如果您在下一次运行中将循环单元的最后状态作为初始状态提供,您可以“模拟”更长的时间步长。但是,无论你是否这样做,LSTM 单元只是“不记得”过去的事情并不准确。即使您以 5 的时间步长进行训练,如果您随后使用大小为 100 的序列运行网络,最后一个输入的输出将(可能)受到所有 99 个先前输入的影响;您根本无法说出它们的影响有多大,因为这是您在培训期间没有遇到的情况。

于 2017-06-02T10:45:29.303 回答