首页 > 解决方案 > 带有 TimeSeriesGenerator 的 Keras LSTM 自定义数据生成器

问题描述

所以我正在尝试使用 Keras 的fit_generator和自定义数据生成器来输入 LSTM 网络。

什么有效

为了说明这个问题,我创建了一个玩具示例,试图以简单的升序预测下一个数字,并使用Keras TimeseriesGenerator创建一个 Sequence 实例:

WINDOW_LENGTH = 4
data = np.arange(0,100).reshape(-1,1)
data_gen = TimeseriesGenerator(data, data, length=WINDOW_LENGTH,
                               sampling_rate=1, batch_size=1)

我使用一个简单的 LSTM 网络:

data_dim = 1
input1 = Input(shape=(WINDOW_LENGTH, data_dim))
lstm1 = LSTM(100)(input1)
hidden = Dense(20, activation='relu')(lstm1)
output = Dense(data_dim, activation='linear')(hidden)

model = Model(inputs=input1, outputs=output)
model.compile(loss='mse', optimizer='rmsprop', metrics=['accuracy'])

并使用以下fit_generator功能对其进行训练:

model.fit_generator(generator=data_gen,
                    steps_per_epoch=32,
                    epochs=10)

这可以完美地训练,并且模型会按预期进行预测。

问题

现在的问题是,在我的非玩具情况下,我想在将数据输入fit_generator. 作为实现这一目标的一步,我创建了一个生成器函数,它只包装了之前使用的 TimeseriesGenerator。

def get_generator(data, targets, window_length = 5, batch_size = 32):
    while True:
        data_gen = TimeseriesGenerator(data, targets, length=window_length, 
                                       sampling_rate=1, batch_size=batch_size)
        for i in range(len(data_gen)):
            x, y = data_gen[i]
            yield x, y

data_gen_custom = get_generator(data, data,
                                window_length=WINDOW_LENGTH, batch_size=1)

但现在奇怪的是,当我像以前一样训练模型,但是使用这个生成器作为输入时,

model.fit_generator(generator=data_gen_custom,
                    steps_per_epoch=32,
                    epochs=10)

没有错误,但训练错误到处都是(上下跳跃而不是像其他方法那样持续下降),并且模型没有学会做出良好的预测。

任何想法我的自定义生成器方法做错了什么?

标签: pythonkeraslstm

解决方案


这可能是因为对象类型从SequenceaTimeseriesGenerator变成了泛型生成器。该fit_generator函数以不同的方式处理这些。一个更干净的解决方案是继承类并覆盖处理位:

class CustomGen(TimeseriesGenerator):
  def __getitem__(self, idx):
    x, y = super()[idx]
    # do processing here
    return x, y

并且像以前一样使用这个类,因为其余的内部逻辑将保持不变。


推荐阅读