데이터분석/Machine Learning

모든이들을 위한 Facebook Prophet Paper 쉬운 요약정리

늘근이 2018. 6. 5. 23:26

이글에서 분석해볼 paper는 [Forecasting at Scale] 으로, Facebook의 신기방기한 시계열 분석 라이브러리인 Prophet에 대한 설명이 있는 paper입니다. 논문으로는 20페이지가 넘어 읽기가 불편(?)할수 있어 제가 대신 읽어보겠습니다. peer-reviewed가 되어있지 않다고 되어있지만, 현실에서 미치는 라이브러리의 현재 파급력으로 보아 충분히 볼만한 가치가 있어보입니다. 저작권을 살펴보니 냅다 사용해도 괜찮네요.

이를 살펴보게 된 이유는, KDD2018 미세먼지 예측에서 상위권에 포진한 랭커가 날씨 예보정보를 전혀 쓰지않고 과거정보만으로 냅다 미세먼지 예측량을 맞추게 되는 방법중 하나가 바로 이 Prophet library이기 때문이였기 때문입니다. 

이 글에서 대부분의 내용은 paper에서 언급하는 내용이며, 몇가지 이해를 돕기위한 이미지 몇개만 인터넷에서 찾아서 붙여놨으니 살펴보시고 필요하다면 원래 paper를 찾아보면 될 듯합니다. 링크는 아래와 같습니다.

https://peerj.com/preprints/3190.pdf

저자는 Sean J Tay와 Benjamin Letham 두명입니다.

 우리나라 국적의 회사도 이렇게 세상에 영향을 미치는 뛰어나거나 실용적인 paper도 발표하고 존경도 받으면 좋을것 같다는 생각이 듭니다.

초록은 현재 신기하게도 현재 시계열의 전문가가 많이 없다는 점을 강조해서 말하고 있다는 점이 눈에 들어옵니다. 한국이나 미국이나 마찬가지인듯 싶습니다. 그래서 아무나 쉽게 만질수 있는 business-time series 도구를 만들었다! 라고 하는 점이 인상적입니다.

시계열분석은 실제 생산관리나 수요예측을 위해 특별히 많이 쓰게 되는데, paper에서는 다음 두가지 점에 있어서 한계가 있다고 지적합니다. 

1) 완전자동화 되는 시계열은 튜닝하기가 어렵다는점

2) 기업 도메인 지식이 뛰어난 사람은 시계열에 대한 지식이 부족한점.

시계열을 통한 예측은 특히나 실무에서 굉장히 수요가 큰데도 불구하고 품질이 그다지 좋지 않은 편입니다. 그래서 paper는 scale(컴퓨팅 파워를 뜻하는것이 아닌, 모델자체의 확장가능성에 대한 개념)이 가능한 시계열을 만들겠다는 원대한 포부를 밝힙니다. 

최대한 많은 사람들이 쓸 수 있고, 여러 feature들을 고려할 수 있는 누구나 만질 수 있는 시계열 도구를 제공하는데 목적이 있습니다. 

analyst-in-the-loop, 즉 분석가들은 필요한 모델링과 그 결과를 살펴보는것으로 족하고 나머지 피곤한 작업들은 도구가 알아서 해주도록 하는것이 목적이겠죠. 그렇다면 시계열에 들어갈만한 요소들은 도대체 무엇이 있을까요?

위는 페이스북의 여러 이벤트, 친구신청이나 여러 상호작용을 점으로 나타낸 그래프인데 여기에는 어떤 효과가 숨어있을까요. 자세히 살펴보면 눈에보이는 연도, 요일, 그리고 잘 살펴보면 연말 효과, 시즌효과등도 숨어있을것입니다. 심지어는 물건이 새로 출시되거나 할때 트렌드가 완전히 (!) 바뀌는 경우가 생깁니다. 

Prophet이 아닌 기존의 방법들을 소개하자면 아래에 잘 나타나 있습니다.


