使用Keras在RNN中进行多特征序列填充和掩蔽

时间:2018-08-07 06:32:20

标签: keras padding lstm masking

我已经使用Keras构建了LSTM体系结构,但是我不确定重复时间步长是否是处理可变序列长度的好方法。

我有一个多维数据集,具有多个功能序列和不同的时间步长。它是一个多元时间序列数据,带有多个用于训练LSTM的示例,Y为0或1。目前,我正在为每个序列复制最后一个时间步,以确保timesteps = 3

我很高兴有人可以回答以下问题或疑虑: 1.以零表示的特征值创建其他时间步是否更合适?
2.构造此问题,填充顺序和用于评估的蒙版的正确方法是什么。
3.我也在复制Y变量中的最后一个时间步以进行预测,并且Y中的值1仅出现在最后一个时间步中。

# The input sequences are
trainX = np.array([
        [
            # Input features at timestep 1
            [1, 2, 3],
            # Input features at timestep 2
            [5, 2, 3] #<------ duplicate this to ensure compliance
        ],
        # Datapoint 2
        [
            # Features at timestep 1
            [1, 8, 9],
            # Features at timestep 2
            [9, 8, 9],
            # Features at timestep 3
            [7, 6, 1]
        ]
    ])

# The desired model outputs is as follows:
trainY = np.array([
        # Datapoint 1
        [
            # Target class at timestep 1
            [0],
            # Target class at timestep 2
            [1] #<---------- duplicate this to ensure compliance
        ],
        # Datapoint 2
        [
            # Target class at timestep 1
            [0],
            # Target class at timestep 2
            [0]
            # Target class at time step 3
            [0]
        ]
    ])

timesteps = 3
model = Sequential()
model.add(LSTM(3, kernel_initializer ='uniform', return_sequences=True, batch_input_shape=(None, timesteps, trainX.shape[2]), 
               kernel_constraint=maxnorm(3), name='LSTM'))
model.add(Dropout(0.2))
model.add(LSTM(3, return_sequences=True, kernel_constraint=maxnorm(3), name='LSTM-2'))
model.add(Flatten(name='Flatten'))
model.add(Dense(timesteps, activation='sigmoid', name='Dense'))
model.compile(loss="mse", optimizer="sgd", metrics=["mse"])
model.fit(trainX, trainY, epochs=2000, batch_size=2)
predY = model.predict(testX)

1 个答案:

答案 0 :(得分:2)

我认为您的问题有两种解决方案。 (没有重复的时间步):

  1. pad_sequence layermasking layer结合使用。这是常见的方法。现在,由于填充,每个样本都具有相同数量的时间步长。这种方法的好处是,它很容易实现。此外,Masking层将为您带来一点性能提升。 这种方法的缺点:如果在GPU上进行训练,则CuDNNLSTM是要使用的层,它针对gpu进行了高度优化,因此速度要快得多。但这不适用于遮罩层,并且如果您的数据集具有较大的时间步长,那么您将失去性能。

  2. 将timesteps-shape设置为None并编写一个keras生成器,该生成器将按时间步长对批次进行分组。(我认为您还必须使用功能性api)现在您可以实现CuDNNLSTM,每个示例都将仅使用相关的时间步长(而不是填充的时间步长)进行计算,效率更高。

如果您不熟悉keras,而性能并不那么重要,请选择方法1。如果您的生产环境经常需要培训网络并且与成本相关,请尝试方法2。