본문 바로가기
딥러닝으로 하루하루 씹어먹기

LSTM으로 수요 예측하기 - 7장 (Mean Absolute Scaled Error-MASE)

by Yoo Sung Hyun 2021. 4. 21.
728x90

1. 시간별로 데이터 전처리 / Not Scaled

2. 일반 lstm 3레이어 정도(?)

3. 이후 data도 중요하다고 생각듬

4. BI-LSTM 사용

5. 데이터가 너무 없어 K-Fold 적용

6. Layer만 주구장창 쌓다가 AutoEncoder 활용

7. 데이터 Scaled 적용

8. Loss Function Custom

9. 1차 마무리

  - 여기 사이에는 BERT가 포함되어있다. (Google Source를 다 까봤는데, 이건 언제 또 정리할까...) -

10. Attention 적용

  => Dual-Stage Attention RNN (DA-RNN) -> 논문으로 현업 씹어먹기로 작성중...

  => Luong Attention (Dot-Product Attention)

  => Bahdanau Attention

11. Seq2Seq 활용    => 시도 중에 다른업무로 잠시 Holding

 

현재 구현하고 있던 모델은 -1, -7, -62, -93일의 24시간으로 각각 오늘의 24시간을 예측하는 모델이었다. (모델이 총 4개)

애시당초에, long term dependency 이슈에 대해서는 인지하고있었기에, 단순 lstm 형태로 모델을 구성할때부터 애시당초에 과거의 모든 기간을 전부 input, label 데이터로 활용하진 않았다. 딱 과거의 24시간으로 현재의 24시간만 예측했다.

 

때문에 그렇다보니, 단순히 오늘의 값(label)과 예측값의 차이로 학습시키는 RMSE/MAE로는, 뭐 24시간의 패턴성은 학습이 되겠지만, 어떤 기간의 패턴이나 계절성이 제대로 학습되지 않을 것 같다는 생각이 들었고, 이 문제를 해결하면 정확도를 더 높힐 수 있겠단 생각이 들었다.

 

현재 문서에서는 7일전의 24시간으로 오늘의 24시간을 예측하는 7일 GAP 24시간 예측 모델을 예시로 설명하겠다.

 

---- 나의 가설

1. 7일전의 값도 학습이 되서, 7일전의 24시간 패턴도 예측하게 한다면, 오늘의 24시간 패턴도 예측이 잘 되지 않을까?

  • Feature값을 예측값으로 활용하면, 당연히 Feature값을 예측하는 것은 잘 예측하도록 학습이 될테니, 오늘의 24시간과, Feature로 쓰이는 7일전의 24시간을 동시에 예측하게되면, 7일전의 패턴을 기준으로 오늘의 패턴이 잘 학습될 것이다. (Predict Output 값이 7일전 24시간, 오늘 24시간 으로 2가지가 된다.)

2. 과거의 데이터와, 예측해야할 오늘의 데이터가 있다면, loss function에서 그 둘을 이용할 수 있지 않을까?

  • 시간 흐름의 GAP과, 실제 오차값을 동시에 적용할 수 있는 계산 공식을 찾아보자!

 

1번과 2번 순서에 의해 loss function 자체를 찾아보기에 이르렀고, 그러다 발견한 것이.

Mean Absoulute Scaled Error였다.

참고 : brunch.co.kr/@chris-song/34

 

Regression 모델 평가 방법

내 예측 모델이 맞춘 값이 얼마나 정확한 거지? | 이번 포스팅에선, 시계열 예측에서 자주 활용하는 Regression 데이터 예측 모델을 평가하는 법에 대해서 설명드리겠습니다. 우리가 예측 모델을 트

brunch.co.kr

수학 함수에 대한 레퍼런스 : en.wikipedia.org/wiki/Mean_absolute_scaled_error

 

Mean absolute scaled error - Wikipedia

In statistics, the mean absolute scaled error (MASE) is a measure of the accuracy of forecasts. It is the mean absolute error of the forecast values, divided by the mean absolute error of the in-sample one-step naive forecast. It was proposed in 2005 by st

en.wikipedia.org

최종 공식을 정리해보면 이렇다.

-- 최종 공식 --

    비계절성 : 평균(절대값(y 현재 예측 - 현재 실제)) / 평균(절대값(실제 다음 값에 대한 오차))

    계절성 : 평균(절대값(y 현재 예측 - 현재 실제)) / 평균(절대값(실제 기간 gap에 대한 오차))

비계절성도, 계절성도 '분자'는 평균절대값오차(MAE)이므로, 실제 예측값에 대한 오차부분을 계산하게 된다.

'분모'가 조금 어렵게 다가올 수 있는데, 실제 기간 값에서의 오차는 즉, 기간에서의 평균 변동을 의미한다.

 

이해가 잘 안간다면, 아래의 소스로 간단하게 mase를 체험해보자.

pred = np.array([1,2,3,4,5,6,7])
real = np.array([1,4,5,6,8,2,10])

seasonality = 2
print(real[seasonality:])
print(real[:-seasonality])


