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
이번에 다룰 포스트는 약간.... 시도적으로 돌리다가 잘 된 부분을 경험에 입각해서 작성하였다.
사실 5번 작업까지 진행하면서, 점점 나아지는 것은 확인이 되었지만, 현업에 적용하기엔 터무니 없이 부족한 평균오차범위였다.
현업에서 요구했던 평균 오차범위는 +-5%내외면 사용하겠다 였다. (뭐 나중가서는 조금씩 조정이 되었지만...)
이 시기에 나는 막연하게 Layer를 추가하고, Units 수를 변경하고, return_sequence와 return_state를 중간에서 빼서 옮겼다, 붙혔다를 반복하며, 이게 효과가 있을까? 저게 효과가 있을까? 하는식의 경험적 반복시도만 계속되고 있었다.
이쯤에 가장 고민한 것은 이거였다.
Seq2Seq를 결국엔 해야 하는가?
--- 나의 걱정
Auto-Encoder(줄여서 AE)를 사용한다는 것 자체가, 결국 원본 특징으로 사용될 데이터들의 어느정도 재가공이 이루어질텐데, 그게 학습에 긍정적인 영향을 미칠지, 확신이 서지 않았다.
--- 나의 가설
하지만 또 이런 생각도 든게, 어짜피, AE에서 Encoder 부분에서 데이터의 서순을 학습하고, Decoder 부분에서 time-series를 재생성시키면서, 결국 Y값이랑 가장 근사하게 재생성 시키는 모델을 만든다면, 그게 결국 잘 맞추는 lstm 모델이지 않을까? 하는 생각.
Auto-Encoder? 그냥 모델만 바꿔서 돌리면 금방이지!, Reconstruction LSTM Auto-Encoder(줄여서 RAE) 형태로 개발하여, '나의 가설' 부분이 실제로 맞아 떨어지는지 빠르게 확인하기로 했다.
- 실제로 작성된 소스 예시 -
model = Sequential()
model.add(LSTM(5, return_sequences=, input_shape=(past_history, x_concat_data.shape[2])))
model.add(LSTM(4, return_sequences=))
....레이어수 기재 불가
model.add(RepeatVector(past_history))
....레이어수 기재 불가
model.add(Bidirectional(LSTM(4, return_sequences=)))
model.add(Bidirectional(LSTM(5, return_sequences=)))
model.add(TimeDistributed(Dense(6, activation=())))
# model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(TimeDistributed(Dense(7, activation=())))
# model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(TimeDistributed(Dense(8, activation=())))
# model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(TimeDistributed(Dense(future_target)))
if summary_print == 0:
model.summary()
return model
Units 개수와 return_sequences 여부, return_state 여부, activation 펑션 등은 실제 운영되고 있는 소스이기에 정확하게 기재하지 않았다.
본인이 가지고있는 Dataset과 예측하고자 하는 결과값에 가장 적합한 형태를 선택하여 활용하도록 하자.
필자는 RAE를 사용하여 잘 되었음을 시사하고 싶을 뿐이다.
(참고로 뒷부분에만 bi-lstm으로 구성해주는 것이, 학습에서 더 좋은 효과를 보였다. 다만 bi-lstm 사용시 output dim에 대한 부분을 잘 고려하여, 대칭형 AE가 잘 만들어지도록 설계하자.)
뭐 곁다리로 설명을 좀 더 해주자면 return_sequences와 return_state의 관계는 이렇게 설명지을 수 있겠다.
return_sequences / return_state = False | |
True return lstm_output | False return lstm_output |
모든 시점 hidden_state (batch_size,time_step,units_output) |
마지막 시점 hidden_state |
return_state = True | |
모든 시점 hidden_state (lstm_output) / 마지막 시점 hidden_state / 마지막 시점 cell_state (batch_size,time_step, units_output), |
마지막 시점 hidden_state (lstm_output), (batch_size, units_output), |
여기서, return_sequences=False, return_state=True일때 첫번째, 두번째 output parameter는 동일한 값을 가진다.
lstm은 cell에서 x가 결국 hidden state와 함께 가중치가 적용되서 순차적으로 학습이 되므로,
hidden state는 이전 시점에서의 특성값이라고 보면 되겠고,
cell state는 그래서 활성화 함수를 적용시켰을때, 해당 셀이 유의미한지, 그렇지 않은지를 나타내는 상태값이다.
hidden_state와 cell_state의 인위적 활용에 대해서는,
이전상태는 이랬고, 셀의 중요한지여부(?) 가중치정보(?)를 계속 이어붙혀서 학습해나갈지 말지 판단해보도록 하자.
그리고 Attention을 잘 이해하고 활용하려면, 초기에 hidden_state와 cell_state의 이해관계를 잘 잡아놓는 것이 중요하다!
(참고 : rueki.tistory.com/113)
Dense Layer같은 경우에는, 있는 경우에 정확도가 더 좋고, loss 수렴이 빨리되어서 넣어두었다.
결과는 이랬다.
이전장과 비교해보자.
BI-LSTM만 주구장창 쌓았을때보다 모델이 좀 더 예측을 잘해졌으며, 이제 슬슬 좀 팔아먹을 각이 보이기 시작했다...ㅋㅋㅋ
이쯤에서부터는 layer에 대한 고민은 더 많이 하지는 않았고, 적당히 layer 개수와 units만 조금 조정해서 최적의 조건을 찾아주는 작업만 진행했다.
그 이후에는 모델 아키텍쳐에는 문제가 없다고 판단되어, 이제 loss펑션과 데이터를 scaling하여 테스트하게 된다.
Scaling은 사실 제일먼저 했어야 하는 작업 아니냐? 할 수 있지만,
Scaling하면 도중에 확인하는 소스를 짤게 너무 번거로워서, 일단 안한상태로 트렌드를 잡는 모델을 빠르게 만들어, 보고가 어느정도 가능할 수준인지를 판단해보고, 고도화의 느낌으로 접근하였다.
'딥러닝으로 하루하루 씹어먹기' 카테고리의 다른 글
LSTM으로 수요 예측하기 - 8장 (MASE 추가적인 이야기, 그 전에 Data Scaling부터...) (0) | 2021.04.22 |
---|---|
LSTM으로 수요 예측하기 - 7장 (Mean Absolute Scaled Error-MASE) (5) | 2021.04.21 |
막간 - 정리한거 찾다가 발견한 눈물의 대똥꼬쇼 (3) | 2021.04.12 |
LSTM으로 수요 예측하기 - 5장 (K-Fold 사용) (6) | 2021.04.12 |
LSTM으로 수요 예측하기 - 4장 (BI-LSTM 사용) (7) | 2021.04.07 |
댓글