Нейронная сеть LSTM для прогнозирования временных рядов температуры - PullRequest
4 голосов
/ 27 мая 2020

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

LSTM daily minimum temperature prediction

Это реализованный мной код. Данные представляют собой фрейм данных с 3 столбцами (минимальная, максимальная и средняя дневная температура), но я использую только один из столбцов одновременно.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tools.eval_measures import rmse
from sklearn.preprocessing import MinMaxScaler
from keras.preprocessing.sequence import TimeseriesGenerator
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
import warnings
warnings.filterwarnings("ignore")

input_file2 = "TemperaturasCampillos.txt"
seriesT = pd.read_csv(input_file2,sep = "\t", decimal = ".", names = ["Minimas","Maximas","Medias"])
seriesT[seriesT==-999]=np.nan

date1 = '2010-01-01'
date2 = '2010-09-01'
date3 = '2020-05-17'
date4 = '2020-12-31'
mydates = pd.date_range(date2, date3).tolist()
seriesT['Fecha'] = mydates
seriesT.set_index('Fecha',inplace=True)  # Para que los índices sean fechas y así se ponen en el eje x de forma predeterminada
seriesT.index = seriesT.index.to_pydatetime()

df =  seriesT.drop(seriesT.columns[[1, 2]], axis=1)  # df.columns is zero-based pd.Index
n_input = 92
train, test = df[:-n_input], df[-n_input:]

scaler = MinMaxScaler()
scaler.fit(train)
train = scaler.transform(train)
test = scaler.transform(test)


#n_input = 365
n_features = 1
generator = TimeseriesGenerator(train, train, length=n_input, batch_size=1)
model = Sequential()
model.add(LSTM(200, activation='relu', input_shape=(n_input, n_features)))
model.add(Dropout(0.15))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
model.fit_generator(generator,epochs=150)

#create an empty list for each of our 12 predictions
#create the batch that our model will predict off of
#save the prediction to our list
#add the prediction to the end of the batch to be used in the next prediction

pred_list = []

batch = train[-n_input:].reshape((1, n_input, n_features))

for i in range(n_input):   
    pred_list.append(model.predict(batch)[0]) 
    batch = np.append(batch[:,1:,:],[[pred_list[i]]],axis=1)

df_predict = pd.DataFrame(scaler.inverse_transform(pred_list),                           
                          index=df[-n_input:].index, columns=['Prediction'])
df_test = pd.concat([df,df_predict], axis=1)

plt.figure(figsize=(20, 5))
plt.plot(df_test.index, df_test['Minimas'])
plt.plot(df_test.index, df_test['Prediction'], color='r')
plt.legend(loc='best', fontsize='xx-large')
plt.xticks(fontsize=18)
plt.yticks(fontsize=16)
plt.show()

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

#n_input = 365
n_features = 1
generator = TimeseriesGenerator(train, train, length=n_input, batch_size=1)
model = Sequential()
model.add(LSTM(200, activation='relu', input_shape=(n_input, n_features)))
model.add(LSTM(128, activation='relu'))
model.add(LSTM(256, activation='relu'))
model.add(LSTM(128, activation='relu'))
model.add(LSTM(64, activation='relu'))
model.add(LSTM(n_features, activation='relu'))
model.add(Dropout(0.15))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
model.fit_generator(generator,epochs=100)

, но я получаю эту ошибку:

ValueError : Вход 0 несовместим со слоем lstm_86: ожидалось ndim = 3, найдено ndim = 2

Конечно, поскольку модель имеет плохую производительность, я не могу гарантировать, что прогнозы вне выборки будут точными. Почему я не могу добавить в сеть больше слоев? Как я мог улучшить производительность?

1 Ответ

0 голосов
/ 28 мая 2020

Вам не хватает одного аргумента: return_sequences.

Если у вас более одного уровня LSTM, вы должны установить его в TRUE. Потому что в противном случае этот слой будет выводить только последнее скрытое состояние. Добавьте его в каждый слой LSTM.

model.add(LSTM(128, activation='relu', return_sequences=True))

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

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