위에서부터 차례대로 제일 일반적인 auto.arima 를 이용한 방법, 그다음은 ets는 지수평활법을 이용한 방법, seasonal naive 방법, tbats (주, 년도 계절성 고려) 하는 모델입니다. 

arima 모형이 좀 특이한 편인데, 계절성을 잘 포착하지 못하는 모습을 보여주고 있습니다. ets와 snaive는 좀더 장기적인 안목없이 직선만 찍찍 그어놨구요. 이러한 현상이 나왔을때 바로 고객한테 들고가는것은 위험한 행위입니다. 바로 몇가지 파라미터들을 바꾸면서 튜닝노가다를 시작해야할수도요. 

arima의 경우, 최대차분갯수, 자기회귀, 이동평균 세 부분을 조정가능한데 이부분이 잘 모르는 사람들에게는 쉽지 않을거라고 paper에서는 분석하는 사람들을 쪼오금 무시(?)합니다. 역시 페이스북 연구원들... 영리한데?

어쨌거나 네가지 모델 모두 제일 끝쪽의 데이터의 흐름은 잘 포착하지도 못하고 있는데, prophet은 이러한 부분을 잘 포착해주는지 한번 살펴보면 되겠습니다. 

Prophet은 Harvey & Peters 1990의 기본 적인 세개의 요소를 따릅니다.

g(t)는 반복적인 요소를 가지지 않은 트렌드. s(t)는 요일 혹은 연 계절성과 같은 반복적인 변화, 그리고 h(t)는 Holiday와 같이 가끔씩 불규칙하게 영향을 미치는 요소입니다. e는 정규분포를 따르는 잔차라고 가정합니다.

이는 GAM 모델 (Generalized Additive Model) 과 비슷한데, 뭔가 새로운것이 발견되었을때 다시 모델을 쉽게 훈련할수 있다는 장점이 있습니다. (L-BFGS참조) 따라서, 페이스북이 만든 Prophet이라는 모델도, 위처럼 뭔가 라인을 하나 기가막히게 그리는데 초점을 맞추고 있지, ARIMA처럼 내부 데이터 구조가 어떻게 생겼는지에 중점을 두고있지는 않다고 합니다.

이렇게 해서 얻는 이득은 아래와 같은데요,

- 유연성 : 계절성과 여러 기간들에 대한 예측을 쉽게 모델에 적용할수 있습니다. 분석가들은 여러가지를 해볼수 있겠죠.

- ARIMA모델과 다르게, 모델을 차분해서 정규화 시킬필요도 없고 결측치들을 굳이 구겨넣을 이유가 없습니다.

- 훈련은 빠르고 분석가는 여러가지 상세한 모델 스펙을 탐험할수 있습니다. 샤이니와 같은 어플리케이션에서요!

- 결국에는 회귀분석과 같은 느낌이기 때문에 좀 어렵고 생소한 시계열 분석등보다 빠르게 적응할수 있는 측면이 있습니다.


g(t) : Trend 


이제, 실무자들이 겪은 페이스북에서의 여러 상황에 대한 모델들을 살펴보도록 합니다. 두가지를 소개하고 있는데 saturating growth model, 그리고 piecewise linear model 두가지 입니다. 이 두개의 모델은 나름의 g(t)를 설정합니다.

먼저 saturating growth model입니다. 페이스북에서 나온 논문인지는 몰라도, (저는 앱이 깔려있지 않지만) 어떤 지역들은 그냥 인터넷 접속이 가능한 사람들이 다 페이스북 유저 아닐까? 라는 물음을 던지면서 아래와 같은 식을 써놓습니다.

C - Carrying Capacity, K - growth rate, M- Offset parameter 

이해를 돕기위해 그래프를 하나 그려보면, 아래와 같은 모양을 띄게 될겁니다.


 


