LSTM не учится добавлять случайные числа - PullRequest
1 голос
/ 01 мая 2019

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

Идея проста:

  1. Я генерирую обучающий набор последовательностей некоторой длины последовательности случайных чисел и помечаю их суммой (числа взяты из нормального распределения)

  2. Я использую LSTM с RMSE-потерями для прогнозирования выходных данных, суммы этих чисел с учетом последовательности ввода

Интуитивно LSTM должен научиться устанавливать вес входного вентиля равным 1 (смещение 0), вес шлюза забывания равным 0 (смещение 1) и вес выходного вентиля равным 1 (смещение 0) и учиться добавить эти цифры, но это не так. Вставляя код, который я использую, я пробовал с разными скоростями обучения, оптимизаторами, пакетированием, наблюдал за градиентами и выходными данными и не нашел точную причину, по которой происходит сбой.

Код для генерации последовательностей:

import tensorflow as tf
import numpy as np

tf.enable_eager_execution()

def generate_sequences(n_samples, seq_len):
    total_shape = n_samples*seq_len
    random_values = np.random.randn(total_shape)
    random_values = random_values.reshape(n_samples, -1)
    targets = np.sum(random_values, axis=1)
    return random_values, targets

Код для обучения:

n_samples = 100000
seq_len = 2
lr=0.1
epochs = n_samples
batch_size = 1
input_shape = 1

data, targets = generate_sequences(n_samples, seq_len)
train_data = tf.data.Dataset.from_tensor_slices((data, targets))
output = tf.keras.layers.RNN(tf.keras.layers.LSTMCell(1, dtype='float64', recurrent_activation=None, activation=None), input_shape=(batch_size, seq_len, input_shape))
iterator = train_data.batch(batch_size).make_one_shot_iterator()
optimizer = tf.train.AdamOptimizer(lr)

for i in range(epochs):
    my_inp, target = iterator.get_next()
    with tf.GradientTape(persistent=True) as tape:
        tape.watch(my_inp)
        my_out = output(tf.reshape(my_inp, shape=(batch_size,seq_len,1)))
        loss = tf.sqrt(tf.reduce_sum(tf.square(target - my_out)),1)/batch_size

    grads = tape.gradient(loss, output.trainable_variables)
    optimizer.apply_gradients(zip(grads, output.trainable_variables),
                                global_step=tf.train.get_or_create_global_step())

У меня также есть предположение, что это теоретическая проблема (если мы суммируем различные случайные значения, полученные из нормального распределения, то выходной сигнал не находится в диапазоне [-1, 1], и LSTM из-за активаций tanh не может изучите его, но изменение их не улучшит производительность (в примере кода изменено на линейное).

EDIT:

Установив активацию на линейную, я понял, что tanh() сдавливает значения.

РЕШИТЬ:

На самом деле проблема заключалась в tanh() гейтов и повторяющихся состояниях, которые подавляли мои результаты и не позволяли им расти, складывая слагаемые. Помещение всех активаций в линейный режим работает довольно хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...