Home > Software engineering >  LSTM model has poor prediction in simple example
LSTM model has poor prediction in simple example

Time:07-29

I am trying to generate a LSTM model using Keras. I create a simple sine wave example which contain more thang 1000 point to predict the next point. But the result is not good as i expected. When i fit the model the result is moves between 0~1 not like the sine wave. I have tried to change parameter like epoch, batchsize, learning rate, but it is not better.

model predict image

What am I doing wrong?

import joblib
import numpy as np
import matplotlib.pyplot as plt
import copy
import gc
import os
import sys
from sklearn.preprocessing import MinMaxScaler
from tensorflow import keras
import tensorflow as tf
from tensorflow.keras.models import *
from tensorflow.keras.layers import *
from keras.callbacks import Callback

learning_rate = 0.001
len_train = 30
total_predict = 300
len_test = 400 
epoch = 100
batch_size = 32
workers = -1

class Callback_Class(Callback):
    def load_data(self, x_test, y_test):
        self.x_test = x_test
        self.y_test = np.array(y_test)
    def model_predict(self, data_close):
        output_predict = []
        for i in range(total_predict):
            if (i==0):
                data_close_ = data_close.reshape(-1, len_train, 1)
            else:
                data_close_ = np.delete(data_close_, 0)
                data_close_ = np.append(data_close_, pred_close)
                data_close_ = data_close_.reshape(-1, len_train, 1)
            pred_close = model.predict(data_close_)
            pred_close = pred_close.ravel()
            pred_close = np.array(pred_close).reshape(len(pred_close), 1)
            pred_cl = sc.inverse_transform(pred_close)
            output_predict.append(pred_cl)
        output_predict = np.array(output_predict)
        return output_predict
    def on_epoch_end(self, epoch, logs=None):
        if (epoch % 20 == 0):
            output_predict = self.model_predict(self.x_test)
            fig, ax = plt.subplots(figsize=(12,6))
            ax.grid(True)
            plt.title(f"Model predict")
            plt.plot(output_predict.ravel(), color="red", label='Predict')
            plt.plot(self.y_test.ravel(), color="blue", label='REAL')
            fig.tight_layout()
            plt.legend(loc='lower left')
            plt.savefig(f'Demo_lstm_epoch_{epoch}.png')
            plt.clf()
            plt.close()

def lstm_reg(input_shape=(60, 1), unit=40, clustering_params=None):
    inputs = Input(input_shape)
    lstm1f = Bidirectional(LSTM(units=32, return_sequences=True))(inputs)
    lstm1f = Bidirectional(LSTM(units=32, return_sequences=False))(lstm1f)
    outputs = Dense(units=1, activation='linear')(lstm1f)
    model = Model(inputs=inputs, outputs=outputs)
    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate), loss='mean_squared_error', metrics=["accuracy"])
    return model

def create_data_train(data_time_series):
    data_time_series = np.array(data_time_series).ravel()
    X_train = []
    y_train = []
    for i in range(len_train, len(data_time_series)):
        X_train.append(data_time_series[i-len_train:i])
        y_train.append(data_time_series[i])
    X_train, y_train = np.array(X_train), np.array(y_train)
    X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
    return X_train, y_train

x = np.linspace(-20*np.pi, 20*np.pi, 2001)
sin_alpha = np.sin(x).ravel()
sin_alpha_train = np.array(copy.deepcopy(sin_alpha))[:len(sin_alpha)-len_test]
sin_alpha_train = np.array(sin_alpha_train).reshape(len(sin_alpha_train), 1)
sc = MinMaxScaler(feature_range=(0, 1))
sin_alpha_train = sc.fit_transform(sin_alpha_train)
X_train, y_train = create_data_train(sin_alpha_train)
joblib.dump(sc, f'Demo_MinMaxScaler.gz')
sc = joblib.load(f"Demo_MinMaxScaler.gz")
X_test = np.array(copy.deepcopy(sin_alpha))[len(sin_alpha)-len_test:len(sin_alpha)-len_test len_train]
X_test = np.array(X_test).reshape(len(X_test), 1)
X_test = sc.fit_transform(X_test)
y_test = np.array(copy.deepcopy(sin_alpha))[len(sin_alpha)-len_test len_train:len(sin_alpha)-len_test len_train total_predict]

model = lstm_reg(input_shape=(len_train, 1), unit=int(2*(len_train len(y_train))/3))
model.summary()
callback_class = Callback_Class()
callback_class.load_data(X_test, y_test)
model.fit(X_train, y_train, epochs=epoch, use_multiprocessing=True, verbose=1, callbacks=[callback_class], workers=workers, batch_size=batch_size)

CodePudding user response:

It seems like you are normalizing your features and your labels in these lines

sc = MinMaxScaler(feature_range=(0, 1))
sin_alpha_train = sc.fit_transform(sin_alpha_train)
X_train, y_train = create_data_train(sin_alpha_train)

Try it without scaling your label set. Due to your output layer using the linear activation function, which is correct as you're working on a regression problem, the model should be able to handle non scaled labels. The model only learns your data in a range of 0 to 1 while your sine wave goes from -1 to 1.

  • Related