ARIMA·ETS·칼만 필터로 설계하는 시계열 예측
ARIMA·ETS·Kalman Filter의 모델 특성, 검증 기준, 폴백과 재학습 정책을 바탕으로 수요·부하·센서 데이터 예측 파이프라인을 설계하는 방법을 정리한다.
2026-08-14 · 최초 발행 2024-04-29
수요·재고·부하·가격·센서 값을 앞서 관리하려면 예측 모델만 선택해서는 부족하다. 데이터 품질을 확인하고, 패턴에 맞는 후보를 비교하며, 실패 시 대체 모델로 전환할 수 있어야 한다. ARIMA, Exponential Smoothing, Kalman Filter는 이 과정에서 서로 다른 역할을 맡는다.
패턴과 데이터 흐름에 따라 달라지는 모델
ARIMA는 자기회귀(AR), 차분(I), 이동평균(MA)을 결합한 모형이다. (p, d, q)와 계절 성분 (P, D, Q)m을 사용해 비정상 시계열을 정상화해 설명한다. 잔차는 백색잡음으로 가정하며, 차수는 ACF/PACF와 정보준거(AIC/BIC)를 이용해 선택한다. 선형성과 가우시안 잡음 가정이 전제된다.
Exponential Smoothing(ETS)은 수준(Level), 추세(Trend), 계절성(Seasonality)을 지수평활로 다룬다. SES, Holt, Holt-Winters와 ETS(Error, Trend, Seasonality) 체계가 여기에 속한다. 별도의 설명변수 없이 최신 관측치에 높은 가중치를 부여하므로 변동이 큰 단기 예측에 유리하다.
Kalman Filter는 상태공간(State-Space)에 기반한 선형-가우시안 최적 필터다. 잠재 상태 x_t와 관측값 y_t를 함께 추정하며, 결측·센서 노이즈·실시간 스트리밍 환경에서 강점을 보인다. 예측과 갱신을 반복하는 온라인 추정 과정에서 불확실성 공분산을 이용해 신뢰구간도 산출한다.
전처리부터 모델 선정까지 연결하기
결측과 이상치를 처리하고, 필요하면 박스-콕스 변환과 계절 분해를 적용한다. ADF/KPSS로 정상성을 확인해 차분 차수를 정하고, 캘린더·프로모션 같은 외생변수를 ARIMAX/SARIMAX에 포함할지 결정한다.
모델별로 조정할 항목도 다르다. ARIMA는 (p,d,q)(P,D,Q)m, 드리프트, 외생변수 회귀계수를 다룬다. ETS는 오차·추세·계절성의 가법/승법 조합과 덤핑 추세를 선택한다. Kalman Filter에서는 전이행렬 F, 관측행렬 H, 공분산 Q/R, 초기 상태 x0/P0를 설정한다.
후보는 롤링 오리진 백테스트로 비교한다. 다단계 예측 성능 곡선에서 MAPE, MASE, RMSE를 보고, AICc·예측오차·신뢰구간 폭을 합성 점수로 사용하거나 비용 함수로 선택 기준을 세울 수 있다. 예측구간을 제공하고 CUSUM/ADWIN으로 드리프트나 regime shift를 감지하며, 실패 시 계절 평균·Naïve·ETS로 전환하는 폴백과 알람도 함께 둔다.
선택 기준은 패턴 적합도와 운영 조건이 함께 결정한다
| 알고리즘 | 성능(패턴 적합) | 확장성 | 일관성(계절/휴일) | 안정성(결측/이상치) | 운영 편의 |
|---|---|---|---|---|---|
| ARIMA/SARIMA | 추세·계절·자기상관 강함, 중장기 안정 | 수백~수천 시계열 배치 적합 | 휴일·외생변수 ARIMAX로 보완 | 결측 보간 필요, 이상치에 민감 | 자동 차수 탐색 가능, 튜닝 필요 |
| Exponential Smoothing (ETS) | 단기 반응 빠름, 급변 대응 우수 | 매우 높음, 경량 | 계절/추세 모듈식 선택 용이 | 이상치 영향 제한적(가중 완충) | 설정 단순, 실무 적용 용이 |
| Kalman Filter | 센서/실시간에 강함, 노이즈 견고 | 스트리밍·온라인 우수 | 휴일/레짐 전환 상태모형 확장 가능 | 결측 처리 자연 내장 | 설계 복잡, 행렬/공분산 튜닝 필요 |
리테일 수요예측에서는 프로모션과 캘린더를 포함한 SARIMAX 또는 ETS로 SKU·점포 단위 일별 수요를 예측하고, 재고·발주 최적화에 연결해 품절과 과잉 재고 비용을 줄일 수 있다.
에너지·통신 부하처럼 시간대와 요일 계절성이 강한 데이터는 SARIMA/ETS로 단기 예측할 수 있다. 기상 외생변수를 결합하면 오차를 추가로 줄일 수 있다.
제조 설비 상태 감시에는 Kalman Filter의 로컬 레벨 또는 로컬 선형 추세 모형을 사용해 센서 스트리밍을 실시간으로 평활하고 이상을 탐지할 수 있다. 예지보전(PdM) 트리거 기준은 신뢰구간을 바탕으로 설정한다.
금융 시계열에서는 거래량·스프레드의 단기 예측에 ETS를, 요인·상태 추정에는 칼만 스무딩을 적용한다. regime 전환 감지는 리스크 한도를 동적으로 조정하는 근거가 된다.
Naïve 대비 MAPE는 1030% 개선될 수 있으며, 프로모션·외생변수를 포함하면 추가 515%p 개선 가능성이 있다. 안전재고는 10~20% 감소하고, 예측구간을 활용하면 SLA 위반은 15% 이상 줄일 수 있다. 잔차 진단과 구간을 함께 제시하면 의사결정 근거가 명확해지고, 표준화된 파이프라인은 조직 간 일관성과 재현성을 높인다.
예측 결과를 내보내는 파이프라인
입력은 시계열 데이터, 캘린더·프로모션 외생변수, 데이터 품질 신호로 구성한다. 결측·이상치·변환을 처리하고 계절 주기를 추정한 뒤 ARIMA/SARIMA, ETS, Kalman 후보를 학습한다. 롤링 검증으로 다단계 호라이즌을 점수화해 모델을 고르고, 포인트 예측·예측구간·모델·버전·잔차 통계를 출력한다.
데이터 품질이 임계치에 미치지 못하면 폴백 모델과 알람으로 전환하고, 학습이 실패하면 이전 버전으로 롤백한다.
Python으로 후보 모델을 함께 비교하기
환경은 Python 3.10+, numpy, pandas, statsmodels>=0.14, filterpy>=1.4.5이며 설치 명령은 pip install numpy pandas statsmodels filterpy다.
import numpy as np, pandas as pd
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.tsa.holtwinters import ExponentialSmoothing
from filterpy.kalman import KalmanFilter
np.random.seed(42)
# 1) 데이터 생성: 일별, 3년, 주간 계절성
idx = pd.date_range("2021-01-01", periods=3*365, freq="D")
trend = 0.05 * np.arange(len(idx))
season = 3 * np.sin(2*np.pi*idx.dayofweek/7)
noise = np.random.normal(0, 1.2, len(idx))
y = 20 + trend + season + noise
s = pd.Series(y, index=idx)
train, test = s.iloc[:-30], s.iloc[-30:]
def mape(y_true, y_pred):
y_true, y_pred = np.asarray(y_true), np.asarray(y_pred)
return np.mean(np.abs((y_true - y_pred) / np.maximum(1e-6, np.abs(y_true)))) * 100
# 2) ARIMA/SARIMA (주기=7)
sarima = SARIMAX(train, order=(1,1,1), seasonal_order=(1,1,1,7),
enforce_stationarity=False, enforce_invertibility=False).fit(disp=False)
fc_sarima = sarima.get_forecast(steps=len(test))
pred_sarima = fc_sarima.predicted_mean
# 3) ETS (Holt-Winters)
ets = ExponentialSmoothing(train, trend="add", seasonal="add", seasonal_periods=7).fit()
pred_ets = ets.forecast(len(test))
# 4) Kalman Filter (Local Level)
# x_t = x_{t-1} + w_t, y_t = x_t + v_t
kf = KalmanFilter(dim_x=1, dim_z=1)
kf.F = np.array([[1.0]])
kf.H = np.array([[1.0]])
kf.x = np.array([[train.iloc[0]]])
kf.P = np.array([[10.0]]) # 초기 불확실성
var = np.var(train.values)
kf.Q = np.array([[0.01 * var]]) # 프로세스 노이즈
kf.R = np.array([[0.5 * var]]) # 관측 노이즈
# 필터링(훈련 구간)
for z in train.values:
kf.predict()
kf.update(np.array([[z]]))
# h-step 예측: Local Level은 평균 유지
pred_kf = np.repeat(kf.x[0,0], len(test))
pred_kf = pd.Series(pred_kf, index=test.index)
print("MAPE SARIMA: %.2f%%" % mape(test, pred_sarima))
print("MAPE ETS : %.2f%%" % mape(test, pred_ets))
print("MAPE KF : %.2f%%" % mape(test, pred_kf))
학습과 검증은 롤링 오리진 방식이 권장된다. 단일 홀드아웃은 과대적합 또는 과소평가 위험이 있다. Kalman Filter는 Q/R 추정에 민감하므로 EM/MLE 또는 잔차 기반 추정 절차를 도입하고, 실제 서비스에서는 캘린더·프로모션·날씨 등 외생변수 파이프라인을 동기화해야 한다.
운영에서 지켜볼 신호와 배포 단위
결측율·이상치율의 임계선을 정하고 초과 시 폴백과 알람을 작동시킨다. 공휴일과 프로모션 라벨이 빠지지 않았는지도 검증 대상이다.
데이터와 모델 아티팩트는 버저닝하고, 시점 기준 재학습 스냅샷을 고정한다. 피처 엔지니어링 코드와 모델 아티팩트는 원자적으로 배포해야 재현성이 유지된다.
잔차 분포와 MAPE/MASE 드리프트, 구간 커버리지(예: 95% PI)를 추적한다. regime 전환이 감지되면 파라미터를 리셋하거나 모델을 교체한다. 수천 시계열 이상에서는 ETS 또는 경량 SARIMA를 우선 적용하고, 상향식 집계 뒤 상향·하향 조정을 수행할 수 있다. 멀티테넌트 환경에서는 공통 캘린더와 폴백 규칙을 표준화한다.
ARIMA/SARIMA는 구조적 패턴의 설명력과 해석성, 외생변수 포함에 강점이 있다. ETS는 경량성과 견고성, 단기 반응성, 단순한 운영에 적합하다. Kalman Filter는 온라인·센서 환경과 상태공간 확장에 맞는다. 세 모델을 표준 전처리·롤링 백테스트·폴백 체계 안에서 선정하거나 앙상블로 운영하고, 예측구간으로 리스크를 관리한다.