개발자의시작

[Pytorch] 11-4 RNN timeseries 본문

머신러닝(machine learning)

[Pytorch] 11-4 RNN timeseries

LNLP 2022. 3. 16. 09:41

이 글은 모두를위한딥러닝 시즌2 https://github.com/deeplearningzerotoall/PyTorch 을 정리한 글입니다.

 

GitHub - deeplearningzerotoall/PyTorch: Deep Learning Zero to All - Pytorch

Deep Learning Zero to All - Pytorch. Contribute to deeplearningzerotoall/PyTorch development by creating an account on GitHub.

github.com

 

이 chapter에서는 RNN을 이용해서 timeseries data를 예측하는 코드를 PyTorch로 구현해본다.

timeseries data는 보통 시계열 데이터라고 부르는데, 일정한 시간 간격으로 배치된 데이터를 시계열 데이터라고 한다. 보통 주가 데이터가 대표적인 시계열 데이터라고 볼 수 있다. 

예시로 일별 구글 주가 데이터를 들 수 있다. 구글 주식의 시작가, 최고가, 최저가, 거래량, 종가를 일별로 가지고 있다. 

이 데이터를 RNN에 넣어보도록 한다. 이 데이터를 넣는 모델을 보면, 7일간의 데이터를 입력받아서 8일 차 종가를 예측하는 구조로 되어있다. 모델을 자세히 보기에 앞서 모델이 전제하고 있는 바에 대해 생각해 볼 수 있다. 이 모델은 8일 차의 종가를 예측하기 위해서 그전 일주일간의 데이터를 보면 될 것이다 라는 전제로부터 출발하고 있다. 물론 될리는 없다. 주식시작에는 여러 가정과 변수들이 존재하기 때문에 실제로 올바른 예측을 할 수는 없지만, 위의 전제를 가지고 출발했다라고 생각하면 된다. 일단 첫 번째 날에 5개의 dimension을 가지고 있는 vector가 첫날 데이터 input으로 들어가게 되면, 이 데이터가 RNN cell에서 처리가 되어 다음 셀에 처리된 정보를 넘겨주고, 두 번째 셀에서는 2일 차의 정보를 5개의 dimension으로 구성된 vector로 입력받고 그 전 날의 데이터를 입력으로 받아 RNN cell에서 처리하여 다음 cell로 넘겨준다. 이렇게 7번 데이터를 유통하고 난 다음에 마지막에 나가는 output으로 8일 차의 종가를 맞추게 된다. 그렇다면 이 네트워크가 8일 차에 종가를 바로 맞춘다고 가정한다. 여기서 출력되어야 하는 vector의 dimension은 1차원의 vector가 될 것이다. 이렇게 되면 문제가 발생하는데, 이 전의 데이터를 유통하기 위한 모든 단계에서의 hidden state도 dimension이 1이 된다. 이것은 모델로서 굉장히 부담스러운 일인데, 5개의 input data를 처리하고 처리된 결과를 종합해서 하나의 값으로 압축해서 다음 cell에게 전달해주어야 한다. 5개의 데이터를 처리하는 것도 어려운 일인데 압축까지 해야 하는 것이기 때문에 쉽지 않은 일이다. 그래서 일반적으로는 데이터를 유통하기 위한 hidden state의 dimension을 충분히 보장해주고, 보장된 hidden state들이 유통이 되고 마지막으로 출력되는 단계에서는 FC(Fully connected) layer를 연결해서 이 layer의 output이 종가를 맞추도록 하는 구조로 구성한다.

 

이것이 일반적이라고 얘기하는 이유는 위에서 언급했듯 hidden state를 하나의 dimension으로 정보들을 유통해야 한다고 한다면 모델에 가해지는 부담이 증가한다. 따라서 데이터를 유통하는 부분과 유통된 데이터로 label을 맞추는 부분을 분리하는 것이다. 이렇게 해서 특정 네트워크에 가해지는 부담을 분산시키는 것이 네트워크를 구성하는 데 있어서 굉장히 중요한 테크닉 중 하나이다. 따라서 위의 예에서는 7일 차의 데이터들이 입력되면서 어떤 특정한 dimension을 가진 hidden state로 값들이 종합되어 유통되고, 이것으로 마지막에 종가를 예측하는 FC layer가 붙어있는 구조로 이루어진다.

 

