首页 文章

Tensorflow / LSTM机制:如何指定LSTM单元的第一个时间步的先前输出

提问于
浏览
0

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

给定如下所示的结构:A RNN model假设每个节点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) . 当与输出[-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]]

VS:

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

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

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

  • 如果前一个x是1级([1,1]),那么所有后面的[2,2]将是4级,直到达到3级 .

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

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

以下是我对你答案的回应 .

考虑我使用GRU而不是LSTM,其中单元格输出和单元格状态都由"h"表示,如understandign LSTM .

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

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

再次,谢谢你

1 回答

  • 1

    通常,LSTM单元或RNN单元具有在处理每个时间步之后更新的内部状态 . 显然,你无法及时回归,所以你必须从某个时刻开始 . 一般惯例是从一个充满零的单元状态开始;实际上,TensorFlow中的RNN单元具有 zero_state 方法,该方法针对每种特定的单元类型和大小返回这种状态 . 如果你对这个起点不满意(例如,因为你已经处理了半个序列,现在你想要处理另一半,那么你可以选择相同的状态),你可以将 initial_state 参数传递给tf.nn.dynamic_rnn .

    关于培训,我完全取决于你 . 我处理的问题是我每次都有一个标签样本,因此我的输出与输入的大小相同 . 但是,在许多情况下,您只需要整个序列的标签(例如"this sentence is positive/negative"),因此您只需查看最后一个输出 . 无论如何,所有先前的输入当然都很重要,因为它们定义了与最后一个输入组合使用的最后一个单元状态,以确定最终输出 . 例如,如果你采取像"That's cool, man"这样的句子并且逐字处理它,最后一个单词"man"可能不会告诉你很多关于它本身是正面还是负面的句子,但是在这一点上,单元格处于这样一种状态:它确定它是一个正面的句子(也就是说,之后需要一个明显的负面输入才能产生"negative"输出 .

    我不确定你对t-1的意思是什么......我的意思是如果你的输入从t0开始并且你从未见过t-1,你就无法做到这一点(例如,如果你只得到了输入"really like this food"但事实证明整个原始句子是"not really like this food",你只会完全错误) . 但是,如果您确实有输入,那么如果确实很重要,网络将学会将其考虑在内 . LSTM细胞的重点在于它们能够记住过去很远的事物(即内部状态的输入效果可以达到很长的时间 Span ) .

    更新:

    关于您的其他评论 .

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

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

相关问题