이 페이지의 최신 내용은 아직 번역되지 않았습니다. 최신 내용은 영문으로 볼 수 있습니다.

심층 학습을 사용한 시계열 예측

이 예제에서는 장단기 기억(LSTM) 네트워크를 사용하여 시계열 데이터를 예측하는 방법을 보여줍니다.

시퀀스의 미래의 시간 스텝 값을 예측하기 위해 응답 변수가 값이 시간 스텝 하나만큼 이동된 훈련 시퀀스인 sequence-to-sequence 회귀 LSTM 네트워크를 훈련시킬 수 있습니다. 즉, LSTM 네트워크는 입력 시퀀스의 각 시간 스텝마다 다음 시간 스텝의 값을 예측하도록 학습합니다.

미래의 여러 시간 스텝의 값을 예측하려면 predictAndUpdateState 함수를 사용하여 한 번에 하나의 시간 스텝을 예측한 다음 각 예측에 대해 네트워크 상태를 업데이트하십시오.

이 예제에서는 데이터 세트 chickenpox_dataset를 사용합니다. 이 예제에서는 이전 달들의 수두 발병 건수를 주고 수두 발병의 건수를 예측하도록 LSTM 네트워크를 훈련시킵니다.

시퀀스 데이터 불러오기

예제 데이터를 불러옵니다. chickenpox_dataset는 시간 스텝이 달에 대응되고 값이 발병 건수에 대응되는 하나의 시계열을 포함합니다. 출력값은 각 요소가 하나의 시간 스텝인 셀형 배열입니다. 데이터가 행 벡터가 되도록 형태를 변경합니다.

data = chickenpox_dataset;
data = [data{:}];

figure
plot(data)
xlabel("Month")
ylabel("Cases")
title("Monthy Cases of Chickenpox")

훈련 데이터와 테스트 데이터를 나눕니다. 시퀀스의 처음 90%에 대해 훈련을 진행하고 마지막 10%에 대해 테스트를 진행합니다.

numTimeStepsTrain = floor(0.9*numel(data));

dataTrain = data(1:numTimeStepsTrain+1);
dataTest = data(numTimeStepsTrain+1:end);

데이터 표준화하기

더 적합한 피팅을 위해, 그리고 훈련의 발산을 방지하기 위해 평균 0, 분산 1이 되도록 훈련 데이터를 표준화합니다. 테스트 데이터는 훈련 데이터와 동일한 파라미터를 사용하여 예측 시점에 표준화해야 합니다.

mu = mean(dataTrain);
sig = std(dataTrain);

dataTrainStandardized = (dataTrain - mu) / sig;

예측 변수와 응답 변수 준비하기

시퀀스의 미래의 시간 스텝 값을 예측하려면 응답 변수가 값이 시간 스텝 하나만큼 이동된 훈련 시퀀스가 되도록 지정하십시오. 즉, LSTM 네트워크는 입력 시퀀스의 각 시간 스텝마다 다음 시간 스텝의 값을 예측하도록 학습합니다. 예측 변수는 최종 시간 스텝이 없는 훈련 시퀀스입니다.

XTrain = dataTrainStandardized(1:end-1);
YTrain = dataTrainStandardized(2:end);

LSTM 네트워크 아키텍처 정의하기

LSTM 회귀 네트워크를 만듭니다. LSTM 계층이 200개의 은닉 유닛을 갖도록 지정합니다.

numFeatures = 1;
numResponses = 1;
numHiddenUnits = 200;

layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits)
    fullyConnectedLayer(numResponses)
    regressionLayer];

훈련 옵션을 지정합니다. 솔버를 'adam'으로 지정하고 250회의 Epoch에 대해 훈련시킵니다. 기울기가 한없이 증가하지 않도록 하려면 기울기 임계값을 1로 설정하십시오. 초기 학습률을 0.005로 지정하고, Epoch 125회가 지나면 0.2를 곱하여 학습률을 떨어뜨립니다.

options = trainingOptions('adam', ...
    'MaxEpochs',250, ...
    'GradientThreshold',1, ...
    'InitialLearnRate',0.005, ...
    'LearnRateSchedule','piecewise', ...
    'LearnRateDropPeriod',125, ...
    'LearnRateDropFactor',0.2, ...
    'Verbose',0, ...
    'Plots','training-progress');

LSTM 네트워크 훈련시키기

trainNetwork를 사용하여 지정된 훈련 옵션으로 LSTM 네트워크를 훈련시킵니다.

net = trainNetwork(XTrain,YTrain,layers,options);

미래의 시간 스텝 예측하기

미래의 여러 시간 스텝의 값을 예측하려면 predictAndUpdateState 함수를 사용하여 한 번에 하나의 시간 스텝을 예측한 다음 각 예측에 대해 네트워크 상태를 업데이트하십시오. 각 예측에서 직전의 예측을 함수의 입력값으로 사용합니다.

