AI/Prophet

[Prophet] Prophet Tutorial #4 - Holiday Effects

zamezzz 2018. 6. 22. 00:59

 [Ai] Prophet Tutorial #4 

   - Seasonality, Holiday Effects And Regressors


벌써 Prophet 튜토리얼 네 번째 포스팅입니다.


오늘의 주제는 Seasonality, Holiday Effects And Regressors 입니다.

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


오늘의 제목은 꽤 기네요. 그만큼 많고 중요한 내용이 들어있는 것 같습니다.


하나씩 살펴보겠습니다.


 Modeling Holidays and Special Events


첫 번째는 Holidays나 특별한 Events를 설정하여 해당 일자에 특별성을 부여해줍니다.


아마도 해당 일자에는 비슷한 특성을 주어 예측하는데 도움이 되도록 할 것 같습니다.


이를 위해서는 Data_Frame을 만들어 줘야 합니다.


물론 여기에는 과거 데이터와 미래 데이터가 모두 포함이 되어야 합니다.


예제에선 Play off 경기가 있는 날과 Superbowl 경기 날을 Holiday로 설정했습니다.


저는 데이터가 블로그 방문자 수이기 때문에 조금 다른 Holiday를 설정하고자 합니다.


제가 우선 생각하는 것은 공휴일블로그 업데이트일을 Holiday로 설정하려고 합니다.


그리고 해당일 주변의 날짜를 포함시키기 위해 [lower_window, upper_window]를 사용


하여 업데이트일의 다음날까지 포함시키려고 합니다.


그렇다면 lower_window=0, upper_window=1 이렇게 설정해주면 됩니다.


위의 특징을 포함하여 설정한 코드는 다음과 같습니다.


nationalHolidays = pd.DataFrame({

  'holiday': 'nationalHolidays',

  'ds': pd.to_datetime(['2018-01-01','',....]),

})


updatedays = pd.DataFrame({

  'holiday': 'updatedays',

  'ds': pd.to_datetime(['2018-01-01','',....]),

  'lower_window': 0,

  'upper_window': 1

})


holidays = pd.concat((nationalHolidays, updatedays))



그리고 Prophet을 호출할 때 holidays 피쳐를 설정해주면 끝입니다.


m = Prophet(holidays=holidays)


각 holidays피쳐가 주는 영향을 확인하고 싶으면 아래 코드를 적용합니다.


nationalHolidays 및 updatedays 각 holidays 피쳐의 합이 0이 넘는 목록을


최근 날짜부터 10개 컬럼을 출력하는 결과입니다.


forecast[(forecast['nationalHolidays'] + forecast['updatedays']).abs() > 0]

        [['ds', 'nationalHolidays', 'updatedays']][-10:]


위 출력결과는 다음과 같습니다




holidays 피쳐 영향을 받은 목록이 보입니다.


이 날짜들의 예측 값은 조금 보정이 되었으리라 생각이 됩니다.


아래 나오는 Prior scale for holidays and seasonality 부분을 함께 보겠습니다.


holidays 강도 또한 설정이 가능합니다. 방법은 매우 간단합니다.


기본 값은 10이니 참고하여 적용하면 됩니다.


m = Prophet(holidays=holidays, holidays_prior_scale=0.5).fit(df)



 Fourier Order for Seasonalities


시즌 특성이라는 피쳐를 위해 푸리에 급수(Fourier series)에 대한 얘기가 나옵니다.


푸리에 급수란 주기함수를 삼각함수의 급수로 나타낸 것입니다.


