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

LSTM으로 수요 예측하기 - 8장 (MASE 추가적인 이야기, 그 전에 Data Scaling부터...)

by Yoo Sung Hyun 2021. 4. 22.
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

 

2021.04.21 - [딥러닝 일기] - LSTM으로 수요 예측하기 - 7장 (Mean Absolute Scaled Error-MASE)

 

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

1. 시간별로 데이터 전처리 / Not Scaled 2. 일반 lstm 3레이어 정도(?) 3. 이후 data도 중요하다고 생각듬 4. BI-LSTM 사용 5. 데이터가 너무 없어 K-Fold 적용 6. Layer만 주구장창 쌓다가 AutoEncoder 활용..

shyu0522.tistory.com

글에서 이어집니다....

 

Data Scaling 이야기를 이전편에서 했어야했는데, 신나게 MASE 얘기만 하다가 깜빡하고 놓쳐버렸다.

간단한 이야기니까, 빠르게 이야기하고 넘어가도록 하겠다.

 

사실, 내가 발행한 글들을 흥미롭게 읽고있는 수준의 독자라면, 데이터 스케일링에대해서 모를리가 없다고 생각한다.

연속성의 변수들을 다루다보면, 어떤 숫자는 1000자리, 어떤 숫자는 10000자리, 어떤 숫자는 1자리 일 수 있다.

회귀문제에서 이런 데이터의 범위차이가 큰 경우, 1000이 1001이 되는 것만 보면 큰 숫자 차이가 아니지만, 1이 2가 되는 것은 똑같이 1이 증가했지만, 후자는 2배가 변화되는 것으로 판단할 수도 있다.

(물론, 이는 전체 데이터 셋의 범주에 밀접한 연관을 미치지만, 다이나믹하게 하여 설명을 좀 더 편하기 위해 이렇게 표현했다.)

단순히 학습순간만을 보지 않더라도, 실제 운영에서 학습에서 사용되지 않은 엄청 큰 데이터가 들어오면, 모델이 강하게 발산할 여지가 분명히 존재한다.

(물론, 이는 스케일링을 해도 똑같이 존재하나, 하지 않는 것보다는 안정적일 확률이 높다.)

 

이런문제들을 미연에 방지하고, 0으로 수렴해버리거나 완전히 발산해버리는 케이스들을 안정적으로 가져가기 위해서, 우리는 Data Scaling이라는 Data Preprocess 작업을 거쳐야만 한다.

(경험상, 데이터들을 EDA할때, 별로 큰 차이가 나지 않는 연속형 데이터 범주군 안에서는, 오히려 스케일링을 하지 않는게 좋은 정확도를 가지는 경우도 있었다. 단, Train-Test 검증과정 한정으로...)

 

대부분 통상적으로는 연속형 데이터 컬럼들은 Data Scaling을 하는 것이 하지 않는 것 보다 더 좋은 모델안정성을 가지고 있다고 생각한다.

 

scaling은 scikit-learn 메소드로 아주아주 쉽게 변환하고, 다시 되돌릴 수 있다.

유의해야 할 점은, 통상적으로 나누는 80:20 train:test set에서, train set로만 fit, transform을 해야지, test set까지 fit에 들어가버리면, test 결과가 현실 운영 반영 시 결과와 차이가 커질 수 있다. (test는 최대한 현실에서의 문제와 비슷한 상황에서 해야 투명한 결과를 얻을 수 있다.)

 

scaling을 수행하는 객체를 scaler라고 표현하겠다.

scaler는 아래와 같은 종류들이 있다.

https://scikit-learn.org/stable/modules/classes.html#module-sklearn.preprocessing

 

API Reference — scikit-learn 0.24.1 documentation

 

scikit-learn.org

scaler라고 된 애들이 scaler이다.

나는 개발자 가이드를 주로 많이 활용하는 편인데, 위에 scikit-learn에서 지원하는 것들이 잘 명시되어 있으며, 본인만의 scaler를 custom하여 사용할 수도 있다.

 

scikit-learn.org/stable/modules/preprocessing.html

 

6.3. Preprocessing data — scikit-learn 0.24.1 documentation

6.3. Preprocessing data The sklearn.preprocessing package provides several common utility functions and transformer classes to change raw feature vectors into a representation that is more suitable for the downstream estimators. In general, learning algori

