prophet은 페이스북에서 만든 시계열 예측 라이브러리이다. 시계열을 예측하는 데 쓰이는 모델들은 ARIMA, SARIMA, LSTM, ES 등등 다양하게 존재하지만 Prophet의 장점은 누구나 어렵지 않게 조절이 가능하다는 데 의의가 있는 것 같다.
prophet은 계절효과가 강하면서 여러 시즌의 과거 데이터가 있는 경우에 가장 잘 작동한다고 하는데, 실제로 해보니 트렌드를 정말 잘 반영하여 예측하는 것을 볼 수 있었다.
prophet의 구성 요소는
이렇게 4가지로 요약할 수 있다.
prophet을 사용하는 것은 아주 간단하다. 다른 라이브러리들처럼 install - import 순서대로 진행하면 되는데 아주 간단한 문제가 있다.
바로 패키지 이름이 변경되었다는 것인데, 일단 전에 설치할 때에는 fbprophet이라서 설치 시 fbprophet이라고 적고 import 할 때에는prophet으로 적었어야 했지만 현재는 prophet으로 바뀌었다. 그래서 import 할 때에도 Prophet도, fbprophet도 아닌 prophet으로 적어야 맞다.
아나콘다 프롬프트에서
conda install -c conda-forge prophet
를 해주면 정상적으로 설치가 되는데, 실제로 import를 하려고 하면
이렇게 plotly가 문제를 일으킬 수 있다. 이럴 때에는 간단하게 다시 plotly를 설치해주면 된다.
conda install -c plotly ploty
이렇게 plotly까지 설치하면 무사히 import가 된다.
prophet은 sklearn 모델 API를 따르기 때문에 Prophet 클래스의 인스턴스를 만든 다음 fit - predict를 통해서 간편하게 사용이 가능하다.
다른 모델들과 다른 점은 prophet에 들어가야 할 열이 2개라는 점과 두 열이 ds와 y라는 컬럼명을 가지고 있어야 한다는 점이다. 특히 ds의 경우에는 YYYY-MM-DD 또는 YYYY-MM-DD HH:MM:SS의 형식으로 맞추는 것이 좋다고 한다.
from prophet import Prophet
m = Prophet()
m.fit(df)
사용법은 다른 sklearn모델들과 같이 인스턴스 생성 -> 데이터프레임을 넣어서 fit을 하면 된다.
이 경우 사용할 수 있는 다양한 파라미터들이 있는데, 이번에 회사에서 사용하면서 가장 유용하게 사용한 것이 바로 holidays 피쳐이다. 그래서 이번에는 이 내용을 조금 중점적으로 설명해볼까 한다.
holidays피쳐를 사용할 수 있는 방법은 두가지인데,
나라의 공휴일들을 이용하라면 이미 제공되고 있는 나라에 포함되는지 확인 후 add_country_holidays의 country_name에 해당하는 나라의 이름을 적으면 된다.
m = Prophet()
m.add_country_holidays(country_name='KR')
m.fit(df)
빌트인 컨트리 홀리데이라고 해서 과연 한국도 있을까? 하고 찾아봤는데 꽤 많으면서 적은 나라의 국경일들이 등록되어 있었다. 다행히 한국도 있어서 'KR'로 바로 사용이 가능했다.
사용가능한 나라 및 코드 목록
Brazil (BR), Indonesia (ID), India (IN), Malaysia (MY), Vietnam (VN), Thailand (TH), Philippines (PH), Pakistan (PK), Bangladesh (BD), Egypt (EG), China (CN), and Russian (RU), Korea (KR), Belarus (BY), and United Arab Emirates (AE)
어떤 공휴일들이 등록이 되어 있는지 확인하려면, 학습한 모델에 train_holiday_names를 사용하면 된다.
가장 놀랐던 점은 설날과 추석에 앞뒤로 1일에 대한 내용이 있었다는 점과 아직 다 들어간 것 같지는 않지만 Alternative holiday(대체공휴일)에 대한 내용이 있다는 점이었다. 지금 보니 식목일 같은 경우는 수정이 되어야 할 것 같다.
만약 위에서 소개한 이미 등록된 공휴일이 마음에 들지 않거나, 회사 자체적으로 특별한 이벤트가 있어서 수요를 견인할만한 다른 요인이 있었던 날이 있다면 따로 설정이 가능하다.
이런 경우 홀리데이의 정보를 가진 데이터프레임이 필요한데, 어떤 holiday인지를 나타내는 컬럼 하나와 그 날짜가 언제인지가 있어야 한다. 이 때 기억해야 할 점은 예측까지 생각한다면 날짜를 넣을 때 예측값에 포함되는 날짜도 넣어야 한다는 점이다.
holidays = pd.DataFrame({
'holiday': 'playoff',
'ds': pd.to_datetime(['2008-01-13', '2009-01-03', '2010-01-16',
'2010-01-24', '2010-02-07', '2011-01-08',
'2013-01-12', '2014-01-12', '2014-01-19',
'2014-02-02', '2015-01-11', '2016-01-17',
'2016-01-24', '2016-02-07']),
'lower_window': 0,
'upper_window': 1,
})
위의 코드를 예로 든다면
학습은 2015년도까지(2015-01-11)하고 예측을 2016년 하려고 하는 경우에 바람직한 코드이다. 미래 예측하려는 2016년도 playoff기간까지 들어있기 때문이다. 하지만 만약 2017년도를 예측하려고 한다면 그건 2017년도 예측치에 playoff에 대한 영향이 들어가지 않을 것이기 때문에(날짜를 특정하지 못하므로) 이벤트에 대한 영향을 제대로 주지 못하게 된다.
그리고 데이터프레임을 만들 때 이전 / 이후의 영향 정도도 설정할 수 있다. 예를 들어서 위의 코드에서는 upper_window에 1로 되어 있는데 그렇다면 위에 ds에 적어놓은 일 하루 이후까지 그 영향을 포함한다고 보면 된다. lower_window를 설정할 때에는 음수로 적어주면 된다. 크리스마스의 경우에는 다음날인 26일보다는 이전날인 24일이 더 크리스마스의 영향을 많이 받으니 크리스마스를 홀리데이로 설정할 때에는 lower_window를 -1로 해주면 된다.(물론 크리스마스의 경우는 1번에서 설명한 build-in holidays를 사용하면 이미 들어가 있긴 하다.)
그리고 당연하게도 1번과 2번 방법을 모두 사용할 수 있다.
m = Prophet(holidays = hoildays) # 2번
m.add_country_holidays(country_name='KR') # 1번
예측을 하기 위해서는 미리 예측을 어디까지 진행할건지 기간을 설정해야 한다.
future = m.make_future_dataframe(periods=365)
future.tail()
make_future_dataframe을 이용해서 쉽게 만들 수 있는데, periods에 원하는 기간을 넣어서 생성하면 된다.
forecast = m.predict(future)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
그리고 predict를 이용해서 예측하면 되는데 이 때 forecast에 굉장히 많은 정보가 들어간다.
물론 이 외에도 밑에 쭉 많이 들어가있다.
그렇기 때문에 가장 필요한 ds(날짜), yhat(예측값), yhat_lower(예측하한값), yhat_upper(예측상한값) 이렇게만 보는 것 같다.
holiday에 대한 설정이 굉장히 간편해서 아주 재미있었던 prophet
이벤트로 인해서 매출이 커진 경우 어떻게 처리해야할지 고민을 했었는데, custom holidays로 한 번에 넣어버리니 너무 좋았다.
이 외에도 위클리, 먼쓸리 등등 여러 시즈널리티 조절 옵션들이 있는데, 해당 사항을 조금 더 공부해봐야겠다.