자세한 정의는 위키 참고바랍니다. (https://en.wikipedia.org/wiki/Fourier_series)


시즌 특성을 확인하기 위한 파이썬 코드는 아래와 같습니다.


from fbprophet.plot import plot_yearly

m = Prophet().fit(df)

a = plot_yearly(m)


아래 그림과 같이 시즌에 따라 다른 트렌드를 알려줍니다.



물론 이 강도는 변경할 수 있습니다. 기본 값은 10이며 변경은 아래와 같이 합니다.


m = Prophet(yearly_seasonality=20).fit(df)


강도를 높인다면 시즌 변화에 따라 트렌드를 더 유연하게 예측할 수 있으나


오버피팅의 문제가 있으니 주의해서 사용해야 합니다.



 Specifying Custom Seasonalities


이러한 시즌 특성은 사용자가 직접 생성할 수도 있습니다.


Prophet에서는 기본적으로 weekly와 yearly 특성을 제공해주고 있습니다.


이 외 시즌 특성을 확인하고 적용하기 위해서는 'add_seasonality' 함수를 통해


추가시킬 수 있습니다. monthly 특성을 추가시키는 예제를 확인해보겠습니다.


m = Prophet(weekly_seasonality=False)

m.add_seasonality(name='monthly', period=30.5, fourier_order=5)

forecast = m.fit(df).predict(future)

fig = m.plot_components(forecast)


한달을 30.5일 정도로 끊었고 강도는 5정도로 설정했습니다.


그럼 약 30.5일에 대한 트렌드가 표기됩니다. 결과는 아래와 같습니다.



 Additional regressors


Additional regressors는 모델의 선형적으로 예측값을 증가시킬 수 있다고 합니다.


튜토리얼의 예제에서는 NFL 시즌동안의 일요일에는 추가 효과를 더할 수 있다고 합니다


이는 extra_regressor을 통해 진행 할 수 있습니다. 코드는 다음과 같습니다.


def nfl_sunday(ds):

    date = pd.to_datetime(ds)

    if date.weekday() == 6 and (date.month > 8 or date.month < 2):

        return 1

    else:

        return 0

df['nfl_sunday'] = df['ds'].apply(nfl_sunday)


m = Prophet()

m.add_regressor('nfl_sunday')

m.fit(df)


future['nfl_sunday'] = future['ds'].apply(nfl_sunday)


forecast = m.predict(future)

fig = m.plot_components(forecast)


이 특성 또한 holidays의 인터페이스로 표기할 수 있습니다.


2가지 피쳐를 더하여 더욱 강조하기 위해 사용되는 피쳐인 것 같습니다.



오늘의 튜토리얼을 마치기 전에 오늘의 피쳐를 적용하여 비교해보겠습니다.


적용한 피쳐

- 공휴일과 업데이트일의 holidays 피쳐


새로운 seasonality 특성 및 강도 조정, additional regressors는 적용하지 않았습니다


여러번 실험 결과 공휴일과 업데이트일의 holidays 피쳐만 좋은 결과를 내었습니다.


holidays 피쳐는 매우 정확한 예측값을 주는 좋은 피쳐인 것 같다고 느꼈습니다.


그럼 결과값을 보시겠습니다. 지난번 정확도는 81.4%였습니다.


Date

실제

 예측

정확도

2018-06-01

138

142.64

97%

2018-06-02

91

109.45

83%

2018-06-03

89

117.02

76%

2018-06-04

239

186.36

78%

2018-06-05

165

157.04

95%

2018-06-06

128

152.54

84%

2018-06-07

188

188.07

100%

2018-06-08

173

159.74

92%

2018-06-09

114

108.08

95%

합계

81.4%


이번 피쳐를 적용한 결과는 88.9%의 정확도입니다.


이번에는 약 8% 가까이 향상했습니다.


기대했었던 holiday 피쳐를 적용하여 90% 가까운 정확도를 보여서 기분이 좋네요.


이제 얼마 피쳐들이 남지 않은 것 같습니다.


의미 있는 피쳐들을 융합하여 더 좋은 정확도를 내보도록 하겠습니다.


이후에는 각 피쳐별 강도를 조절하여 최적의 조합을 찾고 싶네요 


그럼 포스팅을 마치겠습니다. 감사합니다

반응형