지지플랏의 DataScience

[글또]시계열 Prophet 모형과 하이퍼파라미터 뜯어보기 with 주가데이터 본문

Data Science

[글또]시계열 Prophet 모형과 하이퍼파라미터 뜯어보기 with 주가데이터

지지플랏 2024. 2. 27. 17:23

예상 독자

  • 시계열 데이터 분석을 입문해보자 하는 사람
  • Python의 기본을 알고 있고 머신러닝을 접해본 사람

1. 들어가며

시계열 데이터는 말그대로 시간의 정보를 가지고 있는 데이터를 말합니다.  시간마다 측정된 관측치 값(일일 매출량, 재고량, 판매 수익)등을 예측하기 위한 시도는 과거로부터도 관심이 많았습니다. 미리 정보를 알 수가 있다는 것은 그만큼 경영전략을 미리 세울 수 있는 장점이 있기 때문입니다.  시계열의 메인 관점은 다음과 같습니다. 

 

과거가 미래에 어떤 영향을 주는가?

2. 머신러닝 모델과 시계열 모델의 차이

사실 시계열은 머신러닝의 부분 집합이지만 모델링 과정이 살짝 이질적이기 때문에 따로 공부하는 경우가 많습니다. 본 글에서는 머신러닝과 시계열 모델을 구별해서 명명하겠습니다.

대표적으로 머신러닝을 배운 학생들의 경우 간과하는 것이 머신러닝 데이터의 예제는 대부분 독립변수에 시간이 없는 반면  독립변수가 하나하나 특징의 정보를 가지고 있습니다.타이타닉 데이터의 예로 들면 독립변수가 성별, 나이, 좌석등급 인 것처럼 말입니다. 그런 이유 때문인지 시간이 독립변수인 경우 이질적인 느낌이 드는 경우가 많습니다. 대부분 시계열 데이터는 독립변수는 시간, 종속변수는 관측값 일 뿐입니다. 

머신러닝 모델과 시계열 모델의 차이를 아래에 기술해보겠습니다.

  머신러닝 모델 시계열 모델
종속변수(Y) 수치형, 범주형 주로 수치형
독립변수(X) 다중 변수 가능 단일 변수(주로 시간)
모델 유형 선형회귀, 의사결정나무, 신경망 등 ARIMA, Prophet 등
장점 - 여러 변수간의 관계를 분석 가능
- 비선형 패턴 학습 가능
- 시간의 흐름 포착 가능
- 이해와 해석이 용이
단점 - 시간에 따른 의존성 무시(추세, 계절성)
- 과적합 위험
- 다변량 분석 제한
- 비선형 모델링 제한

3. 시계열 데이터 모델의 종류

1. ARIMA: 가장 많이 사용하는 모델로 데이터의 시계열적 특성(자기상관성*)을 모델링합니다. 비계절적 데이터에 자주 사용됩니다. 확장형으로 계절적 변동성을 포함한 시계열 모델링을 하기 위한 S-ARIMA(seasonal ARIMA)라는 확장형 모델도 있습니다. 

*자기상관성: 서로 다른 두 시점에서의 관측치  사이에 나타나는 상관성. 시계열 데이터는 시간 의존성에 의해서 인접한 변수간의  자기 상관성이 나타날 수 있음.

2. LSTM(Long Shrot Term Memory): 딥러닝 중 순환신경망의 한 형태로 시계열 데이터의 장기 의존성을 효과적으로 학습할 수 있는 장점이 있습니다. LLM 전에 한때 유행했던 알고리즘이지만 요즘은 잘 언급이 안됩니다(ㅠㅠ)

3. Prohet: 계절성, 휴일, 주말(특별 이벤트)을 고려한 시계열 예측을 가능하게 합니다. 사용하기 쉽고 다양한 시계열 데이터에 적용할 수 있는 장점이 있습니다.

4.  XGBoost, LightGBM 등 앙상블 기반 모델: 기술적 지표,  이동평균 등 시계열 데이터의 특성을 이용해 예측할 때 유용할 수 있습니다. 

5. 지수평활법: 계산이 간단하고 구현이 용이하여, 시계열에서 단기 예측을 위해 널리사용됩니다. 실시간 데이터 업데이트에 효율적입니다. 태블로에서 시계열 예측에서 구현되어 있습니다.


4. Prophet 모형

