카테고리 없음

시계열 모델링 1회차

iron-min 2025. 11. 18. 21:08

시계열 데이터

정의: 시계열은 데이터는 시간에 따라 정렬된 데이터

구성요소 : 모든 시계열 데이터는 시계열의 세 가지 구성요소인 계절성, 추세, 오차(주기성) 로 분해될 수 있다

 

 

 

1) 계절성

  • 일정한 경향에 따라 반복되는 패턴
  • 주로 연간 주기를 따르며, 특정 계절에 따라 데이터가 반복적인 변동을 보이는 경우
  • 계절성은 일반적으로 시간에 관련된 고정된 주기를 가지고 있으며, 특정 시점에서 데이터가 규칙적으로 상승하거나 하락하는 현상 ex. 여름철 에어컨 판매 증가, 연말 쇼핑 시즌에 매출 상승.

 

2) 추세

  • 추세는 시간이 지남에 따라 지속적이고 일관된 방향으로 변화하는 장기적 패턴
  • 패턴은 증가, 감소, 혹은 일정한 상태(데이터의 단기적 변동 즉, 노이즈 또는 계절성 구별) ex. 주가가 5년간 연평균 3% 상승한 경향, 또는 인구 증가에 따른 소비 증가

3) 주기성

  • 경제적, 사회적, 정치적 요인에 의해 발생하는 불규칙한 변동 패턴
  • 계절성과 다른점은 장기적이고 불규칙한 패턴이라는 점 ex. 경기 순환에 따른 경제 성장 및 침체 주기
  • 추세, 계절적 요인과 겹치는 부분이 많아 합쳐서 계절성에 넣기도함

4) 잔차

  • 잔차는 시계열 데이터에서 추세와 계절성을 제거한 후 남는 무작위적 변화량
  • 특정 패턴을 가지지 않으며 주로 백색소음(White Noise)처럼 랜덤한 요소입니다. ex. 추세와 계절성 요인을 제거한 후 남는 예측 불가능한 변화량

 

시계열 예측과 회귀예측의 비교

 

시계열 데이터 실습

1) 데이터 구성확인

df = pd.read_csv('/content/TimeSeriesForecastingInPython/data/jj.csv')
df.head()

 

 

2) 트레인 테스트 분리

 

- 간단한 시각화
 
 
 

 

- 훈련 데이터: 1960년부터 1979년까지 분기
- 테스트 데이터: 1980년도 4개의 분기

train = df[:-4]
test = df[-4:]

 

① 단순평균으로 예측(RMSE)

historical_mean = np.mean(train['data'])
test.loc[:, 'pred_mean'] = historical_mean
test['error'] = test['data'] - test['pred_mean']
test

 

 

※ 시계열 분석에는 RMSE 대신 MAPE라는 지표를씀

 

 

def mape(y_true, y_pred):
    return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
    
mape_hist_mean = mape(test['data'], test['pred_mean'])
mape_hist_mean
# 출력결과
np.float64(70.00752579965119)

 

- 간단한 시각화

fig, ax = plt.subplots()

ax.plot(train['date'], train['data'], 'g-.', label='Train')
ax.plot(test['date'], test['data'], 'b-', label='Test')
ax.plot(test['date'], test['pred_mean'], 'r--', label='Predicted')
ax.set_xlabel('Date')
ax.set_ylabel('Earnings per share (USD)')
ax.axvspan(80, 83, color='#808080', alpha=0.2)
ax.legend(loc=2)

#2년간격으로 8씩 증가하는 배열을 생성하여 x축을 정리
plt.xticks(np.arange(0, 85, 8), [1960, 1962, 1964, 1966, 1968, 1970, 1972, 1974, 1976, 1978, 1980])

#x축 눈금 자동서식
fig.autofmt_xdate()
#여백 제거
plt.tight_layout()

 

빨간색이 예측값이지만 정확하게 예측하지 못한 모습입니다.

 

 

② 직전데이터로 예측

last_year_mean = np.mean(train['data'][-4:])
test.loc[:, 'pred__last_yr_mean'] = last_year_mean

test

 

mape_last_year_mean = mape(test['data'], test['pred__last_yr_mean'])
mape_last_year_mean

- 간단한 시각화

이전보다 나아졌지만 그래도 정확한 예측이 되지 않았습니다.

 

③ 마지막 측정된 데이터로 이용하기

last = train['data'].iloc[-1]
mape_last = mape(test['data'], test['pred_last'])
mape_last

 

오히려 예측성이 더 떨어졌습니다.

 

 

 마지막으로 측정된 계절성으로 예측(Naive seasonal forecast)

#1979년 마지막 5분기의 데이터
test.loc[:, 'pred_last_season'] = train['data'][-4:].values

test

 

 

mape_naive_seasonal = mape(test['data'], test['pred_last_season'])
mape_naive_seasonal

 

간단한 시각화)

fig, ax = plt.subplots()

ax.plot(train['date'], train['data'], 'g-.', label='Train')
ax.plot(test['date'], test['data'], 'b-', label='Test')
ax.plot(test['date'], test['pred_last_season'], 'r--', label='Predicted')
ax.set_xlabel('Date')
ax.set_ylabel('Earnings per share (USD)')
ax.axvspan(80, 83, color='#808080', alpha=0.2)
ax.legend(loc=2)

plt.xticks(np.arange(0, 85, 8), [1960, 1962, 1964, 1966, 1968, 1970, 1972, 1974, 1976, 1978, 1980])

fig.autofmt_xdate()
plt.tight_layout()

# plt.savefig('figures/CH02_F09_peixeiro.png', dpi=300)

 

 

4개의 지표 MAPE 비교

fig, ax = plt.subplots()

x = ['hist_mean', 'last_year_mean', 'last', 'naive_seasonal']
y = [70.00, 15.60, 30.46, 11.56]

ax.bar(x, y, width=0.4)
ax.set_xlabel('Baselines')
ax.set_ylabel('MAPE (%)')
ax.set_ylim(0, 75)

for index, value in enumerate(y):
    plt.text(x=index, y=value + 1, s=str(value), ha='center')

plt.tight_layout()

 

요약

  • 모델은 가장 간단한모델부터 하나씩 변수를 바꿔가며 테스트하면 해석력이 좋아진다.
  • 베이스라인 모델은 평균을 이용한는 것이 대표적이다.
  • MAPE는 예측값이 실제값과 얼마나 차이나는지 직관적으로 측정하는 지표이다.