훈련 데이터와 동일한 파라미터를 사용하여 테스트 데이터를 표준화합니다.

dataTestStandardized = (dataTest - mu) / sig;
XTest = dataTestStandardized(1:end-1);

네트워크 상태를 초기화하려면 먼저 훈련 데이터 XTrain에 대해 예측을 수행하십시오. 다음으로, 훈련 응답 변수 YTrain(end)의 마지막 시간 스텝을 사용하여 첫 번째 예측을 수행합니다. 루프를 사용해 나머지 예측을 반복 수행하고 직전 예측을 predictAndUpdateState의 입력값으로 사용합니다.

대규모의 데이터 모음, 긴 시퀀스 또는 큰 네트워크의 경우에는 일반적으로 GPU에서의 예측이 CPU에서의 예측보다 연산 속도가 빠릅니다. 그 밖의 경우에는 일반적으로 CPU에서의 예측이 연산 속도가 빠릅니다. 단일 시간 스텝 예측에는 CPU를 사용하십시오. 예측에 CPU를 사용하려면 predictAndUpdateState'ExecutionEnvironment' 옵션을 'cpu'로 설정하십시오.

net = predictAndUpdateState(net,XTrain);
[net,YPred] = predictAndUpdateState(net,YTrain(end));

numTimeStepsTest = numel(XTest);
for i = 2:numTimeStepsTest
    [net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),'ExecutionEnvironment','cpu');
end

앞에서 계산한 파라미터를 사용하여 예측의 표준화를 해제합니다.

YPred = sig*YPred + mu;

훈련 진행 상황 플롯은 표준화된 데이터로부터 계산된 RMSE(제곱평균제곱근 오차)를 보고합니다. 표준화를 해제한 예측으로부터 RMSE를 계산합니다.

YTest = dataTest(2:end);
rmse = sqrt(mean((YPred-YTest).^2))
rmse = single
    211.2789

예측된 값을 사용하여 훈련 시계열을 플로팅합니다.

figure
plot(dataTrain(1:end-1))
hold on
idx = numTimeStepsTrain:(numTimeStepsTrain+numTimeStepsTest);
plot(idx,[data(numTimeStepsTrain) YPred],'.-')
hold off
xlabel("Month")
ylabel("Cases")
title("Forecast")
legend(["Observed" "Forecast"])

예측된 값과 테스트 데이터를 비교합니다.

figure
subplot(2,1,1)
plot(YTest)
hold on
plot(YPred,'.-')
hold off
legend(["Observed" "Forecast"])
ylabel("Cases")
title("Forecast")

subplot(2,1,2)
stem(YPred - YTest)
xlabel("Month")
ylabel("Error")
title("RMSE = " + rmse)

관측된 값으로 네트워크 상태 업데이트하기

예측과 예측 사이의 시간 스텝의 실제 값에 액세스할 수 있으면 예측된 값 대신 관측된 값을 사용하여 네트워크 상태를 업데이트할 수 있습니다.

먼저 네트워크 상태를 초기화합니다. 새로운 시퀀스에 대해 예측을 수행하려면 resetState를 사용하여 네트워크 상태를 재설정하십시오. 네트워크 상태를 재설정하면 이전 예측들이 새로운 데이터에 대한 예측에 영향을 주지 않게 됩니다. 네트워크 상태를 재설정한 다음 훈련 데이터에 대해 예측을 수행하여 네트워크 상태를 초기화합니다.

net = resetState(net);
net = predictAndUpdateState(net,XTrain);

각 시간 스텝에서 예측을 수행합니다. 각 예측에서 직전 시간 스텝의 관측된 값을 사용하여 다음 시간 스텝을 예측합니다. predictAndUpdateState'ExecutionEnvironment''cpu'로 설정합니다.

YPred = [];
numTimeStepsTest = numel(XTest);
for i = 1:numTimeStepsTest
    [net,YPred(:,i)] = predictAndUpdateState(net,XTest(:,i),'ExecutionEnvironment','cpu');
end

앞에서 계산한 파라미터를 사용하여 예측의 표준화를 해제합니다.

YPred = sig*YPred + mu;

RMSE(제곱평균제곱근 오차)를 계산합니다.

rmse = sqrt(mean((YPred-YTest).^2))
rmse = 156.7908

예측된 값과 테스트 데이터를 비교합니다.

figure
subplot(2,1,1)
plot(YTest)
hold on
plot(YPred,'.-')
hold off
legend(["Observed" "Predicted"])
ylabel("Cases")
title("Forecast with Updates")

subplot(2,1,2)
stem(YPred - YTest)
xlabel("Month")
ylabel("Error")
title("RMSE = " + rmse)

이때 예측된 값 대신 관측된 값을 사용하여 네트워크 상태를 업데이트하면 예측이 더욱 정확해집니다.

참고 항목

| | |

관련 항목