LSTM 原理
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
from keras.models import Sequential
from keras.layers import Dense, LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
np.random.seed(7)
def create_dataset(dataset, look_back=1):
dataX, dataY = [], []
for i in range(len(dataset)-look_back-1):
a = dataset[i:(i+look_back), 0]
dataX.append(a)
dataY.append(dataset[i + look_back, 0])
return np.array(dataX), np.array(dataY)
dataframe = pd.read_csv('../input/traininggoogleprices/TrainPrices.csv', usecols=[1])
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
train_size = int(len(dataset) * 0.9)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
look_back=1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
# create and fit the LSTM network
model = Sequential()
model.add(LSTM(128,activation='tanh', input_shape=(1, look_back), return_sequences=True))
model.add(LSTM(128,activation='tanh', input_shape=(1, look_back),return_sequences=False))
model.add(Dense(1, activation='relu'))
model.compile(loss='mse', optimizer='RMSProp', metrics = ['accuracy'])
model.fit(trainX, trainY, epochs=10, batch_size=32, verbose=2)
# make predictions
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)
# invert predictions
trainPredict = scaler.inverse_transform(trainPredict)
trainY = scaler.inverse_transform([trainY])
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform([testY])
# calculate root mean squared error
trainScore = math.sqrt(mean_squared_error(trainY[0], trainPredict[:,0]))
print('Train Score: %.2f RMSE' % (trainScore))
testScore = math.sqrt(mean_squared_error(testY[0], testPredict[:,0]))
print('Test Score: %.2f RMSE' % (testScore))
# shift train predictions for plotting
trainPredictPlot = np.empty_like(dataset)
trainPredictPlot[:, :] = np.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = np.empty_like(dataset)
testPredictPlot[:, :] = np.nan
testPredictPlot[len(trainPredict)+(look_back*2)+1:len(dataset)-1, :] = testPredict
# plot baseline and predictions
plt.plot(scaler.inverse_transform(dataset))
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.show()
多變量時間序列預測
諸如長期短期記憶(LSTM)復發神經網絡的神經網絡能夠幾乎無縫地模擬多個輸入變量的問題。這在時間序列預測中是一個很大的好處,其中古典線性方法難以適應多變量或多輸入預測問題。
在本教程中,您將發現如何在Keras深度學習庫中開發多變量時間序列預測的LSTM模型。
如何將原始數據集轉換為可用于時間序列預測的內容。
如何準備數據并適應多變量時間序列預測問題的LSTM。
如何做出預測并將結果重新調整到原始單位。
目錄
- 空氣污染預測
- 數據準備
- 多變量時間序列預測
1. 空氣污染預測
數據包括日期時間,稱為PM2.5濃度的污染物,以及天氣信息,包括露點,溫度,壓力,風向,風速和累積的降雪小時數。原始數據中的完整功能列表如下:
NO:行號
年:這一年的數據年
月份:這一行的數據月份
day:此行中的數據日
小時:小時數據在這行
pm2.5:PM2.5濃度
DEWP:露點
溫度:溫度
PRES:壓力
cbwd:組合風向
Iws:累積風速
是:積雪時間
Ir:累積的下雨時數
我們可以使用這些數據并構建一個預測問題,鑒于天氣條件和前幾個小時的污染,我們預測在下一個小時的污染。
Beijing PM2.5 Data Set
2,數據準備
第一步是將日期時間信息整合為一個日期時間,以便我們可以將其用作熊貓的索引。
快速檢查顯示前24小時的pm2.5的NA值。因此,我們將需要刪除第一行數據。在數據集中還有幾個分散的“NA”值;我們現在可以用0值標記它們。
以下腳本加載原始數據集,并將日期時間信息解析為Pandas DataFrame索引。 “No”列被刪除,然后為每列指定更清晰的名稱。最后,將NA值替換為“0”值,并刪除前24小時。
from pandas import read_csv
from datetime import datetime
# load data
def parse(x):
return datetime.strptime(x, '%Y %m %d %H')
dataset = read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
dataset.drop('No', axis=1, inplace=True)
# manually specify column names
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
dataset.index.name = 'date'
# mark all NA values with 0
dataset['pollution'].fillna(0, inplace=True)
# drop the first 24 hours
dataset = dataset[24:]
# summarize first 5 rows
print(dataset.head(5))
# save to file
dataset.to_csv('pollution.csv')
然后可以對其畫圖來看他們的分布情況:
from pandas import read_csv
from matplotlib import pyplot
# load dataset
dataset = read_csv('pollution.csv', header=0, index_col=0)
values = dataset.values
# specify columns to plot
groups = [0, 1, 2, 3, 5, 6, 7]
i = 1
# plot each column
pyplot.figure()
for group in groups:
pyplot.subplot(len(groups), 1, i)
pyplot.plot(values[:, group])
pyplot.title(dataset.columns[group], y=0.5, loc='right')
i += 1
pyplot.show()
多元LSTM預測
第一步是為LSTM準備污染數據集。
這涉及將數據集視為監督學習問題并對輸入變量進行歸一化。
考慮到上一個時間段的污染測量和天氣條件,我們將把監督學習問題作為預測當前時刻(t)的污染情況。
這個表述是直接的,只是為了這個演示。您可以探索的一些替代方案包括:
根據過去24小時的天氣情況和污染,預測下一個小時的污染。
預測下一個小時的污染,并給予下一個小時的“預期”天氣條件。
我們可以使用在博客文章中開發的series_to_supervised()函數來轉換數據集:
# convert series to supervised learning
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
df = DataFrame(data)
cols, names = list(), list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
if i == 0:
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
else:
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
# put it all together
agg = concat(cols, axis=1)
agg.columns = names
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg
# load dataset
dataset = read_csv('pollution.csv', header=0, index_col=0)
values = dataset.values
# integer encode direction
encoder = LabelEncoder()
values[:,4] = encoder.fit_transform(values[:,4])
# ensure all data is float
values = values.astype('float32')
# normalize features
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
# frame as supervised learning
reframed = series_to_supervised(scaled, 1, 1)
# drop columns we don't want to predict
reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True)
print(reframed.head())
這個數據準備很簡單,我們可以探索更多。您可以看到的一些想法包括:
one-hot 編碼。
使所有系列均勻分散和季節性調整。
提供超過1小時的輸入時間步長。
最后一點可能是最重要的,因為在學習序列預測問題時,LSTMs通過時間使用反向傳播。
定義和擬合模型
在本節中,我們將適合多變量輸入數據的LSTM。
首先,我們必須將準備好的數據集分成列車和測試集。為了加快對這次示范的模式培訓,我們將僅適用于數據第一年的模型,然后對其余4年的數據進行評估。如果您有時間,請考慮瀏覽此測試工具的倒置版本。
下面的示例將數據集分成列車和測試集,然后將列車和測試集分成輸入和輸出變量。最后,將輸入(X)重構為LSTM預期的3D格式,即[樣本,時間步長,特征]。
# split into train and test sets
values = reframed.values
n_train_hours = 365 * 24
train = values[:n_train_hours, :]
test = values[n_train_hours:, :]
# split into input and outputs
train_X, train_y = train[:, :-1], train[:, -1]
test_X, test_y = test[:, :-1], test[:, -1]
# reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
# design network
model = Sequential()
model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dense(1))
model.compile(loss='mae', optimizer='adam')
# fit network
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
# plot history
pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.legend()
pyplot.show()