본문으로 건너뛰기

075 단변량 시계열 예측

키워드: 단변량, univariate

개요

단변량 시계열 예측은 하나의 변수만 사용하여 미래 값을 예측하는 방법입니다. 과거의 자기 자신 값만으로 미래를 예측하는 가장 기본적인 시계열 예측 방법론입니다.

실습 환경

  • Python 버전: 3.11 권장
  • 필요 패키지: pycaret[full]>=3.0

단변량 vs 다변량

단변량 (Univariate):
y(t+1) = f(y(t), y(t-1), y(t-2), ...)
- 자기 자신의 과거 값만 사용
- 외부 변수 없음

다변량 (Multivariate):
y(t+1) = f(y(t), x1(t), x2(t), ...)
- 외부 변수 (exogenous) 포함
- 더 많은 정보 활용

데이터 준비

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 075 항공 승객 데이터 시뮬레이션
np.random.seed(42)
dates = pd.date_range('2010-01-01', periods=144, freq='MS') # 12년 월별

# 075 구성 요소
trend = np.linspace(100, 500, len(dates)) # 상승 추세
seasonality = 50 * np.sin(2 * np.pi * np.arange(len(dates)) / 12) # 연간 계절성
multiplicative_seasonal = 1 + 0.2 * np.sin(2 * np.pi * np.arange(len(dates)) / 12)
noise = np.random.normal(0, 20, len(dates))

# 075 승법 모델
values = trend * multiplicative_seasonal + noise

data = pd.DataFrame({
'date': dates,
'passengers': values
})
data.set_index('date', inplace=True)

# 075 시각화
plt.figure(figsize=(14, 5))
plt.plot(data.index, data['passengers'])
plt.xlabel('Date')
plt.ylabel('Passengers')
plt.title('Monthly Airline Passengers')
plt.grid(True, alpha=0.3)
plt.savefig('airline_data.png', dpi=150)

print(f"데이터 기간: {data.index.min()} ~ {data.index.max()}")
print(f"데이터 수: {len(data)}")

기본 예측 방법

from pycaret.time_series import *

# 075 환경 설정
ts = setup(
data=data,
target='passengers',
fh=12, # 12개월 예측
fold=3,
seasonal_period=12,
session_id=42,
verbose=False
)

# 1. Naive (마지막 값 반복)
naive = create_model('naive')

# 2. Seasonal Naive (작년 같은 달 값)
snaive = create_model('snaive')

# 3. Polynomial Trend (추세만)
polytrend = create_model('polytrend')

통계 모델

ARIMA

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

# 075 Auto ARIMA (자동 파라미터 선택)
arima = create_model('auto_arima')

# 075 예측
pred_arima = predict_model(arima)
print(pred_arima)

# 075 시각화
plot_model(arima, plot='forecast')

지수 평활 (Exponential Smoothing)

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

# 075 지수 평활
exp_smooth = create_model('exp_smooth')

# 075 ETS (Error, Trend, Seasonality)
ets = create_model('ets')

# 075 비교
plot_model(exp_smooth, plot='forecast')
plot_model(ets, plot='forecast')

Theta

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

# 075 Theta 방법
theta = create_model('theta')

plot_model(theta, plot='forecast')

Prophet

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

# 075 Facebook Prophet
prophet = create_model('prophet')

# 075 예측
pred_prophet = predict_model(prophet)

# 075 시각화
plot_model(prophet, plot='forecast')

# 075 구성 요소 분해
plot_model(prophet, plot='decomp')

머신러닝 모델

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

# 075 선형 회귀 (계절성 제거 후)
lr = create_model('lr_cds_dt')

# 075 Ridge (계절성 제거 후)
ridge = create_model('ridge_cds_dt')

# 075 LightGBM (계절성 제거 후)
lgbm = create_model('lightgbm_cds_dt')

# 075 Random Forest
rf = create_model('rf_cds_dt')

모델 비교

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, fold=3, seasonal_period=12,
session_id=42, verbose=False)