print('mase : ', np.mean(np.abs(real-pred))/np.mean(np.abs(real[seasonality:]-real[:-seasonality])))

실제 기간 gap에 대한 오차가 real[seasonality:]-real[:-seasonality]가 되는 이유는, seasonality가 1인경우 바로 다음값과의 오차를 구하기 위해서, 2인경우 2번째 다음값과 오차를 구하기 위해서이다.

    => 이 부분은 소스로 구현할때 사용에 부적합한 부분이 있어, 필자가 사용한 loss function에서는 수정되었다.

 

함수식을 loss의 관점에서 해석해보면,

평균오차(분자)가 작으면 작을 수록 loss는 당연 작아지겠지만, MAE와는 다르게 각 실제값에서의 평균 기간 오차를 나누기때문에,

평소에 값이 막 바뀌지 않는 기간 범위라면 (분모가 작다면), 보다 오차가 0에 가까워야지만 (정확하게 예측해야지만), loss가 작아지겠고,

평소에 값이 심하게 바뀌는 기간 범위라면 (분모가 크다면), 보다 오차가 크더라도 (예측을 많이하더라도), loss가 작아질 수 있는

그런 함수가 되겠다.

 

이 부분은 단순히 모델의 실제값과의 오차를 계산하는것에서 나아가,

평소에 안정적인 기간이라면, 보다 안정적으로, 평소에 심하게 오르내리는 기간이라면, 예측을 조금 더 많이하더라도 허용할 수 있도록 하여, 패턴이 뚜렷하지 않고, 갑작스럽게 오르내리는 데이터 예측에 대해서도 어느정도 수용할 수 있도록 모델이 설계될 수 있겠다는 생각이 들었다.

 

한마디로, 과거에서부터 현재까지의 평균 변동폭을 예측값 학습에 있어 살짝 스케일링 보정 가능하겠다는 생각이 들었다. (loss자체가 유연하게 scaling되는 효과를 보게 되니 Mean Absolute 'Scaled' Error라고 볼 수 있겠다.)

 

위에 수학 함수대로의 mase는 단점이 몇가지 있는데,

1. 1 배열에서의 seasonality로만 계산하므로, 7일로 7일을 예측하기 위해서는 real배열에 총 14일의 데이터가 들어가고 seasonality가 7로 적용되어야 한다는 점. (데이터 계산을 특정 index 기준으로 나누어 계산해야 되다보니, 모델 소스 유지보수 및 수정이 번거롭고 생각해야될 점이 많음.)

2. 1 배열에서의 데이터를 나누어서 활용하다보니, GAP이 떨어져 있는 데이터. 예를들면, 1분기와 3분기 데이터의 gap을 활용하고 싶으면, real[seasonality:]-real[:-seasonality] 이 부분을 데이터 전처리 과정에서 잘 발라내야되는 번거로움이 존재함.

3. 데이터를 잘 처리하여, 이슈가 없게 삽입하여도, batch나 k-fold 작업 간 잘못 잘려져 나가면, seasonality로 쪼갤 데이터가 없어 뺄셈이 잘못되어 loss가 nan이 되어버린다.

4. 가장 중요한 점, 이런 공통화 시키기 불편한 계산 방식 때문인지, TensorFlow혹은 Scikit-learn에서 모듈화된 소스를 재공해주지 않는다. (쓸거면 본인의 data 특성에 맞게 직접 작성해야된다.)

 

결국 함수 그대로의 내용을 소스로 옮겨서 쓰는건 힘들겠다고 판단했고,

직접 작성하기에 이르게 된다.

 

참고로 위에 존재하는 단점 4개는 'real[seasonality:]-real[:-seasonality]' 부분에서 생기는 불편함으로, 이 부분을 줄여 seasonal naive forecasting이라고도 부르던데, 이 부분을 직접 소스를 수정하여, 좀 더 유연하게 바꿔놓았다.

    => 결국 예측하고자 하는 대상 기간에 대한 오차값을 구하면 되므로, y_true를 (과거값 실제, 현재값 실제)로 구성하여, 예측 대상 기간의 오차를 계산할 수 있도록 label data를 input하여 처리하였다.

    이렇게 처리하면, 배열 index로 계산하는 것이 아닌, 딱 1:1매핑된 값 간의 계산이 되므로, index에서 짤려 이상하게 계산될 소요도 없다.

 

이렇게 하여, 시계열 예측을 좀 더 보강하기 위해, feature로 들어가던 기간을 같이 예측하게 하는 방식과,

RMSE/MAE가 아닌 MASE를 이용하여 loss 계산 후 기울기 변동을 유연하게 수정하는 것으로, 모델의 예측 정확도가 좀 올라갈 수 있는 가설들을 세워봤고, 그걸 실제로 적용해봤다.

 

글이 장문이 되어, 실제로 소스는 어떻게 작성되었고, 결과는 어땠는지, 여기서 하지못한 추가적인 이야기들은 다음장에서 이어서 설명하도록 하겠다. (data 스케일링 이야기도 못했네...?)

728x90

댓글