seq2seq - модель вывода дает радикально отличающиеся результаты, чем модель поезда на одном и том же наборе проверки - PullRequest
0 голосов
/ 17 апреля 2020

Я работаю над проблемой sese2seq. Для моего подхода я использую LSTM seq2seq RNN с Teacher Forcing. Как вы уже знаете, для цели задачи модель должна быть обучена, а затем с использованием обученных уровней должна быть построена модель вывода для решения задачи (т. Е. Общие уровни).
Вот мой код для определение общих слоев:

# Define the shared layers for the train and inference models
encoder_lstm = LSTM(latent_dim, return_state=True, name='encoder_lstm')
# Define the shared layers for the train and inference models
encoder_lstm = LSTM(latent_dim, return_state=True, name='encoder_lstm')
decoder_lstm = LSTM(latent_dim, return_sequences=True, 
                    return_state=True, name='decoder_lstm')
decoder_dense = Dense(decoder_output_dim, 
                      activation='linear', name='decoder_dense')
decoder_reshape = Reshape((decoder_output_dim, ), name='decoder_reshape')

Далее я определяю модель поезда, используя общие слои.

# Define an input for the encoder
encoder_inputs = Input(shape=(Tx, encoder_input_dim), name='encoder_input')

# We discard output and keep the states only.
_, h, c = encoder_lstm(encoder_inputs)

# Define an input for the decoder
decoder_inputs = Input(shape=(Ty, decoder_input_dim), name='decoder_input')

# Obtain all the outputs from the decoder (return_sequences = True)
decoder_outputs, _, _  = decoder_lstm(decoder_inputs, initial_state=[h, c])

# Apply dense layer to each output
decoder_outputs = decoder_dense(decoder_outputs)

train_model = Model(inputs=[encoder_inputs, decoder_inputs], outputs=decoder_outputs)

Справедливо упомянуть, что я использую пользовательские потери функция, которая в основном означает Mean Square Error, но я маскирую определенные записи.

def masked_mse(y_true, y_pred):
    return K.mean(
                  K.mean(((y_true[:,:,0] - y_pred[:,:,0])**2)*(1-y_true[:,:,1]),
                         axis=0),
                  axis=0)

После обучения в течение нескольких эпох выходные результаты выглядят примерно так:

Train on 67397 samples, validate on 3389 samples
Epoch 1/10
67397/67397 [==============================] - 36s 536us/sample - loss: 0.1981 - val_loss: 0.0713
Epoch 2/10
67397/67397 [==============================] - 34s 499us/sample - loss: 0.0755 - val_loss: 0.0535
Epoch 3/10
67397/67397 [==============================] - 31s 456us/sample - loss: 0.0633 - val_loss: 0.0494
Epoch 4/10
67397/67397 [==============================] - 29s 429us/sample - loss: 0.0595 - val_loss: 0.0478

loss

Мы заметили, что потери для набора проверки составляют около 0,045 .
Теперь я создаю модель для вывода, полученную из общих слоев выше:

# Define an input for the encoder
encoder_inputs = Input(shape=(Tx, encoder_input_dim), name='encoder_input')

# We discard output and keep the states only.
_, h, c = encoder_lstm(encoder_inputs)

# Define an input for the decoder
decoder_input = Input(shape=(1, decoder_input_dim), name='decoder_input')
current_input = decoder_input

# Obtain the outputs for each of the Ty timesteps
decoder_outputs = []
for _ in range(Ty):
    # apply a single step of recurrence
    out, h, c = decoder_lstm(current_input, initial_state=[h, c])

    # pass the LSTM output through a dense layer
    out = decoder_dense(out)

    # The input in the next timestep (its shape is (?, 1, 1))
    current_input = out

    # reshape the decoder output as (?, 1) for convenience
    out = decoder_reshape(out)

    # append the output to the model's outputs
    decoder_outputs.append(out)

inference_model = Model(inputs=[encoder_inputs, decoder_input], outputs=decoder_outputs)

Используя эту модель вывода, я пытаюсь чтобы оценить его на том же проверочном наборе, который я использовал во время обучения, чтобы воссоздать последние результаты:

# The input for the first timestep in the decoder is -1,
# (consistently, the same was applied during training)
decoder_input = -1 * np.ones((len(X_valid), 1, 1))

# Obtain the predictions, the resulting shape is (Ty, ?, 1)
y_pred = np.array(inference_model.predict([X_valid, decoder_input]))

# Reshape the output in the shape (?, Ty, 1)
y_pred = np.swapaxes(y_pred, axis1=0, axis2=1)

loss = masked_mse(K.constant(y_valid), K.constant(y_pred))
K.eval(loss)

Результат оценки потери: 0.1637 . Продолжил тренировку и никогда не опускался ниже 0,14.

Это очень странно, поскольку я использую тот же набор проверки для оценки. Я подозреваю, что ошибка, вероятно, где-то в том, как строится модель логического вывода, однако я не уверен.
Что вы думаете?

1 Ответ

0 голосов
/ 17 апреля 2020

Если ваша модель вывода не отличается от обученной модели, вам не нужно ничего копировать. Вы можете использовать train_model.predict(...) непосредственно в существующей модели.

Копирование слоев важно, если вы выполняете несколько этапов обучения, например, в обучении с переносом, но для вывода не требуется использовать обученную модель.


Но, возвращаясь к вашему обычному l oop, ваше повторение LSTM должно произойти до применения слоя Dense.

decoder_outputs = []
for _ in range(Ty):
    out, h, c = decoder_lstm(current_input, initial_state=[h, c])

    # This line moved to before the decoder_dense call.
    current_input = out

    out = decoder_dense(out)
    out = decoder_reshape(out)
    decoder_outputs.append(out)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...