시계열 예측
시계열 예측
기본 예측 기법
- 실습 데이터 준비: (맥주 생산량)
beer = pd.read_excel('beer.xlsx', parse_dates=True, index_col='quarter') # 예측할 미래 시점(20분기) 인덱스 생성 future = pd.date_range(beer.index[-1], periods=20, freq='Q') # 'Q': 분기말 빈도 - 평균 기법 (Average Method): 과거 전체 데이터 평균으로 미래 값 예측.
pred_avg = pd.DataFrame({ 'production': beer.production.mean()}, index=future) beer.production.plot() pred_avg.production.plot() - 단순 기법 (Naïve Method): 마지막 관측 값으로 미래 값 예측. (랜덤 워크 시 최적)
pred_naive = pd.DataFrame({ 'production': beer.production.iloc[-1]}, index=future) beer.production.plot() pred_naive.production.plot() - 계절성 단순 기법 (Seasonal Naïve Method): 마지막 동일 계절 값으로 예측.
import numpy as np # 마지막 1년(4분기) 값 반복 사용 (np.tile: 배열 반복) last_season = beer.production.iloc[-4:] pred_seasonal_naive = pd.DataFrame({ 'production': np.tile(last_season, 5)}, index=future) # 20분기=5년 beer.production.plot() pred_seasonal_naive.production.plot() - 표류 기법 (Drift Method): 마지막 관측 값 + 과거 평균 변화량(추세) 적용 예측.
num = len(beer.production) - 1 drift = (beer.production.iloc[-1] - beer.production.iloc[0]) / num # 전체 기간 평균 변화량 last = beer.production.iloc[-1] pred_drift = pd.DataFrame({ 'production': last + np.arange(1, 21) * drift}, index=future) # 1~20 시점 예측 beer.production.plot() pred_drift.production.plot() - 표류 + 계절성 단순 기법 결합: 계절성 예측값 + 표류 예측값.
pred_drift_seasonal = pd.DataFrame( {'production': pred_seasonal_naive['production'] + np.arange(1, 21) * drift}, index=future) beer.production.plot() pred_drift_seasonal.production.plot()
Prophet
- Facebook 개발 시계열 예측 라이브러리.
- 설치:
conda install -y -c conda-forge prophet(또는pip install prophet) - 특징:
- 시계열 = 추세(trend) + 주기적변화(seasonality) + 휴일효과(holiday) 분해 모델링.
- 추세 변화점(changepoint) 자동/수동 감지.
- 정상 시계열 아니어도 사용 가능.
- 다양한 옵션(계절성 주기, 휴일 등) 설정 용이.
- 기본 사용법:
from prophet import Prophet import pandas as pd # 데이터 로드 (컬럼명 'ds', 'y' 필수) # df = pd.read_excel('manning.xlsx') # 예시 데이터 # df.rename(columns={'Date': 'ds', 'Visits': 'y'}, inplace=True) # 컬럼명 변경 필요시 # 모델 생성 및 학습 m = Prophet() m.fit(df) # 미래 날짜 생성 future = m.make_future_dataframe(periods=365) # 향후 365일 예측 # 예측 수행 forecast = m.predict(future) # 예측 결과 확인 (주요 컬럼) print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()) # ds:날짜, yhat:예측값, yhat_lower/upper: 불확실성 구간(신뢰구간 유사) # 예측 결과 시각화 fig1 = m.plot(forecast) plt.show() # 성분 분해 시각화 (추세, 주별/연별 계절성 등) fig2 = m.plot_components(forecast) plt.show() - 추세 변화점 (Changepoint):
- 자동 감지 시각화:
from prophet.plot import add_changepoints_to_plot fig = m.plot(forecast) a = add_changepoints_to_plot(fig.gca(), m, forecast) # gca(): 현재 그래프 축 가져오기 plt.show() - 수동 지정:
m = Prophet(changepoints=['2014-01-01']) # 특정 날짜 지정 # ... fit, predict, plot ...
- 자동 감지 시각화:
- 휴일 효과:
- 휴일 정보 담은 DataFrame 별도 생성 (컬럼:
holiday,ds,lower_window,upper_window). - 모델 생성 시
holidays인자 전달.# h1, h2: 플레이오프, 슈퍼볼 날짜 DataFrame (슬라이드 311 참고) # holidays = pd.concat([h1, h2]) m = Prophet(holidays=holidays) # ... fit, predict, plot_components ... - 국가별 공휴일 자동 추가:
m = Prophet() m.add_country_holidays(country_name='US') # 미국 공휴일 추가 # ... fit, predict ...
- 휴일 정보 담은 DataFrame 별도 생성 (컬럼:
- 계절성 옵션:
- 기본: 연(yearly), 주(weekly), 일(daily) 자동 감지 및 적용.
- 끄기:
m = Prophet(weekly_seasonality=False) - 임의 주기 추가:
# name:이름, period:주기(일), fourier_order: 복잡도(클수록 변동성 높음) m.add_seasonality(name='monthly', period=30.5, fourier_order=5)
- 조건부 계절성: 특정 조건 만족 시에만 적용되는 계절성.
- 데이터에 조건 열 추가 (
on_season,off_season등). add_seasonality시condition_name지정.# 예: 시즌 중에만 적용되는 주별 계절성 m.add_seasonality(name='weekly_on_season', period=7, fourier_order=3, condition_name='on_season')
- 데이터에 조건 열 추가 (
- 외부 독립변수(Regressor) 추가: (미래 값 알아야 예측 가능)
m = Prophet() m.add_regressor('Unemployment') # 실업률 변수 추가 m.add_regressor('Income') # 소득 변수 추가 m.fit(df) # 학습 데이터에는 해당 변수 포함되어야 함 # 예측 시 future 데이터프레임에도 해당 변수 값 필요 # forecast = m.predict(future_with_regressors) # 추가된 독립변수 계수 확인 from prophet.utilities import regressor_coefficients print(regressor_coefficients(m)) - 성장 한계 설정 (Logistic Growth): 데이터가 특정 상한/하한 수렴 시.
- 데이터에 'cap'(상한), 'floor'(하한) 열 추가.
- 모델 생성 시
growth='logistic'지정.df['cap'] = 8.5 # 상한값 설정 m = Prophet(growth='logistic') m.fit(df) # 예측 시 future에도 'cap' 열 필요 # future['cap'] = 8.5 # forecast = m.predict(future) # m.plot(forecast)