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