# 075 전체 모델 비교
best = compare_models()

# 075 특정 모델만 비교
selected_models = compare_models(
include=['naive', 'snaive', 'arima', 'exp_smooth', 'ets', 'prophet', 'lightgbm_cds_dt']
)

예측 결과 시각화

from pycaret.time_series import *
import matplotlib.pyplot as plt

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

# 075 여러 모델 예측
models_dict = {
'ARIMA': create_model('auto_arima'),
'ETS': create_model('ets'),
'Prophet': create_model('prophet'),
'LightGBM': create_model('lightgbm_cds_dt')
}

# 075 예측
predictions = {}
for name, model in models_dict.items():
pred = predict_model(model)
predictions[name] = pred['y_pred'].values

# 075 비교 시각화
plt.figure(figsize=(14, 6))

# 075 실제 데이터
plt.plot(data.index, data['passengers'], label='Actual', color='black', linewidth=2)

# 075 예측 기간
future_dates = pd.date_range(data.index[-1] + pd.DateOffset(months=1),
periods=12, freq='MS')

colors = ['blue', 'red', 'green', 'orange']
for (name, pred), color in zip(predictions.items(), colors):
plt.plot(future_dates, pred, label=name, color=color, linestyle='--', linewidth=1.5)

plt.xlabel('Date')
plt.ylabel('Passengers')
plt.title('Model Comparison - 12 Month Forecast')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('model_comparison.png', dpi=150)

예측 구간 (Prediction Interval)

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

model = create_model('auto_arima')

# 075 예측 구간 포함 예측
predictions = predict_model(model, return_pred_int=True)
print(predictions)

# 075 시각화 (구간 포함)
plot_model(model, plot='forecast') # 기본적으로 구간 표시

긴 기간 예측

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

model = create_model('auto_arima')

# 075 다양한 예측 기간
horizons = [6, 12, 24, 36]
all_predictions = {}

for h in horizons:
pred = predict_model(model, fh=h)
all_predictions[h] = pred

print(f"6개월 예측: {all_predictions[6]['y_pred'].values}")
print(f"12개월 예측: {all_predictions[12]['y_pred'].values}")

재학습 (Finalize)

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

# 075 모델 생성 (일부 데이터로 검증)
model = create_model('auto_arima')

# 075 전체 데이터로 재학습
final_model = finalize_model(model)

# 075 최종 예측
final_pred = predict_model(final_model)
print(final_pred)

# 075 저장
save_model(final_model, 'final_arima_model')

잔차 분석

from pycaret.time_series import *

ts = setup(data, target='passengers', fh=12, seasonal_period=12,
session_id=42, verbose=False)

model = create_model('auto_arima')

# 075 잔차 진단
plot_model(model, plot='diagnostics')

# 075 ACF (자기상관)
plot_model(model, plot='acf')

# 075 잔차 분포
plot_model(model, plot='residuals')

좋은 잔차의 특징

1. 정규 분포
2. 평균 0
3. 등분산
4. 자기상관 없음 (백색 잡음)

모델 선택 가이드

데이터 특성에 따른 모델 선택:

강한 계절성:
- Seasonal Naive (베이스라인)
- ETS, SARIMA
- Prophet

명확한 추세:
- ETS (추세 포함)
- ARIMA
- Polynomial Trend

복잡한 패턴:
- Prophet (휴일, 이벤트)
- LightGBM, XGBoost
- TBATS (다중 계절성)

적은 데이터:
- Naive, Seasonal Naive
- ETS
- Theta

정리

  • 단변량 예측: 자기 자신의 과거 값만 사용
  • 통계 모델: ARIMA, ETS, Theta
  • ML 모델: LightGBM, RF (계절성 제거 후)
  • Prophet: 트렌드 + 계절성 + 휴일
  • 잔차 분석으로 모델 적합성 확인

다음 글 예고

다음 글에서는 다변량 시계열 예측을 다룹니다.


PyCaret 머신러닝 마스터 시리즈 #075