지수평활로 시계열 예측 모델 선택하기
단순 지수평활, Holt, Holt-Winters, ETS 모델의 차이와 시계열 예측 운영 시 모델 선택·검증 방법을 정리한다.
2026-08-14 · 최초 발행 2024-04-29
최근 관측치를 반영하는 시계열 예측 방법
지수평활(Exponential Smoothing)은 최근 관측치에 더 큰 가중을 두면서 시계열을 예측하는 방법군이다. 단순 지수평활(SES)에서 시작해 Holt의 이중 지수평활(DES), Holt-Winters, ETS(Error-Trend-Seasonality)로 확장된다.
데이터가 많지 않거나 많은 시계열을 빠르게 예측해야 할 때, 정확도와 운영 편의 사이의 균형을 잡는 선택지가 된다. 관련 영어 토픽에는 Exponential Smoothing, Holt’s Linear Trend, Holt-Winters, ETS가 있다.
레벨·추세·계절성에 따라 달라지는 모형
단순 지수평활(SES)은 레벨(level)만 추정한다. 최근 관측치의 영향이 기하급수적으로 커지며, 갱신식과 예측식은 다음과 같다.
- (l_t = \alpha \cdot y_t + (1-\alpha) \cdot l_{t-1})
- (\hat{y}_{t+h} = l_t), (0<\alpha\le1)
Holt의 이중 지수평활은 레벨과 추세(trend)를 함께 추정하므로 완만한 상승이나 하락이 있는 시계열에 맞는다.
- (l_t = \alpha \cdot y_t + (1-\alpha)(l_{t-1}+b_{t-1}))
- (b_t = \beta(l_t-l_{t-1})+(1-\beta)b_{t-1})
- (\hat{y}_{t+h}=l_t+h\cdot b_t)
감쇠 추세(damped trend, (\phi))를 적용할 수도 있다. 이 경우 예측식은 (\hat{y}_{t+h}=l_t+(\phi+\dots+\phi^h)\cdot b_t)이며, (0<\phi<1)이다.
Holt-Winters는 계절성(seasonality)까지 포함한다. 계절 성분은 가법(additive) 또는 승법(multiplicative)으로 둘 수 있다. 가법 모형의 예시는 다음과 같다.
- (l_t=\alpha(y_t-s_{t-m})+(1-\alpha)(l_{t-1}+b_{t-1}))
- (s_t=\gamma(y_t-l_t)+(1-\gamma)s_{t-m})
- (\hat{y}{t+h}=l_t+h\cdot b_t+s{t-m+h_m})
승법 모형은 (y_t)와 (s_t)를 곱셈 형태로 다루며, (m)은 계절 주기다.
ETS 모델은 Error, Trend, Seasonality를 A(가법), M(승법), N(없음)의 조합으로 표현하는 상태공간(state-space) 모형이다. ETS(A,A,A), ETS(M,A,M) 같은 구조를 쓸 수 있으며, 최대우도추정(MLE)으로 모수를 추정하고 AICc, BIC를 이용해 모델 선택을 지원한다. 승법 오차나 계절 성분은 값이 양수여야 하며, 분산이 수준에 비례하면 승법을 권장한다.
모델을 고를 때 확인할 데이터 특성
지수 감쇠 가중치는 최근 변화에 민감하게 반응하며, 그 정도는 (\alpha), (\beta), (\gamma)로 조절한다. 과거 전체를 보관하는 대신 레벨·추세·계절 상태로 압축해 유지하므로 저메모리·저지연 처리에 적합하다.
모형의 범위는 다음처럼 나뉜다.
| 모델 | 다루는 성분 |
|---|---|
| SES | 레벨 |
| Holt | 레벨+추세 |
| Holt-Winters/ETS | 레벨+추세+계절 |
변동 폭이 수준에 비례하면 승법을, 일정하면 가법을 선택한다. MLE와 복잡도가 낮은 수치 최적화로 모수를 추정하며, 초기화 방식으로 heuristic 또는 estimated를 선택할 수 있다. Box-Cox 변환, 감쇠 추세, 일부 구현의 외생 회귀도 성능과 안정성을 조정하는 수단이다.
ETS 구조는 AICc/BIC로 비교할 수 있다. 잔차는 ACF를 통한 백색성, 정규성, 이분산성을 점검하고, 일반화 성능은 롤링-오리진 교차검증으로 확인한다. 레벨·추세·계절 성분이 분리되므로 원인을 파악하기 쉽고, 파라미터 수가 적어 과적합 위험도 낮다. 수천~수십만 시계열을 배치로 처리하거나 병렬화하는 환경에도 맞는다.
수요와 운영 지표에서의 활용
수요·재고 예측에서는 SKU나 매장 단위의 단기 예측에 적용할 수 있다. 주·월 단위의 승법 계절성과 감쇠 추세 조합을 고려하고, 품절 또는 프로모션 구간을 마스킹한 뒤 적합한다. 잔차 이상 탐지는 경보 기준으로도 활용된다.
일·주간 트래픽과 전환율 예측은 용량 계획에 쓰인다. 예측구간과 실제 관측값의 편차를 보면 SLO 위반을 조기에 탐지할 수 있다.
에너지, 운송, 콜센터처럼 시간대별 수요 변동이 큰 업무에서는 차고지와 인력 배치에 반영한다. 시간 단위는 (m=24), 요일 단위는 (m=7)처럼 계절 주기를 둘 수 있으며, 다중 주기는 사전 변환 또는 분해를 적용한다.
적합·검증·운영으로 이어지는 흐름
입력으로는 시계열 (y_t), 시간 인덱스, 계절 주기 (m), 최소 관측 길이(계절×2 이상 권장)가 필요하다. 결측치와 이상치의 처리 정책, 승법 모형의 양수 제약도 먼저 정한다.
결측 보간과 이상치 윈저라이징을 수행하고, 필요하면 Box-Cox((\lambda))를 선택한다. SES, Holt, Holt-Winters의 가법·승법 모형, ETS 조합을 후보로 둔 뒤 MLE로 모수를 추정한다. 초기화와 수렴을 확인하고 잔차 진단 결과에 따라 재적합한다. 검증에서는 롤링-오리진 CV의 MAPE/MASE와 정보기준을 함께 본다.
운영 결과물에는 최종 모델, 예측치와 구간, 레벨·추세·계절 성분 분해, 진단 리포트가 포함된다. 재적합 주기, 경보 임계값, 모델 카드는 운영 파라미터로 관리한다.
후보 모형의 특성과 제약
| 모델 | 성능(정확도) | 확장성(대량 시계열) | 일관성(가정 적합성) | 안정성(이상치 민감도) | 운영 편의 |
|---|---|---|---|---|---|
| SES | 추세/계절 없을 때 우수 | 매우 높음 | 단순 레벨 가정 | 높음(민감) | 매우 쉬움 |
| Holt(DES) | 완만한 추세에서 우수 | 매우 높음 | 선형 추세 가정 | 중간 | 쉬움 |
| Holt-Winters(가법) | 일정 분산 계절에 우수 | 높음 | 가법 계절 가정 | 중간 | 보통 |
| Holt-Winters(승법) | 수준 비례 계절에 우수 | 높음 | 승법 계절·양수 제약 | 중간~낮음(0 근처 취약) | 보통 |
| ETS(자동 선택) | 데이터 따라 최고 | 높음 | 구조/오차 선택 유연 | 중간(구조 의존) | 보통 |
성능 평가는 데이터 특성에 좌우된다. 분산이 증가하는 경우에는 승법 모형 또는 변환을 고려한다.
Python으로 모델별 예측 결과 비교
전제조건은 Python 3.10+, pandas 2.x, statsmodels 0.14+, numpy, scipy다. 승법 모형을 사용하려면 시계열이 양수여야 하며, 아래 예시는 월별 (m=12)를 사용한다.
# pip install pandas numpy statsmodels scipy
import warnings
warnings.filterwarnings("ignore")
import numpy as np
import pandas as pd
from sklearn.metrics import mean_absolute_percentage_error
from statsmodels.tsa.holtwinters import SimpleExpSmoothing, Holt, ExponentialSmoothing
from statsmodels.tsa.exponential_smoothing.ets import ETSModel
from statsmodels.tools.sm_exceptions import ConvergenceWarning
# 1) 데이터 생성: 추세 + 계절 + 잡음 (월별 6년)
rng = pd.period_range("2018-01", periods=72, freq="M").to_timestamp()
np.random.seed(42)
trend = np.linspace(50, 80, 72)
season = 10 + 8*np.sin(2*np.pi*np.arange(72)/12)
noise = np.random.normal(0, 2.0, 72)
y = pd.Series(trend + season + noise, index=rng)
# 2) 학습/검증 분할
train, test = y.iloc[:-12], y.iloc[-12:]
m = 12
def fit_and_forecast(train, horizon):
results = {}
# SES
try:
ses = SimpleExpSmoothing(train, initialization_method="estimated").fit()
results["SES"] = ses.forecast(horizon)
except Exception as e:
results["SES"] = pd.Series([np.nan]*horizon, index=test.index)
# Holt (감쇠 추세 포함)
try:
holt = Holt(train, damped_trend=True, initialization_method="estimated").fit()
results["Holt_damped"] = holt.forecast(horizon)
except Exception:
# 감쇠 실패 시 비감쇠 대체
holt = Holt(train, damped_trend=False, initialization_method="estimated").fit()
results["Holt_linear"] = holt.forecast(horizon)
# Holt-Winters 가법
try:
hwa = ExponentialSmoothing(
train, trend="add", seasonal="add", seasonal_periods=m,
initialization_method="estimated"
).fit(optimized=True, use_brute=True)
results["HW_add"] = hwa.forecast(horizon)
except Exception:
results["HW_add"] = pd.Series([np.nan]*horizon, index=test.index)
# Holt-Winters 승법 (양수 제약)
if (train > 0).all():
try:
hwm = ExponentialSmoothing(
train, trend="add", seasonal="mul", seasonal_periods=m,
initialization_method="estimated"
).fit(optimized=True, use_brute=True)
results["HW_mul"] = hwm.forecast(horizon)
except Exception:
results["HW_mul"] = pd.Series([np.nan]*horizon, index=test.index)
# ETS 자동(예: A,A,A 탐색)
try:
ets = ETSModel(train, error="add", trend="add", seasonal="add",
seasonal_periods=m).fit()
results["ETS_AAA"] = ets.forecast(horizon)
except (ConvergenceWarning, Exception):
# 단순 ETS 대체
ets = ETSModel(train, error="add", trend="add", seasonal=None).fit()
results["ETS_AAN"] = ets.forecast(horizon)
return results
res = fit_and_forecast(train, len(test))
# 3) 평가
for name, fcst in res.items():
if fcst.isna().any():
continue
mape = mean_absolute_percentage_error(test, fcst)
print(f"{name:10s} MAPE={mape:.3f}")
# 4) 결과 확인
df_out = pd.DataFrame({"actual": test})
for k, v in res.items():
df_out[k] = v
print(df_out.head(3))
최적화가 실패하면 initialization_method="heuristic"을 시도하거나 파라미터 경계를 조정한다. 승법 모델은 0이나 음수가 포함되면 실패하므로, 로그 또는 Box-Cox 변환 후 가법 모델을 적용한다. 많은 시계열은 시계열별 독립 병렬 처리로 선형 확장할 수 있다.
예측 운영에서 기대할 수 있는 변화
단순한 계절+추세 데이터에서는 나이브 대비 MAPE가 1030% 개선될 수 있으며, 수천 시계열을 동시에 학습할 때 ARIMA 대비 훈련 시간을 520배 단축할 수 있다. 두 결과 모두 데이터, 구현, 하드웨어에 의존한다. ETS 기반 모델 선택 자동화는 수동 튜닝 시간을 50% 이상 줄일 수 있다.
성분 분해는 설명 가능성을 높여 운영 의사결정의 신뢰도를 돕는다. 상태 업데이트가 간결하므로 실시간·스트리밍 예측에도 적용하기 쉽다. 분산 구조에 맞는 가법·승법 선택, MLE와 정보기준, 롤링 검증을 함께 적용하면 지수평활은 대량 배치와 실시간 예측의 기본 베이스라인 또는 운영 모델이 될 수 있다.