Data Analysis & ML/시계열분석

[시계열 분석] Prophet

YSY^ 2021. 12. 19. 19:15

Prophet 알고리즘

기본가정

  • 자동화 된 기술은 상황에 맞게 튜닝하기 어렵고 경험적 지식을 반영하기 어려움
  • 분석가들은 도메인 지식만 풍부한 편이며 분석을 쉽게 다루지 못함
  • 비전문가가 경험적 특성을 반영할 수 있도록 필요한 부분을 자동화

Prophet 모델의 주요 구성요소 : Trend, Seasonality, Holiday

공식 : y(t)=g(t)+s(t)+h(t)+ϵi

  • g(t) : 반복적인 요소가 없는 트랜드
  • s(t) : 반폭적인 요소를 가지고 있는 변화(계절성)
  • h(t) : 불규칙적으로 영향을 미치는 이벤트(휴일)
  • ϵi: 정규분포라고 가정한 오차

데이터 세팅

  • 자전거 쉐어링 데이터 활용
# 데이터 전처리시 활용하는 함수

## 데이터셋 train, test 분리
def datasplit_ts(raw, Y_colname, X_colname, criteria):
    raw_train = raw.loc[raw.index < criteria,:]
    raw_test = raw.loc[raw.index >= criteria,:]
    Y_train = raw_train[Y_colname]
    X_train = raw_train[X_colname]
    Y_test = raw_test[Y_colname]
    X_test = raw_test[X_colname]
    print('Train_size:', raw_train.shape, 'Test_size:', raw_test.shape)
    print('X_train:', X_train.shape, 'Y_train:', Y_train.shape)
    print('X_test:', X_test.shape, 'Y_test:', Y_test.shape)
    return X_train, X_test, Y_train, Y_test

## 데이터 스케일링
def feature_engineering_scaling(scaler, X_train, X_test):
    # preprocessing.MinMaxScaler()
    # preprocessing.StandardScaler()
    # preprocessing.RobustScaler()
    # preprocessing.Normalizer()
    scaler = scaler
    scaler_fit = scaler.fit(X_train)
    X_train_scaling = pd.DataFrame(scaler_fit.transform(X_train), 
                               index=X_train.index, columns=X_train.columns)
    X_test_scaling = pd.DataFrame(scaler_fit.transform(X_test), 
                               index=X_test.index, columns=X_test.columns)
    return X_train_scaling, X_test_scaling
import pmdarima as pm
import pandas as pd
from sklearn import preprocessing


# Data Loading
location = 'https://raw.githubusercontent.com/cheonbi/TimeSeriesAnalysis/master/Data/BikeSharingDemand/Bike_Sharing_Demand_Full.csv'
bike_data = pd.read_csv(location)
bike_data.set_index("datetime", inplace=True)

Y_colname = ['count']
X_colname = ['season', 'holiday', 'workingday', 'weather', 'temp', 'atemp','humidity', 'windspeed']

X_train, X_test, Y_train, Y_test = datasplit_ts(bike_data, Y_colname, X_colname, '2012-07-01')

prophet 라이브러리 및 데이터 세팅

import timeit
start = timeit.default_timer()

from fbprophet import Prophet
from fbprophet.plot import plot_plotly, plot_components_plotly
from fbprophet.plot import add_changepoints_to_plot

# Rearrange of Data
Y_train_prophet = Y_train.reset_index() #1.시간을 index로 가지고 있으면안됨 -> 시간축을 컬럼으로 가지고 있어야함
Y_train_prophet.columns = ['ds', 'y'] #2.컬럼의 이름은 소문자로 해주어야 작동.(고정)
## 3. X와 Y를 합쳐서 알고리즘 fitting을 해야함
train_prophet = pd.concat([Y_train_prophet, 
                           X_train_scaled.reset_index().iloc[:,1:]], 
                           axis=1)
  • 시간을 index로 가지고 있으면 안되며, 시간축을 컬럼으로 가지고 있어야함
  • 컬럼의 이름은 소문자로 해주어야 작동.(고정)
  • X와 Y를 합쳐서 알고리즘 fitting을 해야함

prophet 파라미터 세팅

