Обучение LSTM с отслеживанием состояния "многие ко многим" с финальным плотным слоем и без него

Я пытаюсь обучить повторяющуюся модель в Keras, содержащую LSTM, для целей регрессии. Я хотел бы использовать модель в Интернете, и, насколько я понял, мне нужно обучить LSTM с отслеживанием состояния. Поскольку модель должна выводить последовательность значений, я надеюсь, что она вычисляет потери для каждого из ожидаемых выходных векторов. Однако я боюсь, что мой код работает не так, и я был бы признателен, если бы кто-нибудь помог мне понять, правильно ли я поступаю или есть какой-то лучший подход.

Входом в модель является последовательность 128-мерных векторов. Каждая последовательность в обучающем наборе имеет разную длину. Каждый раз модель должна выводить вектор из 3 элементов.

Я пытаюсь обучить и сравнить две модели: A) простой LSTM со 128 входами и 3 выходами; Б) простой LSTM со 128 входами и 100 выходами + плотный слой с 3 выходами;

Для модели A) я написал следующий код:

# Model
model = Sequential()
model.add(LSTM(3, batch_input_shape=(1, None, 128),  return_sequences=True, activation = "linear", stateful = True))`
model.compile(loss='mean_squared_error', optimizer=Adam())

# Training
for i in range(n_epoch):
    for j in np.random.permutation(n_sequences):
        X = data[j] # j-th sequences
        X = X[np.newaxis, ...] # X has size 1 x NTimes x 128

        Y = dataY[j] # Y has size NTimes x 3

        history = model.fit(X, Y, epochs=1, batch_size=1, verbose=0, shuffle=False)
        model.reset_states()

С этим кодом модель A), кажется, хорошо обучается, потому что выходная последовательность приближается к последовательности истинности на обучающем наборе. Однако мне интересно, действительно ли потери вычисляются с учетом всех выходных векторов NTimes.

Для модели B) я не смог найти способ получить всю выходную последовательность из-за плотного слоя. Поэтому я написал:

# Model
model = Sequential()
model.add(LSTM(100, batch_input_shape=(1, None, 128), , stateful = True))
model.add(Dense(3,   activation="linear"))
model.compile(loss='mean_squared_error', optimizer=Adam())

# Training
for i in range(n_epoch):
    for j in np.random.permutation(n_sequences):
        X = data[j]  #j-th sequence
        X = X[np.newaxis, ...] # X has size 1 x NTimes x 128

        Y = dataY[j] # Y has size NTimes x 3

        for h in range(X.shape[1]):
            x = X[0,h,:]
            x = x[np.newaxis, np.newaxis, ...] # h-th vector in j-th sequence
            y = Y[h,:]
            y = y[np.newaxis, ...]
            loss += model.train_on_batch(x,y)
        model.reset_states() #After the end of the sequence

С этим кодом модель B) не тренируется нормально. Мне кажется, что обучение не сходится, а значения потерь циклически увеличиваются и уменьшаются. Я также пытался использовать в качестве Y только последний вектор, и они вызывали функцию соответствия для всей обучающей последовательности X, но без улучшений.

Есть идеи? Спасибо!

1 ответ

Решение

Если вы хотите, чтобы на каждом шаге вашей последовательности по-прежнему было три выхода, вам нужно TimeDistribute вашего слоя Dense следующим образом:

model.add(TimeDistributed(Dense(3, activation="linear")))

Это применяет плотный слой к каждому временному шагу независимо.

См. https://keras.io/layers/wrappers/.

Другие вопросы по тегам