1. 시계열(Time Series)의 정의
- 시간의 흐름에 따라 순차적으로 수집된 데이터
- 시간 순서가 중요하며, 관측 간격이 일정한 경우가 대부분 (예: 일간, 월간, 분 단위 등)
- 관측값들 사이에 시간적 의존성이 존재함
예시
2. 시계열 데이터와 일반 데이터의 차이점
3. 시계열의 주요 통계적 특성
이 특성들은 시계열 분석에서 모델 선택, 전처리, 예측 기법에 직접적인 영향을 미칩니다.
3.1 정상성 (Stationarity)
- 정의: 시계열의 통계적 성질(평균, 분산, 공분산 등)이 시간에 따라 변하지 않는 것
- 필수 개념: 대부분의 시계열 모델(AR, ARIMA 등)은 정상성을 전제로 함
수학적 조건
- 평균이 일정하다: \(\mathbb{E}[Y_t] = \mu\) (모든 t에 대해 동일)
- 분산이 일정하다: \(Var(Y_t) = \sigma^2\)
- 공분산이 시간 간격(lag)에만 의존: \(Cov(Y_t, Y_{t-k}) = \gamma(k)\)
예시
- 백색잡음 (White Noise): 정상
- 주가의 수익률 (log return): 대체로 정상
- 추세/계절성이 있는 시계열: 비정상
왜 중요한가?
- 비정상 시계열은 예측이 어려우며, 차분(differencing) 등의 기법으로 정상화 필요
3.2 추세성 (Trend)
- 정의: 시간의 흐름에 따라 시계열 값이 지속적으로 증가하거나 감소하는 경향
- 형태:
- 선형 추세 (linear)
- 비선형 추세 (exponential, polynomial)
예시
- 인플레이션에 따른 물가 상승
- 꾸준히 증가하는 웹사이트 방문자 수
3.3 계절성 (Seasonality)
- 정의: 고정된 주기로 반복되는 패턴
- 조건: 주기가 명확하고 반복성이 있어야 함 (예: 12개월, 7일 등)
예시
- 여름철 에어컨 판매 증가
- 12월 소비 지출 증가
파악 방법
- 시계열 그래프
- ACF(자기상관) 분석
- Fourier 변환 등
3.4 주기성 (Cycle)
- 정의: 계절성과 유사하지만, 주기가 불규칙하고 길며, 반복 주기가 고정되어 있지 않음
- 원인: 경제, 정책, 사회 요인 등
예시
- 경기 침체와 회복
- 장기적 수요 변화
3.5 자기상관성 (Autocorrelatiohn)
- 정의: 과거의 값이 현재의 값에 영향을 주는 성질
- 지연(Lag) 간의 상관관계를 측정
활용
- AR (자기회귀) 모델
- ACF, PACF 분석
4. 시계열 분해란?
- 시계열을 추세 + 계절성 + 잔차로 수학적으로 분리하는 과정
- 목적:
- 패턴 파악
- 모델링 전 구조 이해
- 계절성 제거 후 예측 성능 개선
- 구성 요소
- Trend (추세)
- 장기적인 증가/감소 경향
- Seasonality (계절성)
- 고정된 주기로 반복되는 패턴
- Residual (잔차)
- 추세/계절성으로 설명되지 않는 불규칙한 요소
- Trend (추세)
5. 시계열 데이터를 분해하는 이유
1) 시계열의 구조를 이해하기 위해
시계열 데이터는 단순히 시간에 따른 순자들의 나열이 아니라, 그 안에 패턴과 구조가 숨어 있습니다.
- 추세 (Trend) : 전체적으로 상승 중인지, 하락 중인지 확인.
- 계절성 (Seasonality) : 일정한 주기로 반복되는 패턴이 있는지 확인.
- 잔차 (Residual) : 예측하기 어려운 불규칙한 변화가 얼마나 되는지 확인.
=> 주가가 오르고 있는 것처럼 보여도, 계절성 때문인지 실제 추세인지 분해해봐야 알 수 있습니다.
2) 각 성분을 따로 분석하거나 제거해서 더 정확한 모델을 만들기 위해
시계열 모델은 불필요한 성분(노이즈)을 제거하고 본질적인 패턴만 학습할수록 예측력이 좋아집니다.
- 계절성이 강하면 -> SARIMA, Prophet 등 계절성 포함 모델 사용
- 계절성이 약하고 노이즈가 크면 -> smoothing, ARIMA 등 사용
- 잔차가 너무 크면 -> 이상 탐지, 외부 변수 고려 필요
즉, 분해는 예측 이전에 "어떤 모델을 선택하고, 어떻게 사전처리를 해야 하는가"에 대한 방향을 제공합니다.
3) 계절성 제거(deseasonalizing)나 추세 제거(detrending)에 사용
시계열 데이터 분해를 통해 계절성 또는 추세를 제거하고, 변동성만 남긴 시계열로 예측 모델을 만들 수 있습니다.
# Additive 모델
deseasonalized = observed - seasonal
# Multiplicative 모델
deseasonalized = observed / seasonal
이렇게 하면, 불필요하게 예측이 어려운 계절 요인을 제거하고 순수한 추세나 변동만 학습시킬 수 있습니다.
4) 이상치 탐지 및 해석 용이
시계열 데이터를 분해하면 잔차(Residual)를 별도로 볼 수 있으므로 이상 거래, 외부 이벤트, 정책 변화 등이 반영된 순간을 쉽게 식별할 수 있습니다.
5) 비정상 시계열을 부분적으로 처리할 수 있음
ARIMA 같은 모델은 정상성을 전제로 하기 때문에 분해를 통해 비정상성을 가진 추세/계절성을 제거하고 나머지(잔차 또는 정상성 있는 데이터)만 모델링에 사용할 수 있습니다.
6. 분해 모델의 종류
1) Additive Model (가법 모델)
수식
$$Y(t) = T(t) + S(t) + R(t)$$
의미
- 전체 시계열 값은 추세 + 계절성 + 잔차의 단순한 합으로 구성된다고 가정함
- 각 성분의 영향은 서로 독립적이고 일정함
특징
- 계절성의 진폭(진동 폭)이 시간이 지나도 일정함
- 데이터이 전체 값이 커져도 계절 효과는 그대로
사용 예시
- 월별 기온 변화: 여름에는 +10도, 겨울에는 -10도 -> 항상 일정한 편차
- 고정 금액으로 매년 증가하는 예산 등
2) Multiplicative Model (승법 모델)
수식
$$Y(t) = T(t) \times S(t) \times R(t)$$
의미
- 전체 시계열 값은 추세 x 계절성 x 잔차의 곱으로 구성된다고 가정함
- 계절성과 잔차의 영향이 비율적으로 커짐
특징
- 계절성의 진폭이 시간에 따라 달라짐
- 추세가 커질수록 계절성의 진폭도 같이 커짐
사용 예시
- 매출 데이터: 매년 매출 규모가 커지면서 계절성 변동 폭도 커짐
3) 실제 적용 기준
- 계절성 진폭이 일정하다 -> Additive 사용
- 계절성 진폭이 시간이 갈수록 커진다 -> Multiplicative 사용
- 데이터에 음수나 0이 포함된다 -> Additive만 사용
- 주가/매출처럼 비율적 변화가 중요 -> Multiplicative 권장
7. 시계열 분해 실습
시계열 분해 실습을 위한 데이터셋으로는 삼성전자 주식 데이터를 사용하겠습니다. 학습에 사용할 데이터는 Yahoo Finance API를 이용해 가져오겠습니다.
코드 분할 설명
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose
- yfinance는 Yahoo Finance에서 주가 데이터를 불러오는 라이브러리입니다. 종목 코드만 알고 있다면 편리하게 데이터를 불러올 수 있습니다.
- seasonal_decompose는 시계열 분해 함수로 trend, seasonality, residual을 계산해줍니다.
# 삼성전자(005930.KS) 주식 데이터 다운로드
samsung = yf.download('005930.KS', start='2018-01-01', end='2024-12-31')
- Yahoo Finance 라이브러리에서 제공하는 download 함수는 주식 데이터 다운로드를 위한 인자로 종목 코드, 데이터를 불러올 시작 날짜, 데이터를 불러올 종료 날짜 3가지를 입력 받습니다.
- 저는 삼성전자의 종목 코드인 '005930.KS' 를 이용해 2018년 1월 1일부터 2024년 12월 31일까지의 주식 데이터를 가져오겠습니다.
- 가져온 데이터는 DataFrame 형식으로 저장되며, 날짜를 인덱스로 하고 주가 관련 열(Open, High, Low, Close, Volume 등)을 가집니다.
- 이번 시계열 분해 실습에서는 주식의 종가인 Close 열의 데이터만 사용하겠습니다.
# 월별 평균 종가로 리샘플링 (계절성 분해는 일정 간격 필요)
monthly_close = samsung['Close'].resample('M').mean()
monthly_close = monthly_close.dropna()
- 계절성 분해를 위해서는 일정 간격이 필요하므로 월 단위로 리샘플링을 수행합니다.
- 거래일이 없는 경우에는 결측치가 생길 수 있어, 결측치가 생긴 행을 제거합니다.
- 월 단위로 리샘플링을 수행한 결과 이전보다 그래프의 자잘한 변동이 줄어든 것을 확인할 수 있습니다.
# 분해 수행 (12개월 주기 기준)
result = seasonal_decompose(monthly_close, model='multiplicative', period=12)
- 시계열 데이터를 추세, 계절성, 잔차로 분해를 수행하는 코드입니다.
- 사용할 수 있는 분해 방식에는 additive와 multiplicative가 있으며, 주가처럼 변화폭이 커지는 경우에는 multiplicative 방식이 더 적합하므로, 해당 실습에서는 multiplicative 방식을 사용하겠습니다.
- period는 주기의 계절성을 가정하는 인자로 1년(12개월)로 설정하였습니다.
# 추세(Trend), 계절성(Seasonality), 잔차(Residual) 각각 시각화
fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True)
# 추세
axes[0].plot(result.trend, label='Trend', color='blue')
axes[0].set_title('Trend')
axes[0].legend()
# 계절성
axes[1].plot(result.seasonal, label='Seasonality', color='green')
axes[1].set_title('Seasonality')
axes[1].legend()
# 잔차
axes[2].plot(result.resid, label='Residual', color='red')
axes[2].set_title('Residual')
axes[2].legend()
- 시계열의 성분별로 시각화를 수행하는 코드입니다.
- 추세, 계절성, 잔차를 각각 시각화 하였습니다.
- 시각화 결과는 아래와 같습니다:
여기서 잔차는 시계열 데이터에서 추세(Trend), 계절성(Seasonality)을 제거하고 남은 데이터를 의미합니다.
전체 코드
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose
# 삼성전자(005930.KS) 주식 데이터 다운로드
samsung = yf.download('005930.KS', start='2018-01-01', end='2024-12-31')
# 월별 평균 종가로 리샘플링 (계절성 분해는 일정 간격 필요)
monthly_close = samsung['Close'].resample('M').mean()
monthly_close = monthly_close.dropna()
# 분해 수행 (12개월 주기 기준)
result = seasonal_decompose(monthly_close, model='multiplicative', period=12)
# 추세(Trend), 계절성(Seasonality), 잔차(Residual) 각각 시각화
fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True)
# 추세
axes[0].plot(result.trend, label='Trend', color='blue')
axes[0].set_title('Trend')
axes[0].legend()
# 계절성
axes[1].plot(result.seasonal, label='Seasonality', color='green')
axes[1].set_title('Seasonality')
axes[1].legend()
# 잔차
axes[2].plot(result.resid, label='Residual', color='red')
axes[2].set_title('Residual')
axes[2].legend()