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()
多變量時間序列預(yù)測
諸如長期短期記憶(LSTM)復(fù)發(fā)神經(jīng)網(wǎng)絡(luò)的神經(jīng)網(wǎng)絡(luò)能夠幾乎無縫地模擬多個輸入變量的問題蟆炊。這在時間序列預(yù)測中是一個很大的好處稽莉,其中古典線性方法難以適應(yīng)多變量或多輸入預(yù)測問題。
在本教程中涩搓,您將發(fā)現(xiàn)如何在Keras深度學(xué)習(xí)庫中開發(fā)多變量時間序列預(yù)測的LSTM模型污秆。
如何將原始數(shù)據(jù)集轉(zhuǎn)換為可用于時間序列預(yù)測的內(nèi)容。
如何準(zhǔn)備數(shù)據(jù)并適應(yīng)多變量時間序列預(yù)測問題的LSTM昧甘。
如何做出預(yù)測并將結(jié)果重新調(diào)整到原始單位良拼。
目錄
- 空氣污染預(yù)測
- 數(shù)據(jù)準(zhǔn)備
- 多變量時間序列預(yù)測
1. 空氣污染預(yù)測
數(shù)據(jù)包括日期時間,稱為PM2.5濃度的污染物充边,以及天氣信息庸推,包括露點,溫度浇冰,壓力贬媒,風(fēng)向,風(fēng)速和累積的降雪小時數(shù)肘习。原始數(shù)據(jù)中的完整功能列表如下:
NO:行號
年:這一年的數(shù)據(jù)年
月份:這一行的數(shù)據(jù)月份
day:此行中的數(shù)據(jù)日
小時:小時數(shù)據(jù)在這行
pm2.5:PM2.5濃度
DEWP:露點
溫度:溫度
PRES:壓力
cbwd:組合風(fēng)向
Iws:累積風(fēng)速
是:積雪時間
Ir:累積的下雨時數(shù)
我們可以使用這些數(shù)據(jù)并構(gòu)建一個預(yù)測問題掖蛤,鑒于天氣條件和前幾個小時的污染,我們預(yù)測在下一個小時的污染井厌。
Beijing PM2.5 Data Set
2,數(shù)據(jù)準(zhǔn)備
第一步是將日期時間信息整合為一個日期時間蚓庭,以便我們可以將其用作熊貓的索引。
快速檢查顯示前24小時的pm2.5的NA值仅仆。因此器赞,我們將需要刪除第一行數(shù)據(jù)。在數(shù)據(jù)集中還有幾個分散的“NA”值;我們現(xiàn)在可以用0值標(biāo)記它們墓拜。
以下腳本加載原始數(shù)據(jù)集港柜,并將日期時間信息解析為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預(yù)測
第一步是為LSTM準(zhǔn)備污染數(shù)據(jù)集氯夷。
這涉及將數(shù)據(jù)集視為監(jiān)督學(xué)習(xí)問題并對輸入變量進(jìn)行歸一化。
考慮到上一個時間段的污染測量和天氣條件靶擦,我們將把監(jiān)督學(xué)習(xí)問題作為預(yù)測當(dāng)前時刻(t)的污染情況腮考。
這個表述是直接的,只是為了這個演示玄捕。您可以探索的一些替代方案包括:
根據(jù)過去24小時的天氣情況和污染踩蔚,預(yù)測下一個小時的污染。
預(yù)測下一個小時的污染枚粘,并給予下一個小時的“預(yù)期”天氣條件馅闽。
我們可以使用在博客文章中開發(fā)的series_to_supervised()函數(shù)來轉(zhuǎn)換數(shù)據(jù)集:
# 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())
這個數(shù)據(jù)準(zhǔn)備很簡單,我們可以探索更多馍迄。您可以看到的一些想法包括:
one-hot 編碼福也。
使所有系列均勻分散和季節(jié)性調(diào)整。
提供超過1小時的輸入時間步長柬姚。
最后一點可能是最重要的,因為在學(xué)習(xí)序列預(yù)測問題時庄涡,LSTMs通過時間使用反向傳播量承。
定義和擬合模型
在本節(jié)中,我們將適合多變量輸入數(shù)據(jù)的LSTM穴店。
首先撕捍,我們必須將準(zhǔn)備好的數(shù)據(jù)集分成列車和測試集。為了加快對這次示范的模式培訓(xùn)泣洞,我們將僅適用于數(shù)據(jù)第一年的模型忧风,然后對其余4年的數(shù)據(jù)進(jìn)行評估。如果您有時間球凰,請考慮瀏覽此測試工具的倒置版本狮腿。
下面的示例將數(shù)據(jù)集分成列車和測試集,然后將列車和測試集分成輸入和輸出變量呕诉。最后缘厢,將輸入(X)重構(gòu)為LSTM預(yù)期的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()