scikit-learn.org

해당 아티클의 custom transformers를 확인해보기 바란다.

 

뭐 볼게 많으면 귀찮고, 보기도 싫어지니 그냥 내가 많이 쓰는 scaler들은 이런게 있다.

  1. StandardScaler
    • 각 Feature의 평균을 0, 분산을 1로 변경한다. 모든 특성들이 같은 스케일을 갖게 된다.
    • 내가 가장 평범하게 가장 먼저 시도해보는 scaler
  2. RobustScaler
    • 모든 특성들이 같은 크기를 갖는다는 점에서 StandardSclaer와 비슷하지만, 평균과 분산 대신 median과 Quartile을 사용한다.
    • Quartile을 사용한다는 점에서 이상치에 영향을 적게받는다는 특징이 있어서, 이상치 한 두번을 예측하지 못하더라도, 주로 안정적인 Data Pattern을 가지는 예측을 위한 Dataset에서 주로 활용한다.
  3. MinMaxScaler
    • 모든 Feature가 0과 1사이에 위치하게 된다. 데이터가 2차원 셋일 경우, 모든 데이터는 x축의 0과 1사이에, y축의 0과 1사이에 위치하게 된다.
    • AutoML을 사용하게되면 StandardSclaer와 더불어 가장 비교를 많이하게되는 일반적인 Scaler이다. MinAbsScaler도 있는데, AutoML쓰면 그냥 시간만 많으면 Pipeline 만들어놓고 다 때려넣고 돌려보면 되는지라, 솔직히 그냥 시간만 많으면 아무생각없이 다때려넣고 돌려보는 놈중에 하나다.
  4. Normalizer
    • 유클리드 거리가 1이되도록 각 row를 하나하나 조정한다. 
    • StandardScaler와 결과는 거의 비슷한 양상이 나오는 경향이 있던데, 경험상 StandardScaler는 모든 데이터셋의 평균과 분산을 활용하지만, Normalizer는 각각의 row의 컬럼을 기준으로 하다보니, 전체 값 범주대비 좀 더 '독립적(?)'이다. 이 녀석도 StandardScaler와 항상 비교하게된다.

뭐 pipeline, gridsearch, model_selection을 사용하지 않고, 아주 일반적으로 사용한다면,

from sklearn.preprocessing import MinMaxScaler, StandardScaler,RobustScaler
scaler = StandardScaler()
# scaled_list = ['resv_drive_st_cnt','resv_drive_end_cnt','resv_creat_id_cnt','i_call']
scaled_list = ['mon','hour','i_call_x']

fitted_scaled = scaler.fit(train_df[scaled_list])

scaled_train_df = pd.merge(train_df,pd.DataFrame(fitted_scaled.transform(train_df[scaled_list]), columns=['scaled_mon','scaled_hour','scaled_i_call_x']), left_index=True, right_index=True, how='left')
scaled_test_df = pd.merge(test_df,pd.DataFrame(fitted_scaled.transform(test_df[scaled_list]), columns=['scaled_mon','scaled_hour','scaled_i_call_x']), left_index=True, right_index=True, how='left')

 

이와같은 방법으로 활용할 수 있으며,

  • fit : 지정된 데이터셋을 scaler의 기준에 맞게 빵판을 만들어 놓는다.
  • transform : 제공된 데이터셋을 fit으로 만들어진 빵판에 맞게 계산해서 적용한다.
  • fit_transform : 빵판을 만들면서, 적용한다.
  • inverse_transform : 빵판에 맞춰놓은 것을, 다시 원본으로 변환한다.

scaler의 자세한 활용방법에 대해서는, scikit-learn의 각각의 개발자 가이드를 찾아보는게 편하다. 설명도 잘되있고 예시도 좋다.

StandardScaler 예시,

scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html

 

sklearn.preprocessing.StandardScaler — scikit-learn 0.24.1 documentation

 

scikit-learn.org

지정, 제공 dataset은 pandas던 numpy던 다 적용되니 엄청 편리하다.

 

유용하게 사용하길 바라며, 다음 시간에 못다한 mase 얘기를 끝내도록 하겠다.

728x90

댓글