다만, 여기서 C는 인터넷 사용자의 증가에 따라서 충분히 바뀔수 있는 값이기 때문에 C(t)로 교체하고, 성장률또한 지역마다 달라지기 때문에 이를 충분히 반영해줘야 합니다. 여기서 중요한 changepoint라는 개념이 생기는데, 모델에 무언가 변동사항이 생기는 시점을 포착해서 뭔가 조치를 취해야할 때 필요한 항목이라 보면 될것 같습니다. 

예를들어 처음에는 성장률을 k%로 잡았다면 이는 점점 지나면서 changepoint마다 조금씩 조정이 되면서 아래와 같은 형식으로 수정이 될것입니다.

결국 최종적으로 도출되는 식은 이 조정치들을 모두 고려한 piecewise logistic growth model로 탄생하게 됩니다. 여기서 piecewise란, 상황에따라 여러 방정식이 묶이는 경우를 말하는데, 어쨌든 우리는 시간에 따라 조정되는 조정치 a(t)를 가지고 있으므로 동적으로 바뀌게 되므로 piecewise 라는 말이 이해가 될 수 있습니다.

위의의 식이 좀 복잡한데 a(t)는 adjustments를 위한 함수로 보고, 계속해서 성장률이 시간에 따라 바뀔수 있다는 점을 표시한 식입니다. m도 그에맞춰 곡선으로 이어지게 바뀌어줘야하니 똑같이 조정을 해주고요. 

다만, C(t)라는 함수는 대체 어떻게 짜느냐. paper에서 이부분은 슬며시 독자에게 공을 넘깁니다. 월드 뱅크 자료실 이라든지 너의 도메인 지식을 이용하면 되지 않겠어? 라는 말을 던지고 홀연히 설명을 마칩니다. 

결국 중요한건 Prophet에서 사용하는 g(t)라는 항목은 도메인지식이 짬뽕된 아래의 g(t)로 사용할수 있다는것이 중요하다고 말할수 있을겁니다. 예를들어 전자제품의 수요를 때려맞춰야 하는 경우 각종 광고나 날씨에 대한 영업사원들의 노하우가 있다면 시계열에 슬쩍 녹이기가 쉽고, 이를 시각적으로 확인하기도 용이하다를 말하고 있다고 보면 될것같습니다.

하지만, 우리가 미래구간을 예측해야 할때는 사실 이런 changepoint가 어디서 출몰할지 알기가 불가능합니다. Prophet에서는 이러한 changepoint의 등장도 과거와 같이 미래도 adjustment ~ Laplace(0,τ) 의 주기로 나타난다고 가정합니다. 그리고 τ는 이전의 데이터에서 유추 가능한 값이 되겠습니다.


s(t) : Seasonality


시계열은 다른 데이터와 다르게 주기성을 가집니다. paper에서는 푸리에 급수로부터 시작해갑니다. P는 목적에 맞게 연단위라면 365.25를, 일주일 단위라면 7을 넣게 됩니다.

여기서 N을 얼만큼 넣느냐가 이슈가 되는데, 연도기준이라면 N은 10, 그리고 주단위라면 N은 3이 모든 문제에 제일 잘 들어맞는것 같다고 주장합니다. 물론 이 파라미터를 조정할수도 있겠죠.  보통 N이 크면 패턴이 빠르게 바뀌게 되며, N이 작으면 느리게 변하는데 아래의 구글 이미지를 참고하면 될것같습니다.


그리고 이를 풀기위해 행렬식으로 표현하자면,

β = [a1, b1, . . . , aN , bN ] 


에 대해

라는 식을 도출하게 됩니다.



h(t) : Holiday 


사실 실제 비즈니스 상황에서는 제일 중요한것일수도 있는게 휴일여부인데, 다른건 뻔한 측면이 있는 한편 블랙프라이데이나 여타 다른 이벤트들은 크게 기업들의 생산관리나 이윤창출에 영향을 미치게 됩니다. 설날같은 휴일도 범아시아적으로 영향을 미치고 있구요. 

