Я пытался сделать довольно простую вещь, обучить LSTM, который выбирает последовательность случайных чисел и выводит их сумму. Но через несколько часов, не сходясь, я решил спросить здесь, какое из моих помещений не работает.
Идея проста:
Я генерирую обучающий набор последовательностей некоторой длины последовательности случайных чисел и помечаю их суммой (числа взяты из нормального распределения)
Я использую 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()
гейтов и повторяющихся состояниях, которые подавляли мои результаты и не позволяли им расти, складывая слагаемые. Помещение всех активаций в линейный режим работает довольно хорошо.