Как изменить входные данные для предсказания последовательности в последовательности LSTM в TensorFlow 2.0? - PullRequest
0 голосов
/ 04 февраля 2020

Я новичок в машинном обучении и не могу понять, как дать LSTM последовательный ввод в TensorFlow. Я хочу, чтобы сеть могла прогнозировать временные ряды, изучая правило обновления, которое продвигает динамическую систему за один шаг во времени. Я сделал это успешно в MATLAB (я думаю), используя DNN и LSTM. Я приложил образец моих данных ниже, и полный файл данных вместе с кодом можно найти здесь https://drive.google.com/open?id=1W-9yJoVSJI2BRi27NPSnoFfZtgHP3YkK. По сути, мои данные выглядят так:

enter image description here

У меня есть входная последовательность из 3 объектов, и выходная последовательность такая же, как и входная последовательность сдвинут на один. Таким образом, для каждого входа, выход является следующей последовательностью и так далее. Я хочу дать обученной сети начальное условие (один вход последовательности), в которое она возвращает выход одной последовательности, затем этот выход используется в качестве начального условия для следующего прогноза и т. Д. (Не требуется многократных шагов или просмотра назад) , Я использую код MATLAB LSTM:

close all
clc

nnet.guis.closeAllViews()
a=load('Rossler Attractor.csv');

t_sample=1000;
Test_sample=10000;
Input=a(1:t_sample-1,2:end);
Output=a(2:t_sample,2:end);
IC=a(1,2:end);

Input = Input.';
Output = Output.';
IC = IC.';

numFeatures = 3;
numHiddenUnits = 60;
numResponses = 3;
layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %1
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %2
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %3
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %4
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %5
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %6
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %7
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %8
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %9
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %10
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %11
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %12
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %13
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %14
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %15
    dropoutLayer(0.01)
    lstmLayer(numHiddenUnits,'OutputMode','sequence') %16
    dropoutLayer(0.01)
    fullyConnectedLayer(numResponses)
    regressionLayer];
options = trainingOptions('adam', 'MaxEpochs', 1500, 'Verbose', 0, 'Plots', 'training-progress');
net = trainNetwork(Input,Output,layers,options);
LSTM_POD_network = net;
save LSTM_POD_network

%%

ynn=[];
ynn(1,:)=IC;
for jj=2:Test_sample
[net, y0]=predictAndUpdateState(net, IC);
ynn(jj,:)=y0.'; IC=y0;
end
dlmwrite('Predictions.csv', ynn, 'delimiter', ',', 'precision', 12)

Я пытался сделать то же самое в TensorFlow, но не могу этого сделать. Я не могу понять, как изменить входные данные в соответствии с моими потребностями. Код, который я написал в python:

import os
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib as mpl
from tensorflow import keras
import matplotlib.pyplot as plt

mpl.rcParams['figure.figsize'] = (8, 6)
mpl.rcParams['axes.grid'] = False

column_names = ['Time', 'X(t)', 'Y(t)', 'Z(t)']     
dataset = pd.read_csv('Rossler Attractor.csv', names=column_names, skipinitialspace=True)
print('\nData Set:\n', dataset.head())

train_sample = 10000
test_sample = 12000
Input = dataset.iloc[0:train_sample, 1:4].values
Output = dataset.iloc[1:train_sample+1, 1:4].values
IC = dataset.iloc[0, 1:4].values

Features = 3  #input sequence
Responses = 3 #output sequence
Timesteps = 1 #use one previous value to predict next value
Samples = Input.shape[0] - Timesteps

Input_reshaped = np.zeros((Samples, Timesteps, Features))
Output_reshaped = np.zeros((Samples, Timesteps, Features))
IC_reshaped = np.zeros((Samples, Timesteps, Features))

for i in range(Samples):
    y_position = i + Timesteps
    Input_reshaped[i] = Input[i:y_position]
    Output_reshaped[i] = Output[i:y_position]
    IC_reshaped[i] = IC[i:y_position]

Input = Input_reshaped
Output = Output_reshaped
IC = IC_reshaped

print('\nInput:\n', Input)
print('\nOutput:\n', Output)
print('\nInitial Condition:\n', IC)
print('\nInput Shape: ', Input.shape)

