【问题标题】:Varying sequence length in Keras without padding在没有填充的情况下改变 Keras 中的序列长度
【发布时间】:2017-12-06 00:04:42
【问题描述】:

我有一个关于 Keras 中 LSTM 的不同序列长度的问题。我将大小为 200 的批次和具有 100 个特征的序列中每个对象的可变长度 (= x) 序列 (=> [200, x, 100]) 传递到 LSTM:

LSTM(100, return_sequences=True, stateful=True, input_shape=(None, 100), batch_input_shape=(200, None, 100))

我在以下随机创建的矩阵上拟合模型:

x_train = np.random.random((1000, 50, 100))
x_train_2 = np.random.random((1000, 10,100))

就我正确理解 LSTM(和 Keras 实现)而言,x 应该指的是 LSTM 单元的数量。对于每个 LSTM 单元,必须学习一个状态和三个矩阵(用于单元的输入、状态和输出)。如何在不填充到最大值的情况下将不同的序列长度传递到 LSTM 中。指定长度,像我一样?代码正在运行,但实际上不应该(在我的理解中)。 之后甚至可以传递另一个序列长度为 60 的 x_train_3,但不应该有额外的 10 个单元格的状态和矩阵。

顺便说一下,我使用的是 Keras 版本 1.0.8 和 Tensorflow GPU 0.9。

这是我的示例代码:

from keras.models import Sequential
from keras.layers import LSTM, Dense
import numpy as np
from keras import backend as K

with K.get_session():

    # create model
    model = Sequential()
    model.add(LSTM(100, return_sequences=True, stateful=True, input_shape=(None, 100),
             batch_input_shape=(200, None, 100)))
    model.add(LSTM(100))
    model.add(Dense(2, activation='softmax'))
    model.compile(loss='categorical_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])

    # Generate dummy training data
    x_train = np.random.random((1000, 50, 100))
    x_train_2 = np.random.random((1000, 10, 100))
    y_train = np.random.random((1000, 2))
    y_train_2 = np.random.random((1000, 2))

    # Generate dummy validation data
    x_val = np.random.random((200, 50, 100))
    y_val = np.random.random((200, 2))

    # fit and eval models
    model.fit(x_train, y_train, batch_size=200, nb_epoch=1, shuffle=False, validation_data=(x_val, y_val), verbose=1)
    model.fit(x_train_2, y_train_2, batch_size=200, nb_epoch=1, shuffle=False, validation_data=(x_val, y_val), verbose=1)
    score = model.evaluate(x_val, y_val, batch_size=200, verbose=1)

【问题讨论】:

    标签: sequence keras padding lstm recurrent-neural-network


    【解决方案1】:

    首先:您似乎不需要stateful=Truebatch_input。这些适用于当您想要将一个非常长的序列分成几部分并单独训练每个部分时,模型不会认为该序列已经结束。

    当您使用有状态层时,当您决定某个批次是长序列的最后一部分时,您必须手动重置/擦除状态/内存。

    您似乎正在处理整个序列。不需要有状态的。

    填充并不是绝对必要的,但您似乎可以使用填充 + 遮罩来忽略额外的步骤。如果您不想使用填充,则可以将数据分成较小的批次,每个批次具有不同的序列长度。看到这个:Keras misinterprets training data shape

    序列长度(时间步长)不会改变细胞/单元的数量或权重。可以使用不同的长度进行训练。不能改变的维度是特征的数量。


    输入尺寸:

    输入维度为(NumberOfSequences, Length, Features)
    输入形状和单元格数量之间绝对没有关系。它只携带步数或递归数,即Length 维度。

    细胞:

    LSTM 层中的单元的行为与密集层中的“单元”完全一样。

    一个单元格不是一个步骤。一个单元格只是“并行”操作的数量。每组单元一起执行循环操作和步骤。

    细胞之间有对话,正如@Yu-Yang 在 cmets 中所注意到的那样。但是它们是通过步骤继承的同一实体的想法仍然有效。

    您在图像中看到的那些小块,例如this,不是单元格,而是步骤。

    可变长度:

    也就是说,序列的长度根本不会影响 LSTM 层中的参数(矩阵)的数量。它只会影响步数。

    层内固定数量的矩阵对于长序列将被重新计算更多次,而对于短序列则更少。但在所有情况下,它都是一个获取更新并传递到下一步的矩阵。

    序列长度仅因更新次数而异。

    图层定义:

    细胞的数量可以是任意数量,它只会定义有多少并行的迷你大脑将一起工作(这意味着或多或少强大的网络,以及或多或少的输出功能)。

    LSTM(units=78) 
    #will work perfectly well, and will output 78 "features".
    #although it will be less intelligent than one with 100 units, outputting 100 features.    
    

    有一个独特的权重矩阵和一个独特的状态/记忆矩阵,不断向前传递到下一步。这些矩阵只是在每一步中“更新”,但每一步都没有一个矩阵。

    图片示例:

    每个框“A”都是使用和更新同一组矩阵(状态、权重...)的步骤。

    不是 4 个单元,而是一个相同的单元执行 4 次更新,每个输入更新一次。

    每个 X1、X2、... 都是长度维度上序列的一个片段。


    与较短的序列相比,较长的序列将重用和更新矩阵的次数更多。但它仍然是一个单元格。


    单元格的数量确实会影响矩阵的大小,但不取决于序列长度。所有单元格将并行工作,并在它们之间进行一些对话。


    你的模型

    在您的模型中,您可以像这样创建 LSTM 层:

    model.add(LSTM(anyNumber, return_sequences=True, input_shape=(None, 100)))
    model.add(LSTM(anyOtherNumber))
    

    通过像这样在input_shape 中使用None,您已经告诉您的模型它接受任何长度的序列。

    你所要做的就是训练。而且您的培训代码还可以。 唯一不允许的是在内部创建具有不同长度的批次。因此,正如您所做的那样,为每个长度创建一个批次并训练每个批次。

    【讨论】:

    • 您描述的“细胞”有任何参考吗?我从未见过这样描述 LSTM。另外,LSTM(cells=78) 绝对行不通。函数调用中没有这样的关键字。通过“78 个功能”,也许你在谈论units
    • 如果“cells”实际上是指“units”(如在某些论文中所见),那么通常不会说“具有 2 个 cell 的 LSTM 层,它们并行工作”之类的东西。 “每个单元执行自己的循环操作和步骤,每个单元都有自己的权重和状态”这句话也完全没有意义。
    • LSTM(78) 层中,没有 78 个流并行运行。时间步长中的 78 个单位 t+1 将取决于所有 78 个时间单位 t
    • 感谢LSTM的详细解释。最初的问题是询问 Keras 以及如何避免使用 LSTM() 进行填充。我认为展示涉及LSTM(...) 的两行应该是什么样子会很有帮助。
    • 您可以使用这个答案将一个批次分成许多批次,每个批次都有唯一的长度:stackoverflow.com/questions/46144191/…
    猜你喜欢
    • 2013-03-01
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多