소매업체는 매년 12월이면 연말 쇼핑 시즌 재고를 비축합니다. 여름이면 전력망은 에어컨 사용 급증에 대비하죠. 이런 패턴은 해마다 반복됩니다. 이 사실을 무시한 시계열 예측을 만든다면, 정확도를 스스로 낮추는 셈입니다.
계절 자기회귀 누적이동평균 모델(SARIMA)은 널리 쓰이는 ARIMA 프레임워크를 확장해, 규칙적인 추세와 함께 반복되는 계절 패턴까지 포착합니다. 이 글에서는 SARIMA가 무엇인지, 구성 요소가 어떻게 작동하는지, 언제 ARIMA보다 SARIMA를 선택해야 하는지, 그리고 Python으로 단계별로 구축하는 방법을 알아봅니다.
SARIMA란?
SARIMA는 비계절 및 계절 패턴을 모두 다루는 시계열 예측 모델입니다. ARIMA를 직접적으로 기반으로 하므로, ARIMA를 다뤄본 분이라면 대부분의 메커니즘이 익숙할 것입니다. 핵심 차이는 SARIMA가 월별, 분기별, 주별 같은 고정 간격으로 반복되는 거동을 모델링하도록 설계된 두 번째 매개변수 층을 추가한다는 점입니다.
형식적으로 SARIMA 모델은 SARIMA(p, d, q)(P, D, Q)[S]로 표기합니다. 첫 번째 매개변수 집합 (p, d, q)은 표준 ARIMA와 동일하게 비계절 구조를 다룹니다. 두 번째 집합 (P, D, Q)[S]는 계절 패턴을 설명하며, S는 계절 주기의 길이입니다. 월별 데이터의 연간 계절성에는 S = 12, 분기별 데이터에는 S = 4를 사용합니다.
SARIMA의 핵심 구성 요소
SARIMA의 일곱 가지 매개변수는 처음엔 복잡하게 느껴질 수 있습니다. 익숙한 ARIMA 3요소(p, d, q)와 이를 계절 스케일에서 반영한 계절 대응 요소(P, D, Q, S) 두 그룹으로 생각하면 쉽습니다. 각 계절 매개변수는 비계절 쌍과 동일한 역할을 하되, 인접 시점이 아니라 계절 간격에 적용됩니다.
자기회귀(AR) 부분
AR 구성 요소는 과거 값으로 미래 값을 예측합니다. 매개변수 p는 포함할 시차의 개수를 지정합니다. p = 2이면, 현재 값을 예측하기 위해 직전 두 시점을 사용합니다.
계절 측면에서 P는 계절 시차에 대해 같은 일을 합니다. P = 1이고 S = 12라면, 모델은 12기간 전, 즉 전년 같은 달의 값을 예측 변수로 봅니다. 이는 전년 대비 패턴을 직접 포착합니다.
누적(I) 부분
매개변수 d는 추세를 제거해 정상성을 만들기 위해 몇 번 차분할지를 제어합니다. 차분은 각 관측치에서 직전 관측치를 빼는 것으로, 선형 추세를 제거합니다. d = 1이면 1차 차분, d = 2이면 이미 차분된 시계열을 한 번 더 차분합니다.
계절 차분도 동일하지만 계절 시차에서 수행됩니다. D는 적용할 계절 차분의 횟수를 지정합니다. D = 1이고 S = 12이면 각 관측치에서 12기간 전 값을 뺍니다. 일반 추세와 반복 계절 패턴이 모두 있는 시계열에서는 d = 1과 D = 1을 함께 쓰는 것이 흔합니다.
이동평균(MA) 부분
AR 구성 요소가 과거 값을 보는 것과 달리, MA 구성 요소는 현재 관측치와 과거 예측에서 남은 잔차 간의 관계를 모델링합니다. 매개변수 q는 포함할 시차 오차 항의 개수를 설정합니다. q = 1이면, 모델은 직전 단계의 예측 오차를 사용해 현재 예측을 보정합니다.
계절 대응 요소 Q는 같은 논리를 계절 시차에 적용합니다. Q = 1이고 S = 12면, 모델은 12기간 전의 예측 오차를 반영합니다. 이는 이례적으로 더운 여름에 에너지 수요가 크게 늘어나고 그 영향이 다음 해 같은 시기에 반복되는 경우처럼, 계절적 충격이 이어질 때 중요합니다.
계절 구성 요소(S)
S 매개변수는 계절 주기의 길이를 정의하며 세 가지 계절 매개변수(P, D, Q)를 서로 연결합니다. S를 올바르게 설정하는 것이 중요합니다. 월별 데이터에 연간 패턴이 있으면 S = 12, 주간 데이터에 연간 주기가 있으면 S는 대략 52입니다.
여기서 가끔 까다로워지는 부분이 있습니다. 1년은 정확히 52주가 아니라 약 52.18주입니다. 실무에서는 S = 52로 반올림해도 대부분 무리가 없습니다. 하지만 어떤 데이터셋은 여러 계절 주기를 가집니다. 예를 들어 일일 전력 수요는 주간 주기(S = 7)와 연간 주기(S = 365)가 함께 나타납니다. 표준 SARIMA는 하나의 계절 주기만 다루므로, 다중 계절성은 TBATS나 Facebook Prophet 같은 더 고급 방법이 필요합니다.
S가 명확하지 않을 때는 시계열 분해가 도움이 됩니다. 시계열을 추세, 계절, 잔차로 분해하면 지배적인 반복 주기가 시각적으로 드러납니다. 자기상관 함수에서 규칙적인 시차에 스파이크가 있는지도 확인하세요.
ARIMA vs. SARIMA: 무엇이 다른가요?
아마 이렇게 생각하고 계실 겁니다. 실제로 언제 더 간단한 ARIMA 대신 SARIMA를 써야 할까요?
짧은 답: 의미 있는 계절 패턴이 없으면 ARIMA, 있으면 SARIMA를 사용하세요.
ARIMA는 세 가지를 모델링합니다. 시계열 자체의 자기상관(AR), 정상성을 위해 필요한 차분 횟수(I), 과거 예측 오차가 현재 값에 미치는 잔존 영향(MA)입니다. 추세, 순환, 불규칙 잡음을 잘 처리하지만, 고정된 계절 빈도로 반복되는 패턴은 모델링하지 못합니다. 이런 패턴은 설명되지 않은 분산으로 남습니다.
SARIMA는 바로 그 능력을 추가합니다. 데이터에 계절적 봉우리와 골이 뚜렷하다면, 순수 ARIMA를 적합할 경우 그 패턴이 잔차로 밀려나 백색잡음이 아닌 잔차와 더 나쁜 예측으로 이어집니다. SARIMA는 이를 직접 포착합니다.
실무 규칙: 데이터를 그려보고 일정 간격으로 반복되는 패턴을 찾으세요. 연휴 매출 급증, 겨울철 에너지 수요 급증, 분기별 실적 패턴처럼 보이면 SARIMA를 선택하세요. 규칙적 주기 없이 불규칙하거나 추세 중심이라면 ARIMA가 더 단순하고 충분합니다.
저희 Python에서의 ARIMA 모델 강의에서는 두 프레임워크를 모두 다루며, 각각을 언제 적용할지에 대한 직관을 실습으로 기릅니다.
Python으로 SARIMA 모델 구축하기
SARIMA 모델 구축은 논리적인 순서를 따릅니다. 데이터 수집, 정상성 확인, 매개변수 식별, 모델 적합, 진단, 예측입니다. Python의 statsmodels 라이브러리를 사용해 각 단계를 실무적으로 살펴보겠습니다.
데이터 수집
계절성을 포착하려면, 해당 패턴을 최소 두 번, 바람직하게는 여러 주기에 걸쳐 관찰할 수 있을 만큼의 과거 데이터가 필요합니다. 월별 소매 매출, 기온 기록, 에너지 소비량, 승객 수 송량 등이 고전적 예시입니다. 연방준비제도 경제 데이터(FRED), 미국 인구조사국, Kaggle 같은 공개 소스가 좋은 출발점입니다.
이 워크플로에서 표준 교육용 데이터셋은 항공 승객 수입니다. 1949년부터 1960년까지의 월별 데이터로, 뚜렷한 상승 추세와 강한 연간 계절성이 있습니다. statsmodels의 get_rdataset()를 통해 Rdatasets 컬렉션에서 가져올 수 있습니다. 이 데이터로 워크플로를 익힌 뒤 자체 데이터에 적용하세요.
데이터 전처리
SARIMA를 적합하기 전에, 평균과 분산이 시간에 따라 변하지 않는 정상 시계열이 필요합니다. Augmented Dickey-Fuller(ADF) 검정으로 이를 형식적으로 확인합니다. p값이 0.05 미만이면 정상성을 시사합니다.
정상성이 아니면 차분으로 해결합니다. 추세에는 일반 차분(d = 1), 계절 비정상성에는 계절 차분(D = 1, 시차 S), 필요하면 둘 다 적용합니다. 이 단계 전에 결측값을 처리하세요. 시계열 데이터에서는 기간 구조를 깨뜨리는 행 제거 대신 순방향 채우기나 보간이 표준 접근법입니다.
모델 식별
정상 시계열이 준비되면, 자기상관함수(ACF)와 부분자기상관함수(PACF) 도표로 모델 매개변수를 식별합니다. 다음을 확인하세요.
- ACF는 시계열과 그 시차 간의 상관을 보여줍니다. 시차 q 이후 급격한 절단은 MA 차수를 시사합니다. 계절 시차(월별 데이터의 경우 12, 24, 36)의 스파이크는 Q에 대한 정보를 줍니다.
- PACF는 중간 시차 효과를 제거한 부분 상관을 보여줍니다. 시차 p 이후 급격한 절단은 AR 차수를 시사합니다. 계절 스파이크는 P를 결정하는 데 도움을 줍니다.
실무에서는 도표로 후보 값을 얻고, 정보 기준(진단에서 자세히 다룸)으로 몇 가지 모델을 비교합니다. 자동화를 원하면 pmdarima 패키지의 auto_arima()가 매개변수 조합에 대한 그리드 탐색을 수행하고 최적 모델을 선택합니다.
매개변수 추정
후보 매개변수를 정하면, statsmodels는 최대우도추정(MLE)으로 이를 추정해 관측 데이터가 모델 하에서 가장 그럴듯해지도록 계수를 찾습니다. SARIMA 추정은 비계절과 계절 구성 요소를 동시에 맞춰야 하므로 순수 ARIMA보다 계산이 더 많이 듭니다.
적합 과정이 전역 최적해가 아닌 국소 최적해에 수렴하기도 하므로, 결과가 부자연스러우면 시작값이나 매개변수 조합을 몇 가지 달리 시도할 가치가 있습니다.
모델 적합
아래는 항공 승객 데이터셋을 사용해 Python에서 SARIMA 모델을 적합하는 방법입니다.
import pandas as pd
import statsmodels.api as sm
# Load the classic airline dataset
airline_data = sm.datasets.get_rdataset("AirPassengers", "datasets").data
airline_data.index = pd.date_range(start="1949-01", periods=len(airline_data), freq="MS")
passengers = airline_data["value"]
# Fit SARIMA(1,1,1)(1,1,1)[12]
sarima_model = sm.tsa.statespace.SARIMAX(
passengers,
order=(1, 1, 1),
seasonal_order=(1, 1, 1, 12),
enforce_stationarity=False,
enforce_invertibility=False
)
sarima_result = sarima_model.fit(disp=False)
print(sarima_result.summary())
order 인자는 비계절 부분의 (p, d, q), seasonal_order는 (P, D, Q, S)를 받습니다. enforce_stationarity=False와 enforce_invertibility=False를 설정하면 최적화기에 더 많은 유연성을 주어, 실제 데이터에서 수렴을 돕는 경우가 많습니다.
모델 통계와 진단
적합 후, sarima_result.plot_diagnostics()로 내장 진단 도표를 실행합니다. 다음 네 가지를 확인하세요.
- 표준화 잔차: 뚜렷한 패턴 없이 백색잡음처럼 보여야 합니다.
- 잔차 히스토그램: 대략 정규분포여야 합니다.
- 정규 Q-Q 플롯: 점들이 대각선에 가깝게 놓여야 합니다.
- 상관도(잔차의 ACF): 유의한 스파이크가 없어야 하며, 이는 설명되지 않은 자기상관을 의미합니다.
특히 상관도에서 계절 시차에 주목하세요. 12, 24 같은 시차에서의 스파이크는 계절 구성 요소가 충분히 포착되지 않았음을 시사합니다. AIC(아카이케 정보 기준)와 BIC(베이지안 정보 기준)로 대안 명세를 비교하세요. 값이 낮을수록 적합이 좋으며, BIC는 복잡성을 더 강하게 페널티합니다.
예측
검증된 모델이 준비되면 예측은 간단합니다. 학습/테스트로 데이터를 분할해 예측 정확도를 공정하게 평가하세요.
# Train on first 11 years, test on final year
train = passengers[:"1959"]
test = passengers["1960":]
# Refit on training data and forecast
sarima_train = sm.tsa.statespace.SARIMAX(
train,
order=(1, 1, 1),
seasonal_order=(1, 1, 1, 12),
enforce_stationarity=False, # add this
enforce_invertibility=False # add this
).fit(disp=False)
forecast = sarima_train.get_forecast(steps=12)
forecast_mean = forecast.predicted_mean
conf_int = forecast.conf_int()
get_forecast() 메서드는 포인트 예측과 함께, 예측 범위가 멀어질수록 넓어지는 신뢰구간을 반환합니다. 이는 결함이 아니라, 불확실성을 정직하게 반영한 결과입니다. 홀드아웃 테스트셋에 대해 RMSE(평균제곱근오차)나 MAPE(평균절대백분율오차)로 정확도를 평가하세요.
SARIMA의 실무 활용
현실 세계의 많은 신호가 계절적이므로, SARIMA는 어떤 시계열 도구 상자에서도 빠지지 않는 기본 도구입니다. 산업별 몇 가지 예시는 다음과 같습니다.
- 리테일: 재고 계획을 위한 월별 판매량 예측. 특히 매년 변동 폭은 다르지만 수요 급증이 예측 가능한 연휴 시즌에 유용합니다.
- 에너지 소비: 기온과 활동 패턴에 의해 주도되는 일별·연간 계절 주기를 따르는 전기·가스 수요 예측.
- 금융: 회계 캘린더에 맞춰 반복되는 분기별 실적이나 거래량 패턴 모델링.
- 기상 예측: 강한 연간 주기를 따르는 기온, 강수량 등 기후 변수의 전망.
각 경우에서 반복 구조가 곧 신호이며, SARIMA는 이를 포착하도록 설계되어 있습니다.
SARIMA의 한계
어떤 도구가 잘 작동하는 영역을 아는 것만으로는 충분치 않습니다. SARIMA는 계절 시계열에 대한 탄탄한 기준선이지만, 한계를 아는 것이 모델을 잘 쓰는 사람과 맹목적으로 쓰는 사람을 가릅니다.
SARIMA는 정확히 하나의 계절 주기만 처리합니다. 데이터에 일별·주별·연간 패턴이 겹쳐 있다면, SARIMA는 이를 한 번에 모두 모델링하지 못합니다. TBATS, Prophet, LSTM 네트워크 등은 다중 계절 주기를 더 자연스럽게 다룹니다.
또한 SARIMA는 선형성을 가정합니다. 과거 값, 과거 오차, 미래 관측치 간의 선형 관계를 모델링합니다. 금융 시계열이나 혼돈계처럼 비선형 동학이 일반적인 경우에는 다른 도구가 필요합니다. 그리고 ARIMA와 마찬가지로 SARIMA는 시계열 자체의 과거만 사용합니다. 예측에 영향을 주는 외생 요인(프로모션, 기상 이벤트, 경제 지표 등)이 있다면, 외생 변수를 추가한 SARIMAX를 고려하세요.
마지막으로, 매개변수 선택은 정말 어려울 수 있습니다. 일곱 개의 매개변수를 조정해야 하므로 탐색 공간이 크고, 긴 시계열에서는 적합이 느릴 수 있습니다. pmdarima의 auto_arima()는 이를 자동화하는 데 도움이 됩니다. 하지만 매개변수가 실제로 무엇을 의미하는지 이해하는 지름길은 없습니다. 그래서 코드를 다루기 전에 구성 요소를 먼저 설명했습니다.
결론
저는 입문 예측 강의에서 SARIMA가 과소평가된다고 늘 생각해 왔습니다. 보통 "계절 요소가 추가된 ARIMA"로 가볍게 소개되는데, 그 이상입니다. 계절 매개변수는 덧붙여진 요소가 아니라, ARIMA로는 닿을 수 없는 데이터 거동의 한 층위를 구조적으로 포착합니다.
실무에서 SARIMA가 제대로 와닿는 순간은 비계절과 계절 구성 요소가 병렬로 따로 작동하는 모델이 아니라는 점을 깨달을 때입니다. AR과 MA 항은 계절 쌍과 함께 작동하며, 서로 다른 시간 규모의 자기상관을 분담합니다. 이 점이 이해되면, ACF와 PACF 도표 읽기가 패턴 맞추기가 아니라 데이터를 실제로 이해하는 과정처럼 느껴집니다.
월별, 분기별, 혹은 규칙적으로 순환하는 데이터로 작업한다면 SARIMA가 출발점으로 적합합니다. 항상 최종 해답이라서가 아니라, 시계열의 구조를 명확히 생각하도록 이끌어 주기 때문입니다. 그다음은 SARIMAX로 외생 변수를 추가하고, TBATS나 Prophet 같은 방법으로 더 복잡한 다중 계절성을 다룰 수 있습니다. 저희의 시계열 예측 튜토리얼과 Python에서의 ARIMA 모델 강의가 다음 단계로 좋습니다.
SARIMA 자주 묻는 질문
SARIMA는 무엇의 약자인가요?
SARIMA는 Seasonal AutoRegressive Integrated Moving Average의 약자입니다. 표준 ARIMA 모델에 계절 매개변수—(P, D, Q)와 계절 주기 S—를 추가해, 월별이나 분기별 주기처럼 시계열 데이터에서 반복되는 패턴을 포착합니다.
ARIMA와 SARIMA의 차이는 무엇인가요?
ARIMA는 비계절 패턴—추세, 자기상관, 이동평균 효과—을 모델링합니다. SARIMA는 같은 효과를 계절 시차에서 모델링하는 두 번째 매개변수 층(P, D, Q, S)을 추가합니다. 데이터에 일정 간격으로 반복되는 패턴, 예를 들어 매년 12월에 더 높은 매출이 보인다면, SARIMA는 이를 직접 포착하는 반면 ARIMA는 설명되지 않은 잔차 분산으로 남깁니다.
적절한 SARIMA 매개변수는 어떻게 선택하나요?
먼저 Augmented Dickey-Fuller 검정으로 시계열이 정상인지 확인하세요. 그런 다음 ACF와 PACF 도표를 살펴봅니다. 비계절 AR(p)과 MA(q) 차수는 비계절 시차에서의 절단 패턴에서, 계절 차수 P와 Q는 계절 시차의 스파이크에서 유추합니다. 또한 pmdarima 패키지의 auto_arima()로 매개변수 조합을 자동 탐색하고 AIC나 BIC를 사용해 최적 모델을 선택할 수 있습니다.
SARIMA 모델의 계절 주기 S는 어떻게 결정하나요?
계절 주기 S는 패턴이 얼마나 자주 반복되는지를 반영합니다. 월별 데이터의 연간 계절성에는 S = 12, 분기별에는 S = 4, 주간 데이터에는 S = 52(또는 52.18을 반올림)입니다. 주기가 명확하지 않다면, 시계열 분해를 사용하거나 ACF 도표에서 규칙적으로 간격을 둔 스파이크를 확인하세요. 이 스파이크가 지배적인 계절 주파수를 드러냅니다.
SARIMA는 여러 계절 주기를 처리할 수 있나요?
표준 SARIMA는 한 번에 하나의 계절 주기만 처리합니다. 일일 전력 수요처럼 주간과 연간 주기가 모두 있는 다중 계절성 데이터라면, TBATS, Facebook Prophet, LSTM 네트워크 같은 대안을 사용해야 합니다. 이들은 여러 겹의 계절 구조를 동시에 모델링하도록 설계되었습니다.
SARIMA 모델 적합에 가장 적합한 Python 라이브러리는 무엇인가요?
Python의 statsmodels 라이브러리가 표준 선택입니다. 여기서 제공하는 SARIMAX()는(외생 변수가 없어도 SARIMA 모델을 적합할 만큼) 충분히 유연합니다. 매개변수 자동 선택을 위해서는 pmdarima 라이브러리의 auto_arima()가 그리드 탐색을 수행하므로, 시작값을 정하기 어려울 때 워크플로에 추가할 만합니다.
내 SARIMA 모델이 잘 맞는지 어떻게 평가하나요?
적합 후 결과 객체에서 plot_diagnostics()를 실행해, 잔차가 구조 없이 백색잡음처럼 보이는지—특히 ACF에서 계절 시차 스파이크가 없는지—확인하세요. AIC나 BIC(낮을수록 좋음)로 경쟁 모델 명세를 비교합니다. 홀드아웃 데이터의 예측 정확도 평가는 RMSE와 MAPE가 가장 흔한 지표입니다.
SARIMAX란 무엇이며, 언제 SARIMA 대신 사용해야 하나요?
SARIMAX는 SARIMA 프레임워크에 외생 변수—외부 예측 변수—를 추가합니다. 소매 매출에 영향을 주는 프로모션 집행, 에너지 수요에 영향을 주는 기온, 분기 매출에 영향을 주는 거시경제 지표처럼, 시계열 자체의 역사 외에 측정 가능한 요인이 있을 때 사용하세요. 데이터가 시계열 하나뿐이면 SARIMA로 충분하지만, 관련 외생 요인이 있다면 SARIMAX로 이를 직접 반영할 수 있습니다.