게다가 설날같은경우는 음력으로 정해져서 매일 날짜가 바뀌며, 11월 넷째주 목요일 행사! 와 같이 회사별로 일자가 정해지지 않은 경우도 있습니다. 크리스마스는 매년 같다고 해도 말입니다.

이를 하나하나 코딩에 넣기란 여간 성가신 일이 아닙니다. 하지만, Prophet에서는 이러한 휴일과 방학등의 상황을 잘 이해하고 있으며 아래와 같은 식으로 나타내고 있습니다.

t로 나타내어지는 특정한 시간이 우리의 휴일 리스트 D에 포함되어있음을 확인하고 이에대한 조정이 들어가며, 추가적으로 특정 휴일 주변 날들도 냅다 휴일과 마찬가지의 영향력을 가지게 파라미터 설정도 가능합니다.


Model Fitting

주기성과 휴일에 관한 정보가 행렬 X에 준비되어있고, changepoint에 대한 정보가 행렬 A에 잘 마련되어 있으면 아래와 같은 몇가지 심플한 코드로 결과를 꺼내볼 수 있습니다.

(참고로 Stan구현물은 R과 Python등등을 지원합니다. http://mc-stan.org/)

이러한 간단한 구현물로 낸 결과는 아래와 같습니다.

맨 위에서 봤던 ARIMA 등등과 같은 시간의 자료로써, Prophet은 주단위, 연단위 주기성을 잘 포착하고 있는것으로 보입니다. 다만 2014년을 보면 2013년을 통해 조금은 오버피팅 된 느낌이 있긴합니다. 


모든 사용가능한 데이터로 트렌드를 나타낸 그래프로, 점선으로 표현된 부분은 샘플이 없는 예측부분입니다.

아래는 각각의 요소별로 어떠한 변화가 있나 확인해 볼수있는 그래프입니다.


실제 R로 해봐도 그냥 냅다 코드만 부르면 끝나더군요. (실습부분은 나중에)


분석가는 그래서 무엇을 할수 있나?

paper에서 Prophet이 자주 쓰이기를 바라는 분석가의 정의는, 시계열과 통계를 잘 모를수도 있지만 물건이 언제 팔리고 어느 공휴일에 얼만큼 나가는지 정말 잘 알고 있는 우리네 회사원과 같은 '업무'경험이 풍부한 사람입니다. 

- Capacities (시장 총 수요)

- ChangePoints (상품이 바뀌거나 신제품이 출시될 때)

- Holiday and Seasonality (판매량에 영향을 많이 미치는 휴일 등)

- Smoothing Parameter(주기마다 변동을 얼마나 나타내야 하는지)

우리들은 이에 대한 조건들을 바꿔서 계속 Prophet을 실행해볼수 있습니다. 

재미있게도 이 paper에서 강조하는 포인트는 분석가는 그럴듯한 시각화 툴을 가지고 이러한 파라미터들을 쉽게 조정하여 플로팅하고 다시 재모델링 해보는 과정을 빠르게 반복하기를 추천한다는 것입니다.

τ 를 바꿔서 주기성을 자주 반영하게 해준다던지,

σ 를 바꿔서 주기성을 강하게 반영하게 해준다던지, 

등을 말입니다. 

이러한점은 맨위의 그림에 있는것처럼 도메인 지식을 가지고 있는 사람이 직관을 가지고 해야 더 나은부분이 있을 것입니다. 현란한 수식들이 등장하지만, 어느정도의 기본 파라미터들이 무엇을 하는지만 알고 바로 조정을 하면서 모델을 만들면 쉽게 도메인 전문가가 전문지식을 넣을 수 있다고 주장합니다. 

페이스북이 만든 Prophet은 [transform - visualize - model] (Wickham & Grolem 2016) 과 비슷한 접근법을 사용했다고 하여 참고할만 합니다. 인간이 찾아낸 인사이트가 코딩이 되어 다시 모델이 되는 반복적인 모델이라고 하네요.

Prophet은 인간의 직관은 극대화시키고, 자동화시키는 부분은 자동화시키는 편리한 툴이라고 할수 있겠습니다.


Model Evaluation


여기서 마무리 되어야 할것 같지만, 모델을 만드는데 있어 제일 중요한 부분은 forecast결과를 평가하는 부분이라고 합니다. 즉, 평가를 한후 좋은지 나쁜지 빠르게 확인할수 있어야 이것이 loop가 되면서 다시 좋은 모델을 만들기 위한 자양분이 될것이기 때문입니다.

일단 현란하게 수식한번 적어주지만 별게 아닙니다. 

201810주차(T)까지 자료가 있고 이후에 8주차(h)를 더 예측하는데 그 사이 거리입니다. 페북은 MAPE(Mean Absolute Percentage Error)를 해석상 선호한다고 합니다.

오차항은 위와같은데, 몇가지 가정은 있습니다. 지역적(locally) 평활화가 되어있어 에러가 있으면 예측 전구간에서 일정하게 발생하여야 한다는점, 그리고 시간이 지날수록 (h) 예측력은 조금씩 떨어져야 한다는것입니다. 

이 paper에서는 에러를 체크하기 위해 Simulated Historical Forecasts 방법을 소개합니다. 사실 이 방법은 누구나 생각할 수 있는 상식적인 방법입니다.

데이터가 시계열이고 막 섞을수가 없기 때문에 여러가지 데이터 절단점에서 생성되는 forecast데이터를 가지고 측정할수 있습니다. 데이터 전역에서 윈도우 사이즈가 작은 여러 데이터셋을 가져올수 있는데 이러한 것들을 모아 예측을 한다면 여러 예측을 해볼수 있습니다. 여러번 측정하면 에러는 어느 지점으로 수렴할것입니다.

사실 이 윈도우가 작으면 에러가 너무 막 바뀌고 윈도우가 너무 크면 사실 계속 돌려도 어차피 들어있는 데이터가 비슷할것이기 때문에 그냥 경험상 이들은 대충 전체기간의 반절정도를 대상으로 사이즈를 잡고 나올수있는 예측치를 측정한다고 합니다.

그리고 또 하나 팁이 있다면 트렌드를 좀더 확실하게 보기위해 산점도를 사용하며 라인차트는 이용하지 않는 편이라고 합니다.

이렇게 해서 열심히 뽑아낸 결과는, 다음과 같습니다.

역시 에러율에서 제일 낮은게 prophet입니다. auto.arima는 파라미터를 수동으로 설정하지 않는한은 에러가 굉장히 높습니다. (수동으로 파라미터 튜닝이 당연히 가능하지만 여기서 주인공은 prophet이므로)

마지막으로 페북 연구원들이 놓치지 않고 친절하게 가르쳐주는 모델 수정법도 보너스로 있습니다.

- Baseline 모델과 비교하여 뭔가 떨어져보일때는 trend, seasonality 등을 수정하세요.

- 특정 일자에 예측률이 떨어진다면, 아웃라이어를 제거하세요.

- 특정 cutoff (연말 등) 에 예측률이 떨어진다면, changepoint를 추가하는 방법이 있습니다.


개인적으로 논문을 읽고 facebook에 대해 다시 생각해보게 되는 계기가 되었습니다. facebook을 통해 뭔가 활동을 하다보면 뻑뻑한 규정때문에 막히는 경우가 대부분이였는데, 이렇게 논문과 오픈소스 라이브러리를 통해 세상에 기여한다는 점이 멋지지 않나요? 


Tutorial은 사실 많이 존재하기 때문에 굳이 자세하게 적을필요는 없을것 같습니다. 바로 이용해보기 시작하자구욧


'데이터분석 > Machine Learning' 카테고리의 다른 글

TPU 구글에서 사용  (0) 2019.06.22
gensim word2vec simple usage  (0) 2018.12.16
xgboost screen shot  (0) 2018.04.13
회귀 결정트리의 불순도 측정과 값 해석  (0) 2018.04.11
스택힝  (0) 2018.04.09