# Applying Prophet Model
prophet = Prophet(growth='linear', #linear -> 추세를 말함
        # Trend
        changepoints=None, # CP가 발생하는 시점들의 list ['2012-01-01']
        n_changepoints=25, # CP의 수
        changepoint_range=0.8, # CP의 기존 데이터 수 대비 최대 비율
        changepoint_prior_scale=0.05, # CP 추정 민감도로 높을수록 민감
        # Seasonality
        seasonality_mode='additive', # 계절성 모델: 'additive' or 'multiplicative'
        seasonality_prior_scale=10.0, # 계절성 추정 민감도로 높을수록 민감
        yearly_seasonality='auto', # 연계절성
        weekly_seasonality='auto', # 주계절성
        daily_seasonality='auto', #일계절성
        # Holiday
        holidays=None, # 휴일 또는 이벤트 시점 dataframe
        holidays_prior_scale=10.0, # 휴일 추정 민감도로 높을수록 민감
        # Others
        interval_width=0.8, # 추세 예측 정확도 구간범위
        mcmc_samples=0) # 계절성 예측 정확도 제어

Trend 파라미터

  • 비선형도 선형들의 결합인데 CP(트랜드 변화 시점)는 선형들이 변하는 특이점을 말함.(수학적인 것이 아니라 현업에서 보았을때의 changepoint)
파라미터명
특성
changepoints CP가 발생하는 시점들의 list ex. ['2012-01-01']
- 미래에 할것도 넣어줌, 몇백개넣어도 상관없음 ex. 크리스마스 이벤트 등
n_changepoints CP의 수(최대치) (최대한 몇개 있을지 임의로 넣어줌)
changepoint_range CP의 기존 데이터 수 대비 최대 비율
changepoint_prior_scale CP 추정. 민감도로 높을수록 민감

 

Sesonality 파라미터

파라미터명 특성
seasonality_mode 계절성 모델 - additive : 데이터의 진폭이 일정 (default)
- multiplicative : 데이터의 진폭이 점점 증가하거나 감소
seasonality_prior_scale 계절성 추정 민감도로 높을수록 민감
yearly_seasonality 연 계절성
weekly_seasonality 주 계절성
daily_seasonality 일 계절성
  • monthly_seasonality 는 제공하지 않음
  • 데이터가 Additive인지 Multiplicative인지 잘못 구분한다면 오차항을 제대로 분리하지 못하게됨
    • Additive Seasonality : Time series = Trend + Seasonality + Error
    • Multiplicative Seasonality : Time series = Trend * Seasonality * Error

Holiday 파라미터

파라미터명 특성
holidays 휴일 또는 이벤트 시점 dataframe
holidays_prior_scale 휴일 추정 민감도로 높을수록 민감

기타 파라미터

파라미터명 특성
interval_width 추세 예측 정확도 구간범위, 미래에 얼마나 변동할 것인지를 넣어줌
holidays_prior_scale 계절성 예측 정확도 제어
- 구간추정을 할 때, 샘플링해서 조금더 정교한 예측을 하게 함.
- 수치를 높여주면 정확성이 늘어나지만 시간이 굉장히 오래걸림.

시계열 예측 및 시각화

prophet = prophet.fit(train_prophet)
forecast = prophet.make_future_dataframe(freq='H',  #시계열 데이터 frequncy 재검증
                                                        periods=Y_test.shape[0])
pred_prophet = prophet.predict(forecast)
pred_tr_prophet = np.ravel(pred_prophet.loc[:Y_train.shape[0]-1, ['yhat']])
pred_te_prophet = np.ravel(pred_prophet.loc[Y_train.shape[0]:, ['yhat']])

display(pred_prophet[['ds', 'yhat', 'yhat_lower', 'yhat_upper']])

fig = prophet.plot(pred_prophet)
add_changepoints_to_plot(fig.gca(), prophet, pred_prophet)
plt.xticks(rotation=90)
plt.show()

fig = prophet.plot_components(pred_prophet)
ax = fig.get_axes()
for i in range(len(ax)):
    ax[i].tick_params(axis="x", labelsize=15, rotation=90)
plt.show()

 

해당 포스팅은 패스트캠퍼스의 <파이썬을 활용한 시계열 데이터 분석 A-Z 올인원 패키지> 강의를 듣고 정리한 내용입니다

728x90
반응형