Hidden_Units = 60
tf.random.set_seed(13)

def plot_train_history(history, title):
  loss = history.history['loss']
  val_loss = history.history['val_loss']

  epochs = range(len(loss))

  plt.figure()

  plt.plot(epochs, loss, 'b', label='Training loss')
  plt.plot(epochs, val_loss, 'r', label='Validation loss')
  plt.title(title)
  plt.legend()

  plt.show()

class PrintDot(keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs):
    if epoch % 100 == 0: print('')
    print('.', end='')

def build_model():
  model = tf.keras.models.Sequential([
    tf.keras.layers.SimpleRNN(Features, return_sequences=True, activation='tanh', input_shape=(Timesteps, Features)),
    tf.keras.layers.LSTM(Hidden_Units, return_sequences=True, activation='tanh'), #1
    tf.keras.layers.Dropout(rate=0.01),
    tf.keras.layers.LSTM(Hidden_Units, return_sequences=True, activation='tanh'), #2
    tf.keras.layers.Dropout(rate=0.01),
    tf.keras.layers.Dense(Responses, activation='softmax')
  ])

  optimizer = tf.keras.optimizers.Adam(0.001)

  model.compile(loss='mse', optimizer=optimizer, metrics=['mae', 'mse', 'accuracy'])
  return model

model = build_model()
model.summary()

EPOCHS = 5
PATIENCE = EPOCHS*0.1
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=5)
history = model.fit(Input, Output, epochs=EPOCHS, validation_split = 0.01, verbose=1, callbacks=[early_stop, PrintDot()])
model.save("model.h5")

plot_train_history(history, 'Training & Validation Loss')

ynn = IC.values

for jj in range(1, test_sample):
    y0 = model.predict(IC)
    ynn = np.vstack((ynn, y0))
    IC = y0

np.savetxt("Rossler_Predictions.csv", ynn, delimiter=",")

Я попытался изменить форму, как было предложено другим пользователем в одном ответе (как видно из кода), но это дает мне ошибку, говорящую ValueError : не удалось передать входной массив из shape (0) в shape (1,3) . Без изменения, он говорит мне, что ожидал ввода другой формы. Я понимаю, что мне нужно изменить свой вклад. Как мне преобразовать мои данные в 3D для работы LSTM? И будет ли мой прогноз l oop работать так, как задумано?

Дополнительный вопрос: существует ли TensorFlow-эквивалент sequenceInputLayer из MATLAB? А как насчет последнего регрессионного слоя? Любая помощь приветствуется.

Редактировать

Я смог заставить ее работать, используя следующий код и изменяя форму данных. Тем не менее, результаты MATLAB гораздо более многообещающие и превосходят результаты Keras. Я не знаю, почему это так, может быть, MATLAB не делает то, что я думаю, и я запрограммировал это неправильно. Кто-нибудь знает, как улучшить результаты с python? Кроме того, сколько шагов назад выполняет MATLAB, потому что я не указал их. Matlab использует LSTM с отслеживанием состояния?

column_names = ['Time', 'X(t)', 'Y(t)', 'Z(t)']     
dataset = pd.read_csv('Down5_Rossler.csv', names=column_names, skipinitialspace=True)
print('\nData Set:\n', dataset.head())
dataset = dataset.values

train_sample = 2000
test_sample = 2400

Features = 3
Responses = 3
Timesteps = 5

def create_dataset(dataset, look_back=1):
    Input, Output = [], []

    for i in range (len(dataset) - look_back):
        Input.append(dataset[i:(i + look_back), 1:(Features + 1)])
        Output.append(dataset[i + look_back, 1:Features + 1])
    return np.array(Input), np.array(Output)

IC = dataset[0:Timesteps, 1:(Features + 1)]
a = dataset[0:train_sample, 1:(Features + 1)]
IC = np.reshape(IC, (1, Timesteps, Features))

Input, Output = create_dataset(dataset, Timesteps)
Input = np.reshape(Input, (Input.shape[0], Timesteps, Features))
Output = np.reshape(Output, (Output.shape[0], 1, Features))

Это лучший результат, полученный мной python. Best python results I got.

MATLAB точно соответствует исходным данным, как показано на рисунке ниже. MATLAB predicts the training data exactly.

...