Skip to main content

시계열 예측

시계열 예측

  • 주요 개념:
    • sktime
    • 마지막 값으로, 평균으로, 표류로 예측
    • 계절성을 고려한 예측

sktime

  • 시계열 머신러닝 라이브러리
  • 설치:
    pip install sktime
  • 예측을 위한 임포트
    from sktime.forecasting.naive import NaiveForecaster

실습 데이터

  • 파일 로딩
    import pandas as pd
    beer = pd.read_excel('beer.xlsx', parse_dates=True, index_col='quarter')
    y = beer.production
  • 20개 분기 날짜 만들기
    future = pd.date_range(beer.index[-1], periods=20, freq='Q')

예측을 위한 다음 날짜

# 마지막 날짜
last_date = beer.index[-1]

# 예측 시작일
start_date = beer.index[-1] + pd.offsets.QuarterBegin()
  • 요일: pd.offsets.Week(weekday=0) # 0은 월요일
  • 월초: MonthBegin, 월말: MonthEnd
  • 기초: QuarterBegin, 분기말: QuarterEnd
  • 연초: YearBegin, 연말: YearEnd

예측을 위한 다음 날짜

# 20개 분기초(5년) 날짜 만들기
future_dates = pd.date_range(start=start_date, periods=20, freq='QS')
  • freq
    • 매주 월요일: W-MON
    • 월초: MS
    • 월말: M
    • 분기초: QS
    • 분기말: Q
    • 연초: YS
    • 연말: Y

마지막 값으로 예측

  • 모든 예측값을 단순하게 마지막 값으로
  • 다양한 경제 금융 시계열에 잘 맞음
  • 데이터가 랜덤 워크(random walk)할 때 최적 예측치(상승 50%, 하락 50% 이므로)
    fc_last = NaiveForecaster(strategy="last") # 단순 기법
    fc_last.fit(y) # 모형 적합
    y_pred_last = fc_last.predict(fh=future_dates)
    pred_last = pd.DataFrame({'production': y_pred_last}, index=future_dates)
    beer.production.plot()
    pred_last.production.plot()

평균으로 예측

  • 과거 데이터의 평균으로 예측
  • 평균 기법으로 예측한 표 만들기
    fc_mean = NaiveForecaster(strategy="mean") # 평균 기법
    fc_mean.fit(y) # 모형 적합: 모형의 파라미터(평균) 추정
    y_pred_mean = fc_mean.predict(fh=future_dates)
    pred_mean = pd.DataFrame({'production': y_pred_mean}, index=future_dates)
  • 시각화
    beer.production.plot()
    pred_mean.production.plot()

평균 기간의 제한

from sktime.forecasting.naive import NaiveForecaster
y = beer.production
fc_mean_12 = NaiveForecaster(strategy="mean", window_length=12)
# 과거 12개 분기(=3년) 평균치만 사용

fc_mean_12.fit(y)
y_pred_mean_12 = fc_mean_12.predict(fh=future_dates)
pred_mean_12 = pd.DataFrame({'production': y_pred_mean_12}, index=future_dates)
beer.production.plot()
pred_mean_12.production.plot()

표류로 예측

  • 과거 데이터에 나타난 평균 변화량을 적용
    fc_drift = NaiveForecaster(strategy="drift") 
    fc_drift.fit(y) # 모형 적합
    y_pred_drift = fc_drift.predict(fh=future_dates)
    pred_drift = pd.DataFrame({'production': y_pred_drift}, index=future_dates)
    beer.production.plot()
    pred_drift.production.plot()

표류 기간의 제한

fc_drift_12 = NaiveForecaster(strategy="drift", window_length=12) 
fc_drift_12.fit(y)
y_pred_drift_12 = fc_drift_12.predict(fh=future_dates)
pred_drift_12 = pd.DataFrame({'production': y_pred_drift_12}, index=future_dates)
beer.production.plot()
pred_drift_12.production.plot()

마지막 + 계절성

fc_last_season = NaiveForecaster(strategy="last", sp=4) # 계절성 주기: 4분기
# 분기 단위 데이터로 표시
yp = beer.production.copy()
yp.index = beer.index.to_period('Q')
future_periods = future_dates.to_period('Q')
# 나머지는 동일
fc_last_season.fit(yp)
y_pred_ls = fc_last_season.predict(fh=future_periods)
pred_ls = pd.DataFrame({'production': y_pred_ls}, index=future_periods)
beer.production.plot()
pred_ls.production.plot()

평균 + 계절성

fc_mean_season = NaiveForecaster(strategy="mean", sp=4) # 계절성 주기: 4분기
# 분기 단위 데이터로 표시
yp = beer.production.copy()
yp.index = beer.index.to_period('Q')
future_periods = future_dates.to_period('Q')
# 나머지는 동일
fc_mean_season.fit(yp)
y_pred_ms = fc_mean_season.predict(fh=future_periods)
pred_ms = pd.DataFrame({'production': y_pred_ms}, index=future_periods)
beer.production.plot()
pred_ms.production.plot()

표류 + 계절성

  • 표류에는 계절성이 지원되지 않음
  • 기존 추정치들을 결합
    seasonal = y_pred_ls.copy() # 마지막 + 계절성을 복사
    seasonal.index = y_pred_drift.index # 인덱스를 맞춤
    y_pred_ds = y_pred_drift + seasonal - y_pred_last # 마지막 값이 2번 반복되므로 빼줌
    pred_ds = pd.DataFrame({'production': y_pred_ds}, index=future_dates)
    beer.production.plot()
    pred_ds.production.plot()

Prophetverse

  • Meta에서 개발한 머신러닝을 이용한 시계열 예측 모델의 구현
  • 설치
    !pip install prophetverse
  • 예측(sktime과 동일)
    from prophetverse.sktime import Prophetverse
    pp = Prophetverse()
    pp.fit(y=y)
    y_pp = pp.predict(fh=future_dates)
    pred_pp = pd.DataFrame({'production': y_pp}, index=future_dates)
    beer.production.plot()
    pred_pp.production.plot()

계절성

from prophetverse.effects.fourier import LinearFourierSeasonality
from prophetverse.utils import no_input_columns
pps = Prophetverse(
exogenous_effects=[
("seasonality", LinearFourierSeasonality(
freq="D", sp_list=[365.25], fourier_terms_list=[10]),
# 1년은 365.25일(1년 단위 계절성의 푸리에 텀은 보통 10으로 설정)
# 1주 단위 계절성에는 푸리에 텀을 보통 3으로 설정, 1개월 단위는 3~10 사이
no_input_columns),
])
pps.fit(y=y)

계절성

y_pps = pps.predict(fh=future_dates)
pred_pps = pd.DataFrame({'production': y_pps}, index=future_dates)
beer.production.plot()
pred_pps.production.plot()

퀴즈