Prophet 은 2017년 메타(구 페이스북)에서 공개한 시계열 예측 라이브러리입니다. 메타가 최근에도 LLM 관련하여 LLama와 같은 sLM 모델도 공개하는등 구글과 더불어서 데이터 사이언스에 기여하는 바가 많은 것 같습니다. 저도 재직 당시에 회사에서 제품 판매량 예측 보고서를 위해서 Prophet 모델을 적용했던 사례가 기억이 나네요. 시계열은 파다보면 끝도 없이 깊게 들어갈 수 밖에 없기 때문에 간단하게 Prophet 모델을 적용하는 시간을 가져보고도록 하겠습니다. 

https://facebook.github.io/prophet/

 

Prophet

Prophet is a forecasting procedure implemented in R and Python. It is fast and provides completely automated forecasts that can be tuned by hand by data scientists and analysts.

facebook.github.io

4.1 .이론

Prophet 모델의 주요 구성요소는 Trend, Seasonality, Holiday 입니다. 이 세가지를 결합하면 아래의 공식으로 나타낼 수 있습니다.

  • g(t):  Trend를 구성하는 요소로 주기적이지 않은 변화인 트렌드를 타나냅니다.
  • s(t): Seasonality 를 구성하는 요소로 weekly, yearly 등 주기적으로 나타내는 패턴을 말합니다.
  • h(t): Holiday 를 구성하는 요소로 휴일과 같은 불규칙한 이벤트를 나타냅니다.(꼭 휴일일 필요는 없고 event라는 점에 주목하세요 예를들어 주가는 휴일에 장이 쉬기 때문에 사용할 수 없는 변수라고 생각할 수 있는 반면, 월/금과 같은날 주문량의 몰리기 마련입니다. 이걸 event로 정의할 수 있습니다.)
  • E(i): 오차항입니다.

 

4.2. 실습

애플의 21년 ~ 23년 주가데이터를 기준으로 1년 주가를 예측하는 실습을 진행해보겠습니다. 

1. 모듈 불러오기

import pandas as pd
import numpy as np
from prophet import Prophet
# import pandas_datareader.data as web
import yfinance as yf
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

2. 주가 데이터 가져오기

start = '2021-01-01'
end = '2023-12-31'
ticker = 'AAPL'

df = yf.download(ticker, start=start, end=end)
df['ds'] = pd.to_datetime(df.index, format = '%Y-%m-%d')
df['y'] = df['Close']
df = df[['ds','y']]
display(df)

3. 주가 데이터 시각화

ax = df['y'].plot(title = ticker, figsize =(12,4))
ax.set_ylabel('Closs price (Won)')
plt.show()

4. 모델 적합

model_prophet = Prophet(changepoint_prior_scale = 0.15, daily_seasonality = True)
model_prophet.fit(df)

5. 향후 1년간의 time stamp 생성

fcast_time = 365 # 365일 예측
df_forecast = model_prophet.make_future_dataframe(periods = fcast_time, freq = 'D')
df_forecast.tail(10)

 

6. 예측 결과 생성

df_forecast = model_prophet.predict(df_forecast)
df_forecast[['ds','yhat','yhat_lower','yhat_upper']].tail()

7. 예측값 시각화

model_prophet.plot(df_forecast, xlabel = 'Date',ylabel ='price($)');

4.3. 하이퍼 파라미터 튜닝

Prophet 모델에서 조정 할 수 있는 파라미터는 Trend, Seasonality, Holiday 3가지로 나눌 수 있습니다.  위의 예측값 시각화 한 값은 이 3가지를 모두 반영한 그래프입니다. 세부 componenet 을 확인하기 위해서 다음 코드를 작성합니다.

model_prophet.plot_components(df_forecast);

 

1) Trend

Prophet 모델에서 기본적으로 Trend와 관련된 파라미터는 changepoint라는 단어가 붙어있습니다. 명시적으로 작성하지 않아도 기본 값이 정해져 있으나 파라미터 튜닝을 위해서 임의의 값을 넣어 줄 수 있습니다. 

changepoint_prior_scale = 0.15

y축 스케일이 작아서 그렇지 우상향하는 그래프의 트렌드를 확인할 수 있습니다. 처음 모델을 수립할때 changpoint_prior_scale을 0.15 설정하였는데요. 이 스케일을 더 크게 설정할 수록  트렌드를 더 디테일하게 학습하겠지만, 너무 디테일하게 학습하면 과적합이 문제가 생길 것으로 예상할 수 있습니다.

