Time Series Prediction with LSTM Recurrent Neural Networks in Python with Keras
시계열_예측(Time series prediction) 문제는 예측 모델링 문제의 어려운 유형입니다. 회귀 예측(regression predictive) 모델링과 달리, 시계열은 입력 변수간에 시퀀스 종속성의 복잡성을 추가합니다.
시퀀스 의존성을 처리하도록 설계된 강력한 유형의 신경망을 순환 신경망 (recurrent neural networks)이라고합니다. LSTM 네트워크는 매우 큰 아키텍처를 훈련 할 수 있기 때문에 Deep Learning에 사용되는 일종의 반복 신경 네트워크입니다.
이 글에서는 Keras Deep Learning Library를 사용하여 time-series prediction 문제를 해결하기 위해 Python으로 LSTM 네트워크를 개발하는 방법을 알아 봅니다.
이 튜토리얼을 완료하면 자신의 time-series prediction 문제 및 기타 일반적인 시퀀스 문제에 대한 LSTM 네트워크를 구현하고 개발하는 방법을 알 수 있습니다.
- 국제선 승객에 관한 시계열 예측 문제.
- window, time-step 기반 프레이밍 time series prediction 문제를 위한 LSTM 네트워크를 개발하는 방법.
- 매우 긴 시퀀스에서 상태 (메모리)를 유지하는 LSTM 네트워크를 사용하여 개발하고 예측하는 방법.
이 튜토리얼에서는 standard time series prediction 문제에 대한 여러 가지 LSTM을 개발합니다.
LSTM 네트워크에 대한 문제와 선택한 구성은 데모용으로만 최적화되어 있습니다.
이 예제는 time series predictive 모델링 문제에 대해 서로 다르게 구조화 된 LSTM 네트워크를 개발하는 방법을 정확하게 보여줍니다.
Problem Description
이 글에서 살펴볼 문제는 국제선 여객의 예측 문제입니다.
내용은 1 년 1 개월 후 국제선 승객수를 1,000 명 단위로 예측하는 것이 문제입니다. 자료는 1949 년 1 월부터 1960 년 12 월까지, 12 년 동안 144 회의 관찰을 통해 수집되었습니다.
데이터 세트는 DataMarket 웹 페이지의 CSV 파일, “international-airline-passengers.csv”을 사용합니다.
아래는 파일의 처음 몇 줄의 샘플입니다.
"Month","International airline passengers: monthly totals in thousands. Jan 49 ? Dec 60"
"1949-01",112
"1949-02",118
"1949-03",132
"1949-04",129
"1949-05",121
Pandas 라이브러리를 사용하여이 데이터 세트를 쉽게 로드 할 수 있습니다. 각 내용이 1개월 단위로 분리된다는 것을 알고 있습니다 (날짜는 필요하지 않음). 따라서 데이터 세트를 로드 할 때 첫 번째 열을 제외 할 수 있습니다.
다운로드 한 데이터 세트에는 3 개의 footer lines에 대해 3으로 설정된 pandas.read_csv()에 대한 skipfooter 인수로 제외합니다. 일단 로드되면 전체 데이터 세트를 쉽게 플롯 할 수 있습니다. 데이터 집합을로드하고 플롯하는 코드는 다음과 같습니다.
import pandas
import matplotlib.pyplot as plt
dataset = pandas.read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
plt.plot(dataset)
plt.show()
시간이 지남에 따라 데이터 세트의 상승 추세를 볼 수 있습니다.
또한 아마도 북반구 휴가 기간에 해당하는 데이터 세트에 대한 일정주기를 볼 수 있습니다.
[Plot of the Airline Passengers Dataset]
Long Short-Term Memory Network
Long Short-Term Memory 네트워크 또는 LSTM 네트워크는 시간 경과에 따른 Backpropagation을 사용하여 학습된 신경 네트워크이며 시간 경과에 따라 사라지는 그라디언트 문제를 극복합니다.
따라서, 대규모 반복 네트워크를 생성하는데 사용될 수 있으며, 이 네트워크는 machine learning에서 어려운 시퀀스 문제를 해결하고 최첨단 결과를 달성하는 데 사용될 수 있습니다.
뉴런 대신 LSTM 네트워크는 레이어를 통해 연결된 메모리 블록을 가지고 있습니다.
블록은 고전적인 뉴런보다 더 똑똑한 구성 요소와 최근 시퀀스의 메모리가 있습니다. 블록은 블록 상태와 출력을 관리하는 게이트를 포함합니다. 블록은 입력 시퀀스에 따라 작동하고 블록 내의 각 게이트는 sigmoid 활성화 장치를 사용하여 트리거 되었는지 여부를 제어하여 상태 변경 및 블록을 통해 흐르는 정보 추가를 조건부로 만듭니다.
한 유닛에는 세 가지 유형의 게이트가 있습니다.
- Forget Gate: 블록에서 버릴 정보를 조건부로 결정합니다.
- Input Gate: 메모리 상태를 업데이트 할 입력 값을 조건부로 결정합니다.
- Output Gate: 입력 및 블록의 메모리를 기반으로 출력 할 내용을 조건부로 결정합니다.
각 유닛은 유닛의 게이트가 훈련 과정에서 배운 가중치를 갖는 미니 스테이트 머신과 같습니다.
LSTM 레이어에서 정교한 학습과 기억을 달성하는 방법을 볼 수 있으며 고차원 추상화가 어떻게 여러 계층으로 계층화 될 수 있는지 알 수 있습니다.
LSTM Network for Regression
문제를 회귀(regression) 문제로 표현할 수 있습니다.
즉, 이번 달 승객 수 (천 단위)를 고려하면 다음 달 승객 수는 얼마입니까?
단일 데이터 열을 2 열 데이터 세트로 변환하는 간단한 함수를 작성할 수 있습니다. 이 달의 (t) 승객 수를 포함하는 첫 번째 열과 다음 달 (t + 1) 승객 수를 포함하는 두 번째 열을 예측할 수 있습니다.
시작하기 전에 먼저 사용하려는 모든 함수와 클래스를 가져와 봅시다. 이것은 Keras 심층 학습 라이브러리가 설치된 SciPy 작업 환경을 가정합니다.
import numpy
import matplotlib.pyplot as plt
import pandas
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
우리가하기 전에, 우리의 결과를 재현 할 수 있도록 난수 시드를 수정하는 것이 좋습니다.
# fix random seed for reproducibility
numpy.random.seed(7)
이전 섹션의 코드를 사용하여 데이터 세트를 Pandas 데이터 프레임으로로드 할 수도 있습니다. 그런 다음 데이터 프레임에서 NumPy 배열을 추출하고 정수 값을 신경망을 사용하여 모델링하는 데 더 적합한 부동 소수점 값으로 변환 할 수 있습니다.
# load the dataset
dataframe = pandas.read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
LSTM은 특히 Sigmoid (기본값) 또는 tanh 활성화 기능이 사용될 때 입력 데이터의 크기에 민감합니다. 정규화라고도하는 0에서 1의 범위로 데이터의 크기를 다시 조정하는 것이 좋습니다. scikit-learn 라이브러리의 MinMaxScaler 전처리 클래스를 사용하여 데이터 세트를 쉽게 정규화 할 수 있습니다.
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
데이터를 모델링하고 training 데이터 세트에서 모델의 기술을 평가 한 후에는 새로운 보이지 않는 데이터에 대한 모델 기술에 대한 아이디어를 얻을 필요가 있습니다. 정상 분류(normal classification) 또는 회귀 문제(regression problem)의 경우 교차 검증을 사용하여이를 수행합니다.
time series 데이터의 경우 값의 순서가 중요합니다. 우리가 사용할 수 있는 간단한 방법은 정렬 된 데이터 세트를 train 및 테스트 데이터 세트로 분할하는 것 입니다. 아래 코드는 스플릿 포인트의 인덱스를 계산하고 모델을 테스트하는 데 사용할 수 있는 관측치의 67%를 사용하여 데이터를 교육 데이터 세트로 분리하고 나머지 33%는 모델 테스트를 위해 남겨 둡니다.
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
print(len(train), len(test))
이제 위에서 설명한대로 새 데이터 집합을 만드는 함수를 정의할 수 있습니다.
이 함수는 데이터 세트로 변환하려는 NumPy 배열인 데이터 세트와 다음 기간을 예측하기 위해 입력 변수로 사용하는 이전 시간 스텝의 수인 look_back이라는 두 인수를 사용합니다. 이 경우 기본값은 1입니다.
이 기본값은 X가 주어진 시간 (t)에 승객의 수이고 Y가 다음 시간 (t + 1)에 승객의 수인 데이터 세트를 생성합니다.
이를 구성 할 수 있으며, 다음 섹션에서 모양이 다른 데이터 세트를 구성 할 것 입니다.
# convert an array of values into a dataset matrix
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 numpy.array(dataX), numpy.array(dataY)
데이터 집합의 첫 번째 행에 대한이 함수의 영향을 살펴 보겠습니다 (명확화를 위해 비표준 형식으로 표시).
X Y
112 118
118 132
132 129
129 121
121 135
첫 번째 5 행을 이전 섹션에 나열된 원본 데이터 세트 샘플과 비교하면 숫자에 X = t 및 Y = t + 1 패턴이 표시됩니다.
이 함수를 사용하여 모델링을위한 열차 및 테스트 데이터 세트를 준비합시다.
# reshape into X=t and Y=t+1
look_back = 1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
LSTM 네트워크는 입력 데이터 (X)가 [samples, time steps, features]의 형태로 특정 배열 구조와 함께 제공 될 것으로 기대합니다.
현재 우리의 데이터는 [samples, features] 형식으로되어 있으며 각 샘플에 대해 한 번 단계로 문제를 구성하고 있습니다. 다음과 같이 numpy.reshape ()를 사용하여 준비된 train를 변형하고 입력 데이터를 예상되는 구조로 테스트 할 수 있습니다.
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
우리는 이제이 문제에 대한 LSTM 네트워크를 설계하고 맞출 준비가되었습니다.
네트워크에는 1 개의 입력이 있는 보이는 레이어, 4 개의 LSTM 블록 또는 뉴런이있는 숨겨진 레이어, 단일 값 예측을하는 출력 레이어가 있습니다. 기본 Sigmoid 활성화 기능은 LSTM 블록에 사용됩니다. 네트워크는 100 개 epochs에 대해 훈련되고 1의 배치 크기가 사용됩니다.
# create and fit the LSTM network
model = Sequential()
model.add(LSTM(4, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=100, batch_size=1, verbose=2)
모델이 적합하면 train 및 테스트 데이터 세트에서 모델의 성능을 예측할 수 있습니다. 이것은 우리에게 새로운 모델에 대한 비교 점을 줄 것입니다.
오류 점수를 계산하기 전에 예측을 반전하여 원래 데이터 (한 달에 수천 명의 승객)와 동일한 단위로 실적을 보고합니다.
# 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))
마지막으로 모델의 기술을 시각적으로 표시하기 위해 열차 및 테스트 데이터 세트 모두에 대해 모델을 사용하여 예측을 생성 할 수 있습니다.
데이터 세트가 준비되었으므로, x 축에서 원래 데이터 세트와 정렬되도록 예측을 이동해야합니다. 준비가 완료되면 데이터가 그려져 원본 데이터 세트가 파란색으로 표시되고 교육 데이터 세트의 녹색 예측이 표시되며 보이지 않는 테스트 데이터 세트의 예측은 빨간색으로 표시됩니다.
# shift train predictions for plotting
trainPredictPlot = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.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()
이 모델은 train 데이터 세트와 테스트 데이터 세트 모두에 적합한 훌륭한 작업을 수행했다는 것을 알 수 있습니다.
[LSTM Trained on Regression Formulation of Passenger Prediction Problem]
전체 코드 예제는 다음과 같습니다.
# LSTM for international airline passengers problem with regression framing
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
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 numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
# reshape into X=t and Y=t+1
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 = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
# create and fit the LSTM network
model = Sequential()
model.add(LSTM(4, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=100, batch_size=1, 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 = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.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()
예제를 실행하면 다음과 같은 출력이 생성됩니다.
...
Epoch 95/100
0s - loss: 0.0020
Epoch 96/100
0s - loss: 0.0020
Epoch 97/100
0s - loss: 0.0020
Epoch 98/100
0s - loss: 0.0020
Epoch 99/100
0s - loss: 0.0020
Epoch 100/100
0s - loss: 0.0020
Train Score: 22.93 RMSE
Test Score: 47.53 RMSE
이 모델에는 훈련 데이터 세트에 약 23 명의 승객 (수천)의 평균 오류가 있고 테스트 데이터 세트에 약 52 명의 승객 (수천)이 있다는 것을 알 수 있습니다.
LSTM for Regression Using the Window Method
우리는 또한 다음의 단계에 대한 예측을 하기 위해 여러 개의 최근 time steps가 사용될 수 있도록 문제를 구별 할 수 있습니다.
이를 window라고하며 window의 크기는 각 문제에 대해 조정할 수 있는 매개 변수입니다.
예를 들어, 시퀀스 (t + 1)에서 다음 번에 값을 예측하고자하는 현재 시간 (t)이 주어진다면, 현재 시간 (t)뿐만 아니라 이전 시간 (t-1 및 t-2)을 입력 변수로 갖는다.
회귀(regression) 문제로 표현하면 입력 변수는 t-2, t-1, t이고 출력 변수는 t + 1입니다.
이전 섹션에서 작성한 create_dataset() 함수를 사용하면 look_back 인수를 1에서 3으로 늘림으로써 시계열 문제의 공식을 생성 할 수 있습니다.
이 공식을 사용하는 데이터 세트의 샘플은 다음과 같습니다.
X1 X2 X3 Y
112 118 132 129
118 132 129 121
132 129 121 135
129 121 135 148
121 135 148 148
이전 섹션의 예제를 큰 window 크기로 다시 실행할 수 있습니다. 완전성을 위해 window 크기가 변경된 전체 코드 목록이 아래에 나열되어 있습니다.
# LSTM for international airline passengers problem with window regression framing
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
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 numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
# create and fit the LSTM network
model = Sequential()
model.add(LSTM(4, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=100, batch_size=1, 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 = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.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()
예제를 실행하면 다음과 같은 결과가 출력됩니다.
...
Epoch 95/100
0s - loss: 0.0021
Epoch 96/100
0s - loss: 0.0021
Epoch 97/100
0s - loss: 0.0021
Epoch 98/100
0s - loss: 0.0021
Epoch 99/100
0s - loss: 0.0022
Epoch 100/100
0s - loss: 0.0020
Train Score: 24.19 RMSE
Test Score: 58.03 RMSE
오류는 이전 섹션과 비교하여 약간 증가한 것을 볼 수 있습니다. window 크기와 네트워크 아키텍처는 조정되지 않았습니다. 이것은 예측 문제를 프레임하는 방법을 보여주는 데 불과합니다.
[LSTM Trained on Window Method Formulation of Passenger Prediction Problem]
LSTM for Regression with Time Steps
LSTM 네트워크를 위한 데이터 준비에는 시간 단계가 포함되어 있습니다.
일부 시퀀스 문제의 경우 샘플 당 시간 단계가 다양 할 수 있습니다. 예를 들어 물리적인 기계를 측정하여 장애가 발생하거나 surge가 발생하는 경우가 있습니다. 각각의 사건은 사건이 될 관측치가 시간 단계가되는 표본이 될 것이며 관측 된 변수는 특징이 될 것입니다.
time steps는 time series 문제를 표현하는 또 다른 방법을 제공합니다. 위의 window 예와 같이, 다음 시간 단계에서 출력을 예측하기 위해 입력으로 time series에서 이전 시간 단계를 취할 수 있습니다.
과거의 관측치를 별도의 입력 피쳐로 표현하는 대신, 이를 한 입력 피처의 time step로 사용할 수 있습니다. 이는 실제로 문제보다 정확한 프레이밍입니다.
이전 window 기반 예제와 동일한 데이터 표현을 사용하여 이를 수행 할 수 있습니다. 데이터를 재구성 할 때를 제외하고 열을 시간 단계 차원으로 설정하고 형상 차원을 다시 1로 변경합니다.
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))
testX = numpy.reshape(testX, (testX.shape[0], testX.shape[1], 1))
전체 코드 목록은 다음과 같습니다.
# LSTM for international airline passengers problem with time step regression framing
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
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 numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))
testX = numpy.reshape(testX, (testX.shape[0], testX.shape[1], 1))
# create and fit the LSTM network
model = Sequential()
model.add(LSTM(4, input_shape=(look_back, 1)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=100, batch_size=1, 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 = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.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()
예제를 실행하면 다음과 같은 결과가 출력됩니다.
...
Epoch 95/100
1s - loss: 0.0021
Epoch 96/100
1s - loss: 0.0021
Epoch 97/100
1s - loss: 0.0021
Epoch 98/100
1s - loss: 0.0020
Epoch 99/100
1s - loss: 0.0021
Epoch 100/100
1s - loss: 0.0020
Train Score: 23.69 RMSE
Test Score: 58.88 RMSE
입력 데이터의 구조가 훨씬 더 의미가 있지만 결과가 이전 예제보다 약간 더 나은 것을 알 수 있습니다.
[LSTM Trained on Time Step Formulation of Passenger Prediction Problem]
LSTM with Memory Between Batches
LSTM 네트워크에는 긴 시퀀스에서 기억할 수있는 메모리가 있습니다.
일반적으로 model을 수용 할 때 각 training batch 후에 model.predict() 또는 model.evaluate()를 호출 할 때마다 네트워크 내의 상태가 재설정됩니다.
LSTM 계층을 “stateful” 함으로써 Keras에서 LSTM 네트워크의 내부 상태가 지워지는 경우를 보다 세밀하게 제어 할 수 있습니다. 즉, 전체 교육 과정에 걸쳐 상태를 구축 할 수 있으며 예측이 필요한 경우 상태를 유지할 수도 있습니다.
네트워크에 연결될 때 교육 데이터가 섞이지 않아야 합니다. 또한 model.reset_states()에 대한 호출을 통해 train 데이터 (epoch)에 노출 될 때마다 네트워크 상태를 명시적으로 재설정해야 합니다. 이것은 우리가 epoch의 외부 루프를 만들고 각 epoch 호출 model.fit() 및 model.reset_states() 내에서 만들어야 함을 의미합니다.
for i in range(100):
model.fit(trainX, trainY, epochs=1, batch_size=batch_size, verbose=2, shuffle=False)
model.reset_states()
마지막으로, LSTM 계층이 구성 될 때 상태 기반 매개 변수를 True로 설정해야하며 입력 차원을 지정하는 대신 number of samples in a batch, 샘플의 number of time steps 및 number of features를 하드 코딩하여야 하며 batch_input_shape 매개 변수를 설정하여 단계를 완료하십시오.
model.add(LSTM(4, batch_input_shape=(batch_size, time_steps, features), stateful=True))
이 같은 batch size는 나중에 모델을 평가하고 예측을 할 때 사용해야합니다.
model.predict(trainX, batch_size=batch_size)
이전의 시간 단계 예제를 적용하여 상태 기반 LSTM을 사용할 수 있습니다. 전체 코드 목록은 아래에 제공됩니다.
# LSTM for international airline passengers problem with memory
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
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 numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))
testX = numpy.reshape(testX, (testX.shape[0], testX.shape[1], 1))
# create and fit the LSTM network
batch_size = 1
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
for i in range(100):
model.fit(trainX, trainY, epochs=1, batch_size=batch_size, verbose=2, shuffle=False)
model.reset_states()
# make predictions
trainPredict = model.predict(trainX, batch_size=batch_size)
model.reset_states()
testPredict = model.predict(testX, batch_size=batch_size)
# 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 = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.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()
예제를 실행하면 다음과 같은 결과가 출력됩니다.
...
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0016
Train Score: 20.74 RMSE
Test Score: 52.23 RMSE
결과가 더 나 빠졌다는 것을 알 수 있습니다. 모델에는 더 많은 모듈이 필요할 수 있으며 문제의 구조를 내부화하기 위해 더 많은 epoch을 train 받아야 할 수 있습니다.
[Stateful LSTM Trained on Regression Formulation of Passenger Prediction Problem]
Stacked LSTMs with Memory Between Batches
마지막으로, 우리는 LSTM의 큰 장점 중 하나 인 deep network 아키텍처를 활용하여 train 받을 수 있다는 사실을 살펴볼 것입니다.
LSTM 네트워크는 다른 레이어 유형을 쌓을 수 있는 것과 같은 방법으로 Keras에 쌓을 수 있습니다. 필요한 구성에 한 가지 추가 사항은 각 후속 LSTM 레이어 이전의 LSTM 레이어가 시퀀스를 반환해야 한다는 것입니다. 이 작업은 레이어의 return_sequences 매개 변수를 True로 설정하여 수행 할 수 있습니다.
이전 섹션의 stateful LSTM을 확장하여 다음과 같이 두 개의 레이어를 만들 수 있습니다.
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True, return_sequences=True))
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True))
전체 코드 목록은 완전성을 위해 아래에 제공됩니다.
# Stacked LSTM for international airline passengers problem with memory
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
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 numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))
testX = numpy.reshape(testX, (testX.shape[0], testX.shape[1], 1))
# create and fit the LSTM network
batch_size = 1
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True, return_sequences=True))
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
for i in range(100):
model.fit(trainX, trainY, epochs=1, batch_size=batch_size, verbose=2, shuffle=False)
model.reset_states()
# make predictions
trainPredict = model.predict(trainX, batch_size=batch_size)
model.reset_states()
testPredict = model.predict(testX, batch_size=batch_size)
# 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 = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.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()
예제를 실행하면 다음과 같은 출력이 생성됩니다.
...
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0017
Epoch 1/1
1s - loss: 0.0016
Train Score: 20.49 RMSE
Test Score: 56.35 RMSE
테스트 데이터 세트에 대한 예측은 다시 악화됩니다. 이것은 추가적인 train 시기에 대한 필요성을 암시하는 증거입니다.
[Stacked Stateful LSTMs Trained on Regression Formulation of Passenger Prediction Problem]
Summary
이 글에서는 Keras 심층 학습 네트워크를 사용하여 파이썬에서 time series prediction을 위한 LSTM 반복적인 신경망을 개발하는 방법을 발견했습니다.
특히, 다음을 배웠습니다.
- 국제선 승객의 시계열 예측 문제에 대해.
- time series 문제의 회귀(regression) 및 window를 위한 LSTM을 작성하는 방법.
- time series 문제의 time step 공식을 사용하여 LSTM을 만드는 법.
- LSTM을 상태 및 스택 된 LSTM과 함께 생성하여 긴 시퀀스를 배우는 방법.