LSTM如何处理变长序列

2024-04-28 03:22:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我在deep Deep Learning with Python的第7章第1节中发现了一段代码,如下所示:

from keras.models import Model
from keras import layers
from keras import Input

text_vocabulary_size = 10000
question_vocabulary_size = 10000
answer_vocabulary_size = 500

# Our text input is a variable-length sequence of integers.
# Note that we can optionally name our inputs!
text_input = Input(shape=(None,), dtype='int32', name='text')

# Which we embed into a sequence of vectors of size 64
embedded_text = layers.Embedding(64, text_vocabulary_size)(text_input)

# Which we encoded in a single vector via a LSTM
encoded_text = layers.LSTM(32)(embedded_text)

# Same process (with different layer instances) for the question
question_input = Input(shape=(None,), dtype='int32', name='question')
embedded_question = layers.Embedding(32, question_vocabulary_size)(question_input)
encoded_question = layers.LSTM(16)(embedded_question)

# We then concatenate the encoded question and encoded text
concatenated = layers.concatenate([encoded_text, encoded_question], axis=-1)

# And we add a softmax classifier on top
answer = layers.Dense(answer_vocabulary_size, activation='softmax')(concatenated)

# At model instantiation, we specify the two inputs and the output:
model = Model([text_input, question_input], answer)
model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['acc'])

当你看到这个模型的输入没有原始数据的形状信息,那么在嵌入层之后,LSTM的输入或嵌入的输出都是一些可变长度的序列。在

model_summary

所以我想知道:

  • 在这个模型中,keras如何确定lstm层中lstm_单元的个数
  • 如何处理变长序列

附加信息:为了解释什么是lstm_单元(我不知道如何称呼它,所以只需展示图片):

lstm_unit


Tags: thetextanswerfromimportinputsizelayers
2条回答

提供的递归层继承自基本实现keras.layers.Recurrent,其中包括选项return_sequences,默认为False。这意味着,在默认情况下,递归层将消耗可变长度的输入,并最终在最后一个连续步骤中仅生成层的输出。在

因此,使用None来指定可变长度的输入序列维度是没有问题的。在

但是,如果希望层返回输出的完整序列,即输入序列每一步的输出张量,则必须进一步处理输出的可变大小。在

你可以通过让下一层进一步接受一个可变大小的输入来实现这一点,然后在你的网络中讨论这个问题,直到后来你必须从一些可变长度的东西中计算出一个损失函数,或者在继续到后面的层之前计算一些固定长度的表示,这取决于你的模型。在

或者你可以通过要求固定长度的序列来实现,可能是用特殊的sentinel值填充序列的末尾,这些值仅仅表示一个空的序列项,纯粹是为了填充长度。在

另外,Embedding层是一个非常特殊的层,也是用来处理可变长度输入的。对于输入序列的每个标记,输出形状将具有不同的嵌入向量,因此形状具有be(批大小、序列长度、嵌入维数)。因为下一层是LSTM,所以这没问题。。。它也很乐意使用可变长度的序列。在

但正如Embedding上的文档所述:

input_length: Length of input sequences, when it is constant.
      This argument is required if you are going to connect
      `Flatten` then `Dense` layers upstream
      (without it, the shape of the dense outputs cannot be computed).

如果要直接从Embedding转换为非可变长度表示,则必须提供固定的序列长度作为层的一部分。在

最后,请注意,当您表示LSTM层的维度时,例如LSTM(32),您描述的是该层的输出空间的维度。在

^{pr2}$

为了避免批大小为1的低效率,一种策略是根据每个示例的序列长度对输入的训练数据进行排序,然后根据公共序列长度分组,例如使用定制的Keras数据生成器。在

这有允许大批量的优点,特别是如果您的模型可能需要批处理规范化之类的东西或涉及GPU密集型培训,甚至只是为了减少批量更新梯度的噪声估计。但它仍然允许您处理输入训练数据集,该数据集对于不同的示例具有不同的批处理长度。在

但更重要的是,它还有一个很大的优势,即不必管理任何填充,以确保输入中的公共序列长度。在

如何处理单位?

单位是完全独立的长度,所以,没有什么特别的是做。在

长度只会增加“重复步骤”,但重复步骤总是反复使用相同的细胞。在

单元格的数量由用户确定和定义:

  • 第一个LSTM有32个单元/单元
  • 第二个LSTM有16个单元/单元

如何处理可变长度?

  • 方法1:创建一个序列的单独批次,每个批次都有自己的长度。将每一批单独送入模型。方法train_on_batch和{}是最简单的形式。
    • 理想情况下,按长度分开批,每个批收集长度相同的所有序列
  • 方法2:创建一个固定长度的批处理,用0填充每个序列未使用的尾部长度,在嵌入层中使用参数mask_zero=True
    • 注意不要在嵌入的输入中将0用作实际的单词或有意义的数据。在

相关问题 更多 >