위의 timeseries 데이터를 처리하기 위해 구현된 코드를 살펴본다. 하이퍼 파라미터를 살펴보면 7일간의 데이터를 살펴보기 위한 것으로 seq_length는 7로 설정한다. 입력으로 들어가는 vector의 크기는 5(시가, 최고가, 최저가, 거래량, 종가), hidden state로는 10(임의의 크기)을 준다. output_dim은 마지막에 FC layer가 맞춰야 하는 종가의 dimension으로 1이다. learning rate와 iterations을 정해주고 데이터를 불러온다. 불러온 데이터를 시간의 역순으로 ordering 해주는 작업을 거친 후(36 line), 70%는 학습 셋에 사용하고 나머지는 테스트 셋으로 남겨두게 된다. 

분할된 training set과 test set에 대해 scailing 작업을 해준다. scaling 작업을 해주는 이유는 다음과 같다. 주가에 해당하는 데이터는 대략 800 정도에 해당하는 값이고 거래량 같은 경우는 대략 백만에 해당하는 값에 해당한다. 모델의 입장에서는 어떠한 input이 들어왔을 때 800 또는 100만 등의 scale로 출력하는 것 또한 하나의 학습 대상이 된다. 일종의 부담이 될 수 있기 때문에 주가나 거래량에 있는 값들을 0부터 1까지의 값으로(같은 범주에 있는 값들의 상대적인 비교만 가능하도록) 전환해준다. 바꾸는 과정은 매우 간단한 방법을 사용하는데, 최고가와 최저가 사이를 선형으로 linear 하게 나누어서 0~1 사이의 값으로 치환해준다. 이렇게 해서 모든 값을 0~1 사이의 값으로 넣어주게 되면 네트워크 입장에서는 scaling은 학습의 대상에서 제외되게 된다. 따라서 학습의 부담을 덜어주는 테크닉이라고 할 수 있다. 이렇게 처리된 데이터를 7일간의 입력과 8일 차의 종가로 나누어 데이터 셋을 만들어주는 작업을 진행하고 이를 PyTorch가 읽을 수 있는 Tensor의 형태로 변환하는 것까지 하게 되면 데이터의 준비가 완료된다. 

어떻게 scaling 하는지, 어떻게 dataset을 구성하는지는 보조 함수들을 참고하면 된다. 

 

본격적으로 Neural network를 선언하는 부분을 확인할 수 있는데, 간단하게 LSTM layer를 선언하여 rnn 변수에 넣어주고 FC layer를 선언하여 실제 prediction을 할 때는, RNN의 결과를 FC layer를 통과하여 return 해주는 것을 볼 수 있다. 네트워크를 선언하면 input_dim, hidden_dim, output_dim, layer 수를 입력하여 간단하게 network를 선언할 수 있다. 네트워크의 출력 값이 실수 값이기 때문에 MSELoss()를 Loss함수로 사용하고 Adam optimizer를 통해 최적화를 수행한다고 선언한다. 

정해진 iterations 만큼 반복하면서 최적화를 진행하고 예측(prediction)과 test set을 plotting 하면 그림의 우측과 같이 나타난다. 학습 결과 굉장히 예측을 잘하는 것처럼 보이는 결과를 보인다.

 

앞서 얘기한 것과 같이 주식시장에는 변동을 일으키는 변수가 굉장히 많아서 우리가 입력으로 사용한 5개의 feature 만으로는 전체 주식시장의 변동을 예측하기 어렵다. 따라서 더 많은 feature가 필요하며, 수많은 정보들을 모델에게 전해주어야만 그나마 변동에 안정된 주가 예측 모델을 만들 수 있을 것이다. 

 

'머신러닝(machine learning)' 카테고리의 다른 글

[Pytorch] 11-3 RNN - longseq  (0) 2022.03.15
[Pytorch] 11-2 RNN hihello and charseq  (0) 2022.03.14
[Pytorch] 11-1 RNN basics  (0) 2022.03.03
[Pytorch] 11-0 RNN intro  (0) 2022.03.03
[Pytorch] 09-4 Batch Normalization  (0) 2022.03.03
Comments