changepoint_prior_scale = 0.3

changpoint_prior_scale을 0.3으로 설정하면, y축이 늘어나는데도 불구하고 트렌드 그래프가 좀 더 각진 형태를 확인할 수 있습니다.

Trend 관련 파라미터

Parameter Description
changepoints 트렌드 변화 시점을 명시한 날짜 리스트
changepoint_prior_scale changepoint(trend)의 유연성 조절(default = 0.05)
n_changepoints changepoint 의 갯수
changepoint_range changepoint 설정 가능 범위(default = 0.8)

위 파라미터에 대한 자세한 설명은 다음 깃허브에서 찾아볼 수 있습니다.

https://github.com/facebook/prophet/blob/main/python/prophet/forecaster.py

2) Seasonality

Seasonality는 문자 그대로 4계절을 연상하기 쉬운데 그보다는 주기적으로 돌아오는 변화라고 이해하는게 더 맞습니다. 따라서 파라미터도 연, 주, 일 계절성을 설정할 수 있습니다. 일례로 주가의 경우 배당시기가 오면 주식을 매수하는 경향이 있습니다. 이를 Seasonality에 적용 할 수 있습니다. 

year_seasonality = auto(10) 기본 값
year_seasonality = 20 설정

year_seasonality를 2배로 올렸더니 연간 계절성을 더 많이 학습하는 것 처럼 보입니다. 이 역시 과적합을 조심해야겠네요. 

Seasonality 관련 파라미터

Parameter Description
yearly_seasonality 연 계절성
weekly_seasonality 주 계절성
daily_seasonality 일 계절성
seasonality_prior_scale 계절성 반영 강도(default = 10.0)
seasonality_mode 'additive'(default) or 'multiplicative'

seasonality mode 의 경우 계절성을 합연산인가(additive) 아니면 곱연산(multiplicative)하게 가져갈 것이냐의 차이 입니다. 이부분은  Multiplicative Seasonality 에 자세히 나와있는데 사실 2장의 그래프면 쉽게 이해할 수 있습니다.  대표적인 비행기 승객 수에 대한 데이터와 시계열 예측입니다. 

seasonality_mode = 'additive'

 

seasonality_mode = 'mutiplicative'

비행승객 수는 계절성을 띄는 경향이 있지만 그 계절성이 점차 큰 폭으로 증가하는 경향이 있습니다. 전자 additive의 경우는 1950년에는 계절성을 과대평가하는 반면 1960년대에서는 과소평가하는 경향이 있습니다. 비행기 승객은 점차 꾸준히 발전해왔기 때문입니다. 이 때문에 multiplicative 한 계절성이 더 잘 맞다고 말할 수 있습니다. 

 

3) Holiday

Holiday도 역시 공휴일이라는 event를 추가할 수 있습니다. 간단하게 모델객체에 추가할 수 있습니다. 

model_prophet = Prophet(changepoint_prior_scale = 0.15, daily_seasonality = True)
model_prophet.add_country_holidays(country_name='US')
model_prophet.fit(df)

반면 명시적으로 데이터프레임 등으로 이벤트 날짜를 넣고 싶은 경우 다음 파라미터를 참고하면 됩니다.

Holiday 관련 파라미터

Parameter Description
holidays 휴일 또는 이벤트 기간을 명시한 데이터 프레임
holidays_prior_scale holiday 반영 강도(default = 10)

hoidlays 에는 데이터프레임 객체가 들어가는데 첫 열은 holidays 라는 문자열, 두번째 열은 날짜가 들어갑니다. 또한 공휴일 전후로 이벤트가 있는 경우(주식과 같은 경우) lower_window 과 upper_window 컬럼을 옵션으로 추가하여 공휴일 전후 날짜를 인식하게 만들수 있습니다. holiday 데이터 처리하는데 꽤 시간이 걸릴 것 같네요

공식 github - prophet/python/prophet/forecaster.py
공식 docu의 슈퍼볼 관련 날짜의 예시


5. 출처

[1] https://facebook.github.io/prophet/

[2] 시계열 예측 패키지 Prophet 소개, Hyperconnet 

[3] Prophet을 이용한 주가 예측


글또 9기 글 모음