ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 시계열 데이터, 분석, 예측 모델이란?
    공부/데이터 2026. 4. 26. 20:34

    시계열(Time Series)은 데이터 엔지니어링과 데이터 과학에서 가장 자주 다루는 데이터 유형 중 하나입니다. 본 문서에서는 시계열 데이터의 개념, 분석 방법, 그리고 대표적인 모델까지 순서대로 정리합니다.


    1. 시계열 데이터란?

    1-1. 정의

    시계열 데이터(Time Series Data)란 일정한 시간 간격으로 순서대로 수집된 데이터의 집합입니다. 각 데이터 포인트는 특정 시점(timestamp)에 대응하며, 시간의 흐름에 따라 값이 어떻게 변화하는지를 나타냅니다.

    예를 들어 다음과 같은 데이터가 시계열 데이터에 해당합니다.

    • 주식 가격 (매 분/일/주 단위 종가)
    • 기온 및 날씨 측정값 (매 시간 단위)
    • 서버 CPU 사용률 (매 초 단위)
    • 월별 매출액
    • 일별 활성 사용자 수(DAU)

    1-2. 시계열 데이터의 특징

    시계열 데이터는 일반적인 테이블 형태의 데이터와 구별되는 다음과 같은 특징을 가집니다.

    • 순서 의존성: 데이터 포인트의 순서가 의미를 가집니다. 과거 값이 미래 값에 영향을 줍니다.
    • 자기 상관(Autocorrelation): 동일한 시계열 내에서 서로 다른 시점의 값이 상관관계를 가집니다.
    • 시간 인덱스: 반드시 시간 축(timestamp)이 존재합니다.
    • 결측값 처리 난이도: 특정 시점의 데이터가 누락되면 보간(interpolation)이 필요합니다.

    1-3. 시계열 데이터의 구성 요소

    시계열 데이터는 일반적으로 다음 네 가지 요소의 조합으로 분해할 수 있습니다.

    요소 설명 예시
    추세(Trend) 장기적인 증가 또는 감소 방향 연도별 인터넷 사용자 수 증가
    계절성(Seasonality) 일정한 주기로 반복되는 패턴 여름철 에어컨 판매량 급증
    주기성(Cyclicity) 불규칙하지만 반복되는 장기 변동 경기 순환에 따른 실업률 변화
    불규칙 성분(Residual/Noise) 위 세 요소로 설명되지 않는 랜덤 변동 갑작스러운 이벤트나 오류

    1-4. 활용 분야

    시계열 데이터는 다양한 산업과 도메인에서 활용됩니다.

    • 금융: 주가 예측, 환율 분석, 리스크 관리
    • 제조/IoT: 설비 이상 탐지, 예측 정비(Predictive Maintenance)
    • 리테일: 수요 예측, 재고 최적화
    • 에너지: 전력 수요 예측
    • 의료: 환자 바이탈 모니터링, 질병 발생 예측
    • IT 운영: 서버 트래픽 이상 탐지, 용량 계획

    2. 시계열 분석이란?

    2-1. 정의

    시계열 분석(Time Series Analysis)이란 시간 순서로 정렬된 데이터에서 패턴, 추세, 관계를 통계적으로 탐색하고 미래 값을 예측하는 일련의 기법을 의미합니다.

    2-2. 분석 목적

    시계열 분석의 주요 목적은 다음과 같습니다.

    • 기술(Description): 과거 데이터의 패턴과 특성을 요약합니다.
    • 예측(Forecasting): 미래 시점의 값을 추정합니다.
    • 이상 탐지(Anomaly Detection): 정상 범위를 벗어난 값을 감지합니다.
    • 인과 분석(Causal Analysis): 특정 변수가 다른 변수에 미치는 영향을 분석합니다.

    2-3. 정상성(Stationarity)

    시계열 분석에서 가장 핵심적인 개념 중 하나는 정상성(Stationarity)입니다.

    정상 시계열(Stationary Time Series)이란 시간이 지나도 평균, 분산, 자기공분산이 일정한 시계열을 의미합니다. 대부분의 전통적인 시계열 모델은 데이터가 정상성을 만족한다고 가정합니다.

    정상성 검정에는 다음과 같은 방법이 사용됩니다.

    • ADF 검정(Augmented Dickey-Fuller Test): 단위근(Unit Root) 존재 여부를 검정합니다.
    • KPSS 검정: 정상성을 귀무가설로 검정합니다.
    • 시각적 확인: 시계열 플롯, ACF/PACF 그래프를 통해 패턴을 직접 관찰합니다.

    비정상 시계열은 차분(Differencing), 로그 변환, 추세 제거 등의 방법으로 정상 시계열로 변환합니다.

    2-4. 주요 분석 도구

    도구 설명
    ACF (자기상관함수) 현재 값과 과거 값 사이의 상관관계를 시차(lag)별로 측정합니다
    PACF (편자기상관함수) 중간 시차 효과를 제거한 순수한 자기상관을 측정합니다
    시계열 분해(Decomposition) 추세, 계절성, 잔차로 분리합니다
    스펙트럼 분석 주파수 도메인에서 주기성을 분석합니다

    2-5. 분석 절차

    일반적인 시계열 분석은 다음 단계로 진행됩니다.

    1. 데이터 수집 및 전처리: 결측값 처리, 이상값 제거, 리샘플링
    2. 탐색적 분석(EDA): 시각화, 추세 및 계절성 확인
    3. 정상성 검정 및 변환: ADF 검정 후 필요 시 차분 적용
    4. 모델 선택 및 학습: ACF/PACF 분석을 기반으로 파라미터 결정
    5. 모델 평가: MAE, RMSE, MAPE 등의 지표로 성능 측정
    6. 예측 및 모니터링: 실제 운영 환경에서 예측값 생성 및 드리프트 감지

    3. 시계열 모델이란?

    시계열 모델은 크게 전통 통계 모델, 머신러닝 모델, 딥러닝 모델로 구분할 수 있습니다.

    3-1. 전통 통계 모델

    AR (자기회귀 모델, AutoRegressive)

    AR 모델은 현재 값이 과거 값들의 선형 조합으로 표현되는 모델입니다.

    현재값 = 과거 p개 시점의 값들의 가중합 + 오차항

    • 파라미터 p: 몇 시점 전까지의 값을 사용할지 결정합니다 (PACF로 결정).

    MA (이동평균 모델, Moving Average)

    MA 모델은 현재 값이 과거 오차항들의 선형 조합으로 표현되는 모델입니다.

    • 파라미터 q: 몇 시점 전까지의 오차를 사용할지 결정합니다 (ACF로 결정).

    ARMA

    ARMA(p, q) 모델은 AR과 MA를 결합한 모델입니다. 정상 시계열에 적용합니다.

    ARIMA

    ARIMA(p, d, q)는 비정상 시계열에 d번 차분을 적용하여 정상화한 뒤 ARMA를 적용하는 모델입니다.

    • p: AR 차수
    • d: 차분 횟수
    • q: MA 차수

    SARIMA

    SARIMA(p, d, q)(P, D, Q, s)는 ARIMA에 계절성 요소를 추가한 모델입니다. 연간 계절성이 있는 데이터(월별 매출, 기온 등)에 적합합니다.

    ARIMA+ (ARIMAX)

    ARIMA+는 ARIMA 모델에 외부 변수(Exogenous Variables)를 추가로 포함시킨 확장 모델입니다. ARIMAX(AutoRegressive Integrated Moving Average with eXogenous inputs)라고도 부릅니다.

    • 기본 ARIMA가 시계열 자체의 과거 값과 오차만을 사용하는 것과 달리, 외부 설명 변수(예: 기온, 프로모션 여부, 공휴일)를 입력으로 함께 사용합니다.
    • 예측 대상에 영향을 미치는 외부 요인이 명확히 존재할 때 ARIMA 대비 예측 성능이 향상됩니다.
    • Nixtla의 StatsForecast 라이브러리에서는 ARIMA 클래스에 외부 회귀 변수를 지원하는 형태로 제공됩니다.
    • 주의할 점은 예측 시점의 외부 변수 값도 미리 알고 있어야 한다는 점입니다.
    모델 정상성 필요 계절성 처리 특징
    AR 필요 불가 단순, 해석 용이
    MA 필요 불가 단기 충격 모델링
    ARMA 필요 불가 AR+MA 결합
    ARIMA 불필요 불가 차분으로 정상화
    SARIMA 불필요 가능 계절성 포함
    ARIMA+ 불필요 불가 외부 변수 포함, ARIMAX

    3-2. 머신러닝 기반 모델

    Prophet (Facebook/Meta)

    Prophet은 Meta(구 Facebook)에서 공개한 오픈소스 시계열 예측 라이브러리입니다.

    • 비선형 추세, 계절성(연간·주간·일간), 공휴일 효과를 자동으로 모델링합니다.
    • 결측값과 이상값에 강건(robust)합니다.
    • 비전문가도 쉽게 사용할 수 있도록 설계되었습니다.
    • 가산(additive) 또는 승산(multiplicative) 모드를 선택할 수 있습니다.

    NeuralProphet

    NeuralProphet은 Meta의 Prophet을 기반으로 딥러닝(AR-Net)을 결합하여 확장한 하이브리드 모델입니다. PyTorch로 구현되어 있으며, Prophet의 직관적인 분해 구조를 유지하면서 신경망의 표현력을 추가한 것이 특징입니다.

    • 자기회귀 신경망(AR-Net)을 통해 과거 시점의 패턴을 학습합니다.
    • Prophet과 동일하게 추세, 계절성, 공휴일 효과를 명시적으로 모델링합니다.
    • 다단계 예측(Multi-step Forecasting)을 직접 지원합니다.
    • 외부 공변량(Covariates)을 미래 값이 알려진 변수와 알려지지 않은 변수로 구분하여 처리할 수 있습니다.
    • Prophet보다 학습 데이터가 많을 때 성능이 향상되며, 대규모 시계열에서 배치 학습이 가능합니다.

    LightGBM / XGBoost 기반 접근

    트리 기반 모델을 시계열에 적용할 때는 시차 피처(lag features), 롤링 통계(rolling statistics), 날짜 파생 변수 등을 수동으로 생성하여 활용합니다.

    • 다변량(multivariate) 시계열에서 외부 변수(exogenous variables)를 쉽게 포함할 수 있습니다.
    • 해석 가능성이 높고 학습 속도가 빠릅니다.

    3-3. 딥러닝 기반 모델

    LSTM (Long Short-Term Memory)

    LSTM은 RNN(순환 신경망)의 장기 의존성(long-term dependency) 문제를 해결하기 위해 설계된 모델입니다.

    • 게이트 구조(입력 게이트, 망각 게이트, 출력 게이트)를 통해 장기 패턴을 학습합니다.
    • 복잡한 비선형 패턴 학습에 적합합니다.
    • 학습 데이터가 충분해야 성능을 발휘합니다.

    Transformer 기반 모델

    Transformer 아키텍처를 시계열에 적용한 모델들이 최근 각광받고 있습니다.

    • Informer: 긴 시퀀스 예측에 특화된 효율적인 Attention 메커니즘을 사용합니다.
    • Temporal Fusion Transformer (TFT): 다변량 시계열 예측에서 높은 성능을 보이며 해석 가능성을 제공합니다.
    • PatchTST: 시계열을 패치(patch) 단위로 처리하여 효율성을 높입니다.
    • iTransformer (ICLR 2024 Spotlight): 기존 Transformer가 시간 축(time steps)에 Attention을 적용하는 것과 달리, 변수 축(variate)을 토큰으로 전환하여 다변량 상관관계를 학습합니다. 장기 예측(Long-term Forecasting)에서 우수한 성능을 보이며, 변수 간 의존성이 강한 데이터에 특히 효과적입니다.

    N-BEATS / N-HiTS

    순수 딥러닝 기반의 시계열 예측 모델로, 재귀적 잔차 블록 구조를 사용합니다. 통계 모델 없이도 높은 예측 성능을 달성합니다.

    TimeMixer (ICLR 2024)

    TimeMixer는 순수 MLP 기반의 시계열 예측 모델입니다. 시계열을 다중 해상도(Multiscale)로 분해하여 Past-Decomposable-Mixing(PDM)과 Future-Multipredictor-Mixing(FMM) 블록으로 처리합니다.

    • Transformer 없이 MLP만으로 장기·단기 예측 모두에서 state-of-the-art 성능을 달성합니다.
    • GPU 메모리와 연산 효율이 우수하며 다양한 시계열 길이에 대응합니다.
    • 이상 탐지, 결측값 보간, 분류 등 시계열 전반의 태스크를 지원하는 범용 모델로 발전하였습니다.

    3-4. 시계열 파운데이션 모델

    시계열 파운데이션 모델(Time Series Foundation Model)은 수억~수천억 개의 실제 시계열 데이터로 사전 학습(pre-training)된 대규모 모델입니다. 별도의 파인튜닝 없이 제로샷(Zero-Shot) 예측이 가능하며, LLM의 발전 방향을 시계열 도메인에 적용한 흐름입니다.

    Chronos (Amazon, TMLR 2024)

    Amazon에서 개발한 파운데이션 모델로, T5 계열 LLM을 시계열 예측에 재목적화(repurpose)한 모델입니다.

    • 시계열 값을 스케일링·양자화하여 토큰 어휘(vocabulary)로 변환하는 방식을 사용합니다.
    • 약 1천억 개의 실제 시계열 데이터로 사전 학습하였습니다.
    • 확률적 예측(Probabilistic Forecasting)을 지원합니다.
    • 후속 버전인 Chronos-Bolt는 Chronos 대비 추론 속도를 대폭 개선하였으며, GIFT-Eval 제로샷 벤치마크에서 최상위 성능을 기록하였습니다.

    TimesFM (Google, ICML 2024)

    Google Research에서 개발한 디코더 전용(decoder-only) Transformer 기반 파운데이션 모델입니다.

    • 1천억 개의 실제 시계열 데이터 포인트로 사전 학습되었습니다.
    • 시계열을 패치(patch) 단위로 나누어 로컬 의미 정보를 추출합니다.
    • 포인트 예측(Point Forecast)에 집중하는 결정론적(deterministic) 모델입니다.
    • 출시 시점 GIFT-Eval 제로샷 벤치마크 1위를 기록하였으며, 현재 버전 2.5까지 출시되었습니다.

    Moirai (Salesforce, ICML 2024)

    Salesforce에서 개발한 인코더 전용(encoder-only) Transformer 기반 파운데이션 모델입니다.

    • 패치 기반 입력 처리 방식을 사용하며, 4가지 분포의 혼합(Mixture Distribution)으로 유연한 예측 구간을 제공합니다.
    • Moirai 2.0은 디코더 전용 구조로 전환하여 분위수 예측(Quantile Forecasting)과 멀티토큰 예측을 결합하였으며, 3,600만 개의 다양한 시계열 데이터로 학습하였습니다.
    • Moirai-MoE는 Sparse Mixture of Experts 구조를 적용하여, 동일 모델 크기 대비 최대 17% 성능 향상을 달성하고, Chronos 및 TimesFM 대비 최대 65배 적은 활성화 파라미터로 경쟁력 있는 성능을 보입니다.
    모델 개발사 아키텍처 특징
    Chronos Amazon T5 (인코더-디코더) LLM 재목적화, 확률적 예측
    TimesFM Google 디코더 전용 Transformer 100B 포인트 학습, 포인트 예측
    Moirai Salesforce 인코더 전용 Transformer 혼합 분포, 확률적 예측

    3-5. 모델 선택 기준

    상황 권장 모델
    단변량, 간단한 패턴, 소량 데이터 ARIMA, SARIMA
    계절성 강하고 비전문가도 사용 필요 Prophet
    외부 변수가 있는 단변량 시계열 ARIMA+
    Prophet + 딥러닝, 충분한 학습 데이터 NeuralProphet
    다변량, 외부 변수 존재 LightGBM/XGBoost
    복잡한 비선형 패턴, 대량 데이터 LSTM, TFT
    긴 예측 구간, 대규모 데이터 Informer, PatchTST
    다변량, 변수 간 상관관계 중심 iTransformer
    장·단기 모두, 연산 효율 중요 TimeMixer
    학습 데이터 없음 / 제로샷 예측 Chronos, TimesFM, Moirai

    업종별 권장 모델

    업종 고유의 데이터 특성(계절성 강도, 이벤트 빈도, 변동성, 데이터 양)을 기준으로 권장 모델을 정리합니다.

    업종 데이터 특성 권장 모델 선택 근거
    이커머스 — 상시 운영 연간·월별 계절성(여름·겨울), 요일별 패턴, 광고비·카테고리 등 외부 변수 존재 Prophet, LightGBM/XGBoost Prophet은 연·주간 계절성과 공휴일 효과를 자동 모델링. LightGBM은 프로모션·광고비·카테고리 피처를 다변량으로 처리하여 외부 요인 반영에 강점
    이커머스 — 기획전·시즌 세일 (블랙프라이데이, 광군제, 설·추석, 연말 특가) 단기 급등 스파이크(평상시 대비 수십 배), 이벤트 일정 사전 인지 가능, 행사 전후 반동 감소 패턴 Prophet (커스텀 이벤트), ARIMAX, LightGBM Prophet의 holidays / add_regressor로 기획전 구간을 명시적 등록. ARIMAX는 기획전 플래그를 외부 변수로 주입. LightGBM은 프로모션 피처 + 시차 피처 조합으로 스파이크 학습에 실용적
    암호화폐·디지털 자산 극고변동성, 계절성 거의 없음, 뉴스·규제·고래 거래에 민감, 분·초 단위 고빈도 데이터 LSTM, LightGBM (기술적 지표 피처), Informer / PatchTST 비선형 단기 패턴은 LSTM·Transformer 계열이 유리. 장기 예측 신뢰도가 낮으므로 단기(1~24시간) 예측에 집중. RSI·MACD·거래량 등 기술적 지표를 피처로 추가한 LightGBM도 실용적
    배달·푸드테크 시간대별 강한 패턴(점심·저녁), 요일별 차이, 날씨·프로모션 영향, 지역별 다중 시계열 Prophet, SARIMA, LightGBM Prophet은 주간·일간 계절성과 공휴일 처리에 최적. 날씨·할인율 공변량은 LightGBM 또는 NeuralProphet으로 결합. 지역별 다중 시계열이면 iTransformer로 변수 간 상관관계까지 활용 가능
    금융·주식·FX 높은 변동성, 약한 계절성, 거시지표·뉴스 등 외부 요인 중요, 분 단위 이하 고빈도 가능 LSTM, TFT, Chronos / Moirai (확률적 예측) TFT는 다변량 + 해석 가능성(Attention 가중치) 제공. 리스크 관리 목적이면 예측 구간을 제공하는 확률적 모델(Chronos·Moirai) 필수. 장기 예측보다 단기 모멘텀·이상 탐지 용도에 집중 권장
    에너지·전력 강한 일간·연간 주기, 기온·습도 외부 변수 필수, 수요 공급 균형 중요, 안정적 대규모 데이터 SARIMA, ARIMAX, TFT, N-HiTS 일간·계절 이중 주기는 SARIMA가 잘 포착. 기온·습도 외부 변수는 ARIMAX 또는 TFT로 통합. 장기 예측(수일~수주)은 N-HiTS·TimeMixer가 RMSE 기준 우수
    제조·IoT·예측 정비 다변량 센서 데이터, 이상 탐지 중심, 설비 마모·드리프트 패턴, 희소 장애 이벤트 iTransformer, LSTM, TimeMixer 변수 간 상관관계 중심이면 iTransformer. 예측 + 이상 탐지 통합 처리는 TimeMixer. 신규 장비·데이터 희소 구간은 Chronos 제로샷으로 보완
    SaaS·IT 인프라 트래픽 급증·이상 탐지 중심, 배포 이벤트로 인한 구조적 변화(Changepoint), 분·초 단위 메트릭 Prophet, LSTM, TimeMixer, 파운데이션 모델 Prophet은 배포 이벤트를 Changepoint로 자동 포착. LSTM·TimeMixer는 비선형 스파이크 학습에 적합. 신규 서비스·지표처럼 학습 데이터가 부족한 경우 Chronos·TimesFM 제로샷 활용
    헬스케어·의료 환자 바이탈 고빈도 수집, 희귀 이상 탐지, 데이터 수집 불규칙·결측 잦음, 개인정보 규제 LSTM, TimeMixer, Chronos (데이터 부족 시) 불규칙 수집·결측이 많으면 파운데이션 모델(Chronos) 제로샷으로 시작. 충분한 데이터가 확보되면 LSTM·TimeMixer로 고도화. 이상 탐지 전용이면 LSTM 이상 탐지 모드와 결합
    미디어·OTT·콘텐츠 콘텐츠 출시·이벤트 기반 스파이크, 요일·시간대 패턴, 트렌드 급변, 콘텐츠 수명 짧음 Prophet, LightGBM, NeuralProphet Prophet의 커스텀 이벤트로 출시·프로모션 효과 반영. 콘텐츠 메타 피처(장르·마케팅 예산)는 LightGBM으로 처리. 데이터가 충분하면 NeuralProphet으로 딥러닝 결합
    물류·공급망 다품목 SKU 관리, 수요 불규칙·간헐적(0이 많은 SKU), 리드타임 변동, 기획전·계절성 연계 LightGBM (이력 있는 SKU), Chronos (신규 SKU), SARIMA (품목별 단변량) 판매 이력이 있는 SKU는 LightGBM + 시차 피처. 간헐적 수요(0이 많은 SKU)는 Croston·TSBA 계열 전용 모델 우선 검토. 신규 SKU는 Chronos 제로샷으로 콜드 스타트 보완

    4. 모델 평가 지표

    시계열 예측 모델의 성능은 다음 지표로 측정합니다.

    지표 수식 설명 특징
    MAE (평균 절대 오차) 실제값과 예측값의 절대 차이 평균 이상값에 덜 민감
    RMSE (평균 제곱근 오차) 오차 제곱의 평균에 루트 적용 큰 오차에 패널티 부여
    MAPE (평균 절대 백분율 오차) 오차를 실제값 대비 비율로 계산 직관적 해석 가능, 0 근방에서 불안정
    sMAPE (대칭 MAPE) MAPE의 대칭 버전 0 값 처리 개선

    6. 파이썬 라이브러리 및 사용 예시

    각 모델 계열별로 대표적인 파이썬 라이브러리와 최소 동작 예시를 정리합니다.

    6-1. 전통 통계 모델 — statsmodels / statsforecast

    statsmodels는 ARIMA, SARIMA, ARIMAX를 포함한 전통 통계 모델의 표준 라이브러리입니다. Nixtla의 statsforecast는 동일 계열 모델을 훨씬 빠른 속도로 실행하며 AutoARIMA 등 자동화 기능을 제공합니다.

    pip install statsmodels statsforecast

    ARIMA / SARIMA (statsmodels)

    import pandas as pd
    from statsmodels.tsa.statespace.sarimax import SARIMAX
    
    series = pd.Series([112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118])
    
    # ARIMA(1,1,1)
    model = SARIMAX(series, order=(1, 1, 1))
    result = model.fit(disp=False)
    print(result.forecast(steps=3))
    
    # SARIMA(1,1,1)(1,1,1,12) — 월별 계절성
    model_s = SARIMAX(series, order=(1, 1, 1), seasonal_order=(1, 1, 1, 12))
    result_s = model_s.fit(disp=False)
    print(result_s.forecast(steps=3))

    ARIMA+ / ARIMAX (statsmodels)

    import numpy as np
    from statsmodels.tsa.statespace.sarimax import SARIMAX
    
    exog_train = np.array([[1], [0], [1], [0], [1], [0], [1], [0], [1], [0], [1], [0]])
    exog_future = np.array([[1], [0], [1]])
    
    model = SARIMAX(series, exog=exog_train, order=(1, 1, 1))
    result = model.fit(disp=False)
    print(result.forecast(steps=3, exog=exog_future))

    AutoARIMA (statsforecast — 빠른 파라미터 자동 탐색)

    import pandas as pd
    from statsforecast import StatsForecast
    from statsforecast.models import AutoARIMA
    
    df = pd.DataFrame({
        'unique_id': 'item_1',
        'ds': pd.date_range('2020-01-01', periods=36, freq='MS'),
        'y': [112, 118, 132, 129, 121, 135, 148, 148, 136, 119,
              104, 118, 115, 126, 141, 135, 125, 149, 170, 170,
              158, 133, 114, 140, 145, 150, 178, 163, 172, 178,
              199, 199, 184, 162, 146, 166],
    })
    
    sf = StatsForecast(models=[AutoARIMA(season_length=12)], freq='MS')
    sf.fit(df)
    forecast = sf.predict(h=6)
    print(forecast)

    6-2. Prophet / NeuralProphet

    pip install prophet neuralprophet

    Prophet

    import pandas as pd
    from prophet import Prophet
    
    df = pd.DataFrame({
        'ds': pd.date_range('2022-01-01', periods=365, freq='D'),
        'y': range(365),
    })
    
    model = Prophet(
        seasonality_mode='multiplicative',
        yearly_seasonality=True,
        weekly_seasonality=True,
    )
    model.fit(df)
    
    future = model.make_future_dataframe(periods=90)
    forecast = model.predict(future)
    model.plot(forecast)

    NeuralProphet

    import pandas as pd
    from neuralprophet import NeuralProphet
    
    df = pd.DataFrame({
        'ds': pd.date_range('2022-01-01', periods=365, freq='D'),
        'y': range(365),
    })
    
    model = NeuralProphet(
        n_forecasts=30,
        n_lags=60,
        yearly_seasonality=True,
        weekly_seasonality=True,
    )
    model.fit(df, freq='D')
    future = model.make_future_dataframe(df, periods=30)
    forecast = model.predict(future)

    6-3. LightGBM / XGBoost — 시차 피처 방식

    pip install lightgbm xgboost
    import pandas as pd
    import numpy as np
    import lightgbm as lgb
    from sklearn.metrics import mean_absolute_error
    
    def make_lag_features(s: pd.Series, lags=(1, 7, 14, 28)):
        df = pd.DataFrame({'y': s.values})
        for lag in lags:
            df[f'lag_{lag}'] = df['y'].shift(lag)
        df['roll7_mean']  = df['y'].rolling(7).mean()
        df['roll28_std']  = df['y'].rolling(28).std()
        df['dayofweek']   = pd.Series(s.index).dt.dayofweek.values
        return df.dropna()
    
    series = pd.Series(
        np.random.randn(200),
        index=pd.date_range('2022-01-01', periods=200),
    )
    df = make_lag_features(series)
    X, y = df.drop('y', axis=1), df['y']
    
    split = int(len(X) * 0.8)
    X_train, X_test = X.iloc[:split], X.iloc[split:]
    y_train, y_test = y.iloc[:split], y.iloc[split:]
    
    model = lgb.LGBMRegressor(n_estimators=300, learning_rate=0.05)
    model.fit(X_train, y_train)
    preds = model.predict(X_test)
    print('MAE:', mean_absolute_error(y_test, preds))

    6-4. LSTM — PyTorch

    pip install torch
    import torch
    import torch.nn as nn
    import numpy as np
    
    class LSTMForecaster(nn.Module):
        def __init__(self, input_size=1, hidden=64, layers=2, horizon=1):
            super().__init__()
            self.lstm = nn.LSTM(input_size, hidden, layers, batch_first=True)
            self.head  = nn.Linear(hidden, horizon)
    
        def forward(self, x):           # x: [B, seq_len, features]
            out, _ = self.lstm(x)
            return self.head(out[:, -1, :])
    
    model    = LSTMForecaster(hidden=64, layers=2, horizon=7)
    loss_fn  = nn.MSELoss()
    optim    = torch.optim.Adam(model.parameters(), lr=1e-3)
    
    # 더미 학습 루프
    for epoch in range(5):
        x = torch.randn(32, 60, 1)  # [batch=32, seq=60, features=1]
        y = torch.randn(32, 7)      # [batch=32, horizon=7]
        loss = loss_fn(model(x), y)
        optim.zero_grad(); loss.backward(); optim.step()
        print(f'Epoch {epoch+1} Loss: {loss.item():.4f}')

    6-5. TFT / N-BEATS / N-HiTS / iTransformer / TimeMixer — neuralforecast

    Nixtla의 neuralforecast는 TFT, N-BEATS, N-HiTS, PatchTST, iTransformer, TimeMixer 등 최신 딥러닝 시계열 모델을 통일된 API로 제공합니다.

    pip install neuralforecast

    공통 데이터 형식 (unique_id / ds / y)

    import pandas as pd
    import numpy as np
    from neuralforecast import NeuralForecast
    from neuralforecast.models import TFT, NBEATS, NHiTS, iTransformer, TimeMixer
    
    df = pd.DataFrame({
        'unique_id': 'series_1',
        'ds': pd.date_range('2022-01-01', periods=365, freq='D'),
        'y': np.random.randn(365).cumsum(),
    })

    TFT (Temporal Fusion Transformer)

    nf = NeuralForecast(
        models=[TFT(h=30, input_size=60, max_steps=100)],
        freq='D'
    )
    nf.fit(df)
    print(nf.predict())

    N-BEATS / N-HiTS

    nf = NeuralForecast(
        models=[NBEATS(h=30, input_size=60, max_steps=100),
                NHiTS(h=30,  input_size=60, max_steps=100)],
        freq='D'
    )
    nf.fit(df)
    print(nf.predict())

    iTransformer (다변량)

    df_multi = pd.concat([
        df.assign(unique_id='series_1'),
        df.assign(unique_id='series_2', y=np.random.randn(365).cumsum()),
    ])
    
    nf = NeuralForecast(
        models=[iTransformer(h=30, input_size=60, n_series=2, max_steps=100)],
        freq='D'
    )
    nf.fit(df_multi)
    print(nf.predict())

    TimeMixer

    nf = NeuralForecast(
        models=[TimeMixer(h=30, input_size=60, max_steps=100)],
        freq='D'
    )
    nf.fit(df)
    print(nf.predict())

    6-6. 파운데이션 모델 — Chronos / TimesFM / Moirai

    Chronos (Amazon)

    pip install chronos-forecasting
    import torch
    import numpy as np
    from chronos import ChronosPipeline
    
    pipeline = ChronosPipeline.from_pretrained(
        "amazon/chronos-t5-small",   # tiny / mini / small / base / large
        device_map="cpu",
        torch_dtype=torch.bfloat16,
    )
    
    context = torch.tensor(np.random.randn(200), dtype=torch.float32)
    forecast = pipeline.predict(
        context,
        prediction_length=12,
        num_samples=20,
    )
    # forecast: [num_samples, prediction_length]
    median = forecast[0].median(dim=0).values
    print(median)

    TimesFM (Google)

    pip install timesfm[cpu]  # GPU 사용 시: timesfm[gpu]
    import numpy as np
    import timesfm
    
    tfm = timesfm.TimesFm(
        hparams=timesfm.TimesFmHparams(
            backend="cpu",
            per_core_batch_size=32,
            horizon_len=30,
        ),
        checkpoint=timesfm.TimesFmCheckpoint(
            huggingface_repo_id="google/timesfm-1.0-200m-pytorch"
        ),
    )
    tfm.initialize()
    
    forecast_input = [np.random.randn(200).tolist()]
    freq = [0]   # 0: 고빈도(일/시간), 1: 중간(주), 2: 저빈도(월/연)
    
    point_forecast, quantile_forecast = tfm.forecast(forecast_input, freq=freq)
    print(point_forecast)   # shape: [1, horizon_len]

    Moirai (Salesforce)

    pip install uni2ts
    import torch
    from uni2ts.model.moirai import MoiraiForecast, MoiraiModule
    
    model = MoiraiForecast(
        module=MoiraiModule.from_pretrained("Salesforce/moirai-1.1-R-small"),
        prediction_length=12,
        context_length=200,
        patch_size=32,
        num_samples=100,
        target_dim=1,
        feat_dynamic_real_dim=0,
        past_feat_dynamic_real_dim=0,
    )
    
    past_target   = torch.randn(1, 1, 200)                        # [batch, variate, time]
    past_observed = torch.ones(1, 1, 200, dtype=torch.bool)
    
    forecast = model(past_target=past_target, past_observed_target=past_observed)
    # forecast shape: [batch, num_samples, prediction_length]
    print(forecast.median(dim=1).values)   # 분위수 중앙값

    7. 예측 정확도 테스트 및 검증

    시계열 예측 모델의 신뢰성을 확보하려면 모델 개발 단계의 오프라인 테스트부터 실제 서비스 환경에서의 온라인 테스트, 그리고 지속적인 모델 유효성 모니터링까지 단계별로 수행해야 합니다.


    7-1. 오프라인 테스트 (Offline Test)

    오프라인 테스트는 수집된 과거 데이터만을 사용하여 모델 성능을 사전에 평가하는 방법입니다. 실제 서비스 배포 전에 통과해야 하는 기본 검증 단계입니다.

    Hold-out 검증 (단순 분할)

    데이터를 시간 순서를 유지한 상태로 훈련/검증/테스트 세 세트로 분리합니다. 일반 머신러닝의 k-fold CV와 달리, 시계열은 무작위 셔플링이 불가하므로 반드시 거시적 순서를 지켜야 합니다.

    [전체 데이터]
    |<--- 훈련 (70%) --->|<-- 검증(15%) -->|<-- 테스트(15%) -->|
    • 훈련 세트: 모델 파라미터 학습
    • 검증 세트: 하이퍼파라미터 튜닝 및 조기 종료
    • 테스트 세트: 최종 성능 측정 (한 번만 사용)

    백테스트 (Backtesting)

    백테스트는 모델을 과거 데이터에 소급하여 실제에서와 유사한 조건에서 성능을 평가하는 방법입니다. 특정 기간의 데이터로만 훈련하고 그 이후 실제 관측값과 비교합니다.

    시계열 교차검증 (Time Series Cross-Validation)

    단순 Hold-out의 한계를 보완하는 방법으로, 데이터를 여러 구간으로 분할하여 다수의 훈련-테스트 조합으로 성능을 측정합니다. 데이터가 적을 때 유리하며, 운영 환경을 보다 현실적으로 모사합니다.

    두 가지 주요 방식이 있습니다.

    Expanding Window (Walk-Forward) Validation

    시간이 지날수록 훈련 데이터가 누적으로 증가하며 테스트 구간은 고정 크기로 앞으로 이동합니다.

    Fold 1: [===Train===]         [Test]
    Fold 2: [=====Train=====]     [Test]
    Fold 3: [=======Train=======] [Test]
    • 데이터 누적 훈련이라 실제 운영과 가장 유사한 조건입니다.
    • 데이터가 많을수록 성능 추정이 안정적입니다.

    Sliding Window (Rolling Window) Validation

    훈련 구간 크기를 고정한 상태로 앞으로 슬라이딩하며 갼습니다.

    Fold 1: [==Train==] [Test]
    Fold 2:   [==Train==] [Test]
    Fold 3:     [==Train==] [Test]
    • 최근 데이터만 통해 학습하는 모델(실시간 적응형 모델)에 적합합니다.
    • 계절성이 브거나 데이터 특성이 변하는 시계열에 유리합니다.

    파이썬 예시 (skforecast 라이브러리)

    pip install skforecast
    import pandas as pd
    import numpy as np
    from sklearn.linear_model import Ridge
    from skforecast.recursive import ForecasterRecursive
    from skforecast.model_selection import backtesting_forecaster
    
    series = pd.Series(
        np.random.randn(500).cumsum(),
        index=pd.date_range('2020-01-01', periods=500, freq='D'),
        name='y'
    )
    
    forecaster = ForecasterRecursive(
        regressor=Ridge(),
        lags=14,
    )
    
    # Walk-forward 백테스트
    metric, predictions = backtesting_forecaster(
        forecaster=forecaster,
        y=series,
        steps=7,                 # 한 번에 7스텍 예측
        metric='mean_absolute_error',
        initial_train_size=365,  # 초기 훈련 기간
        refit=True,              # True=Expanding, False=Sliding
    )
    print('MAE:', metric)

    7-2. 온라인 테스트 (Online Test)

    온라인 테스트는 실제 라이브 트래픽을 활용하여 모델 성능을 실제 서비스 환경에서 검증하는 방법입니다. 오프라인 테스트를 통과한 모델을 권역별·구간별로 더 세밀하게 검증할 수 있습니다.

    섹도우 모드 테스트 (Shadow Mode)

    새 모델을 레거시 모델과 동시에 실행하되, 서비스는 기존 모델 결과만 사용하고 새 모델 결과는 로깅 용도로만 활용합니다.

    [사용자 요청] → [라우터]
                        ├→ [기존 모델] → 실제 응답 (Live)
                        └→ [신규 모델] → 로그 저장만 (응답에 미반영)
    • 사용자 영향 0으로 실전 데이터 조건에서 새 모델을 테스트할 수 있습니다.
    • 지연시간(latency), 데이터 드리프트, 세그먼트별 성능 츨이를 실제 환경에서 확인할 수 있습니다.
    • 매우 보수적인 접근법으로, 시계열 예측의 1차 온라인 진입 단계로 적합합니다.

    A/B 테스트

    트래픽을 기존 모델(A군)와 신규 모델(B군)으로 일정 비율로 분할하여 성능을 직접 비교합니다.

    [사용자 요청]
        ├→ 90% → [모델 A (기존)]
        └→ 10% → [모델 B (신규)]
    • 두 모델이 실제 예측 결과를 서비스에 반영하므로, 사용자 영향이 있습니다.
    • 통계적 유의성을 확보하려면 충분한 샘플 수와 관찰 기간이 필요합니다.
    • MAE, MAPE 등 예측 지표와 함께 비즈니스 지표(예: 주문 누락률, 재고 과잊배율)도 함께 측정하는 것이 권장됩니다.

    카나리 배포 (Canary Release)

    신규 모델을 전체 트래픽의 일부(예: 1~5%)에만 먼저 배포하여 문제 발생 시 피해 범위를 최소화합니다.

    • A/B 테스트와 비슷하지만, 모델 안정성 확인에 초점을 된 접근법입니다.
    • 성능 이상 감지 시 자동 롤백 정책과 함께 사용하면 효과적입니다.

    7-3. 추가 검증 방법

    잔차 분석 (Residual Analysis)

    모델이 완전히 학습되었다면 잔차(= 실제값 − 예측값)는 화이트 노이즈에 가까워야 합니다. 잔차에 패턴이 남아있다면 모델이 시계열의 구조를 충분히 포착하지 못하고 있다는 신호입니다.

    확인 항목은 다음과 같습니다.

    • 잔차의 평균이 0에 가김 (Unbiasedness)
    • 잔차에 자기상관이 없음 (ACF 플롯으로 확인)
    • 잔차가 정규분포에 가까웈 지 (Q-Q 플롯, Shapiro-Wilk 검정)
    • 잔차의 분산이 일정 (Homoscedasticity)
    import matplotlib.pyplot as plt
    from statsmodels.graphics.tsaplots import plot_acf
    from scipy import stats
    
    residuals = y_test - predictions  # 실제값 - 예측값
    
    fig, axes = plt.subplots(1, 3, figsize=(15, 4))
    
    axes[0].plot(residuals)
    axes[0].axhline(0, color='red', linestyle='--')
    axes[0].set_title('잔차 시계열')
    
    plot_acf(residuals, lags=30, ax=axes[1])
    axes[1].set_title('잔차 ACF')
    
    stats.probplot(residuals, plot=axes[2])
    axes[2].set_title('Q-Q Plot')
    
    plt.tight_layout()
    plt.show()

    확률 예측 보정 검증 (Calibration Check)

    Prophet, Chronos, Moirai와 같이 예측 구간(Prediction Interval)을 제공하는 모델에는 보정(Calibration) 검증이 필요합니다. 90% 신뢰 구간을 제시하는 모델이라면 실제로 90%의 관측값이 해당 구간 내에 들어와야 합니다.

    def coverage_rate(y_true, lower, upper):
        """예측 구간 내에 실제 관측값이 포함되는 비율"""
        return ((y_true >= lower) & (y_true <= upper)).mean()
    
    # 예시: 90% 신뢰 구간
    coverage = coverage_rate(y_test, forecast_lower_90, forecast_upper_90)
    print(f'90% 신뢰 구간 실제 포함율: {coverage:.2%}')  # 목표: ~90%

    콘셉트 드리프트 모니터링 (Concept Drift Monitoring)

    시계열 데이터의 통계적 특성이 시간에 따라 변하는 현상을 콘셉트 드리프트(Concept Drift)라 합니다. 모델을 실제 서비스에 배포한 이후에도 지속적으로 예측 오차를 추적해야 합니다.

    드리프트가 발생하면 모델 재학습(Retraining) 또는 아키텍처 변경을 검토해야 합니다.

    import numpy as np
    
    def rolling_mae(y_true, y_pred, window=30):
        """롤링 윈도우 MAE로 드리프트 구간 감지"""
        errors = np.abs(np.array(y_true) - np.array(y_pred))
        return np.convolve(errors, np.ones(window)/window, mode='valid')
    
    rolling = rolling_mae(y_test, predictions, window=30)
    
    # 롤링 MAE가 기준치의 1.5배 이상이면 드리프트 의심
    threshold = rolling[:30].mean() * 1.5
    drift_points = np.where(rolling > threshold)[0]
    print(f'드리프트 감지 시점: {drift_points}')

    7-4. 검증 단계 요약

    단계 유형 방법 주요 질문
    1단계 오프라인 Hold-out 분할 예측 오차 기준치 충족하는가?
    2단계 오프라인 Walk-Forward / Sliding Window 다양한 구간에서도 안정적으로 성능을 냅는가?
    3단계 오프라인 잔차 분석 / 보정 검증 잔차에 미설명 패턴이 남아있지 않은가?
    4단계 온라인 섹도우 모드 실제 트래픽에서 지연시간 및 드리프트가 없는가?
    5단계 온라인 A/B 테스트 / 카나리 실제 비즈니스 지표가 기존 모델 대비 개선되는가?
    6단계 지속 콘셉트 드리프트 모니터링 시간이 지나도 모델이 유효한가?

    5. 정리

    시계열 데이터는 시간 순서로 정렬된 데이터로, 추세·계절성·주기성·잔차 네 가지 요소로 분해할 수 있습니다. 시계열 분석은 이 패턴을 통계적으로 탐색하고 예측하는 기법이며, 정상성 확보가 분석의 출발점입니다. 모델은 ARIMA 계열의 전통 통계 모델부터 Prophet, NeuralProphet, LSTM, iTransformer, TimeMixer 등 최신 딥러닝 모델까지 다양합니다. 특히 2024년 이후로는 Chronos(Amazon), TimesFM(Google), Moirai(Salesforce) 같은 시계열 파운데이션 모델이 등장하여 학습 데이터 없이도 제로샷 예측이 가능해졌습니다. 데이터의 양·복잡도·외부 변수 유무·학습 가능 여부에 따라 적합한 모델을 선택하는 것이 중요합니다.

    댓글