Сеть Keras производит обратные прогнозы - PullRequest
0 голосов
/ 15 января 2019

У меня есть набор данных временных рядов, и я пытаюсь обучить сеть так, чтобы она соответствовала (очевидно, это всего лишь первый шаг, тогда я буду бороться с переобучением).

Сеть имеет два уровня: LSTM (32 нейрона) и Dense (1 нейрон, без активации)

Обучение / модель имеет следующие параметры: epochs: 20, steps_per_epoch: 100, loss: "mse", optimizer: "rmsprop".

TimeseriesGenerator производит входные серии с: length: 1, sampling_rate: 1, batch_size: 1.

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

y_pred = model.predict_generator(gen)
plot_points = 40
epochs = range(1, plot_points + 1)
pred_points = numpy.resize(y_pred[:plot_points], (plot_points,))
target_points = gen.targets[:plot_points]
plt.plot(epochs, pred_points, 'b', label='Predictions')
plt.plot(epochs, target_points, 'r', label='Targets')
plt.legend()
plt.show()

Я получаю:

predictions and targets chart

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

РЕДАКТИРОВАТЬ (некоторые соответствующие части моего кода):

train_gen = keras.preprocessing.sequence.TimeseriesGenerator(
        x,
        y,
        length=1,
        sampling_rate=1,
        batch_size=1,
        shuffle=False
    )

model = Sequential()
model.add(LSTM(32, input_shape=(1, 1), return_sequences=False))
model.add(Dense(1, input_shape=(1, 1)))

model.compile(
    loss="mse",
    optimizer="rmsprop",
    metrics=[keras.metrics.mean_squared_error]
)

history = model.fit_generator(
    train_gen,
    epochs=20,
    steps_per_epoch=100
)

РЕДАКТИРОВАТЬ (другой, случайно сгенерированный набор данных):

enter image description here

Мне пришлось увеличить количество нейронов LSTM до 256, при предыдущей настройке (32 нейрона) синяя линия была почти плоской. Однако с увеличением возникает та же закономерность - обратные прогнозы с несколько меньшей амплитудой .

РЕДАКТИРОВАТЬ (цели смещены на +1):

enter image description here

Смещение целей на единицу по сравнению с предсказаниями не дает намного лучшей подгонки. Обратите внимание на выделенные части, где график не просто чередуется, он более заметен.

РЕДАКТИРОВАТЬ (увеличенная длина до 2 ... TimeseriesGenerator(length=2, ...)):

enter image description here

С length=2 предсказания перестают так близко отслеживать цели, но общая картина инверсии все еще сохраняется.

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Вы говорите, что ваша сеть «только что научилась сводить на нет входное значение и немного уменьшать его». Я так не думаю. Весьма вероятно, что все, что вы видите, это то, что сеть работает плохо и просто предсказывает предыдущее значение (но масштабируется, как вы говорите). Этот вопрос я видел снова и снова. Вот еще один пример и еще один этой проблемы. Кроме того, помните, что очень легко обмануть себя, сдвигая данные на единицу. Весьма вероятно, что вы просто сдвинули неверный прогноз во времени и получили дублирование.

0 голосов
/ 19 января 2019

РЕДАКТИРОВАТЬ: После комментариев автора я не верю, что это правильный ответ, но я буду держать его в курсе для потомков.

Отличный вопрос, и ответ связан с тем, как работает Time_generator! Очевидно, вместо того, чтобы захватывать пары x, y с одинаковым индексом (например, ввод x[0] для вывода цели y[0]), она захватывает цель со смещением 1 (так что от x[0] до y[1]).

Таким образом, построение графика y со смещением 1 даст желаемую подгонку.

Код для симуляции:

import keras 
import matplotlib.pyplot as plt

x=np.random.uniform(0,10,size=41).reshape(-1,1)
x[::2]*=-1
y=x[1:]
x=x[:-1]
train_gen = keras.preprocessing.sequence.TimeseriesGenerator(
        x,
        y,
        length=1,
        sampling_rate=1,
        batch_size=1,
        shuffle=False
    )

model = keras.models.Sequential()
model.add(keras.layers.LSTM(100, input_shape=(1, 1), return_sequences=False))
model.add(keras.layers.Dense(1))


model.compile(
    loss="mse",
    optimizer="rmsprop",
    metrics=[keras.metrics.mean_squared_error]
)
model.optimizer.lr/=.1

history = model.fit_generator(
    train_gen,
    epochs=20,
    steps_per_epoch=100
)

Правильная прорисовка:

y_pred = model.predict_generator(train_gen)
plot_points = 39
epochs = range(1, plot_points + 1)
pred_points = np.resize(y_pred[:plot_points], (plot_points,))

target_points = train_gen.targets[1:plot_points+1] #NOTICE DIFFERENT INDEXING HERE

plt.plot(epochs, pred_points, 'b', label='Predictions')
plt.plot(epochs, target_points, 'r', label='Targets')
plt.legend()
plt.show()

Вывод, обратите внимание, что подгонка больше не инвертируется и в основном очень точная:

imagetarget_points">

Вот как это выглядит при неправильном смещении:

Without proper offset

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