STL 분해 :: 시계열 분석 - mindscale
Skip to content

STL 분해

고전적 분해법에서 추세를 뽑아 낼 때 이동 평균 이라는 방법을 썼습니다. 이동 평균은 너무 단순하다 보니까 추세의 추정치가 깔끔하지 않다는 단점이 있습니다. 이동 평균을 대신해서 쓸 수 있는 방법 중에 여러 가지가 있지만 LOESS라는 방법이 있어요. Locally Estimated Scatterplot Smoothing의 약자입니다.

locally 라는 건 국소적 이런 건데 국소적, 부분적 이런 뜻입니다. 그리고 scatterplot은 산점도를 말해요. smoothing은 이제 통계 용어로는 평활이라고 하는데 쉽게 말하면 매끄럽게 만들었다는 뜻입니다. 즉, 산점도로 표현된 데이터의 부분 부분에서 매끄러운 선을 추정했다는 뜻입니다. 이 선들을 이어붙여 전체적으로 매끄러운 곡선을 만드는 것이 LOESS 방법입니다.

그리고 이 LOESS를 이용해서 계절성과 추세를 분해하는 방법이 Seasonal-Trend decomposition using LOESS, 줄여서 STL 분해입니다.

이 방법은 1990년도에 나왔습니다. 그러니까 고전적 분해법의 한 70년 정도 더 나중에 나온 방법이죠. 그래서 이 방법은 좀 복잡하기 때문에 우리가 손으로 하나하나 하는 대신에 STL이라는 함수를 이용해서 할 거예요

period에는 계절성의 주기를 넣어주면 되는데요, 우리가 계절성이 12달 간격으로 있을 것 같다고 가정해서 12라고 써주겠습니다. 분기 데이터라면 4라고 쓸 수 있겠죠.

m.plot()을 하면 순서대로 추세, 계절성, 나머지 성분의 그래프를 그려줍니다.

from statsmodels.tsa.seasonal import STL
m = STL(ym.demand, period=12).fit()
m.plot();

추세 성분만 뽑아보면

m.trend
0      77.535643
1      77.881249
2      78.230341
3      78.581940
4      78.934791
         ...    
190    91.270590
191    90.790901
192    90.300040
193    89.800158
194    89.293399
Name: trend, Length: 195, dtype: float64

계절성 성분만 뽑아보면

m.seasonal
0      0.496967
1     -2.303084
2      7.320967
3     -3.787410
4     -3.793225
         ...   
190    4.177987
191    8.691080
192   -3.405145
193   -5.219293
194    8.454723
Name: season, Length: 195, dtype: float64

나머지 성분만 뽑아보면

m.resid
0      1.317391
1      0.201835
2      0.768693
3     -2.194530
4     -0.281566
         ...   
190   -2.078577
191   -1.141981
192   -0.454894
193    0.459135
194    0.051878
Name: resid, Length: 195, dtype: float64

STL 모형의 인자

robust=True로 하면 이상적이나 극단치의 영향을 더 적게 받는 방식으로 추정합니다.

STL(ym.demand, period=12, robust=True).fit().plot();

추세의 매끄러움을 지정할 수 있습니다. trend 값은: 클 수록 추세가 매끄러워집니다. 이 값은 period보다 큰 홀수여야 합니다.

STL(ym.demand, period=12, trend=13).fit().trend.plot();

계절 성분의 매끄러움도 지정할 수 있습니다. seasonal이 클 수록 추세가 매끄러워집니다. 이 값은 3보다 큰 홀수여야 합니다.(기본값 7)

STL(ym.demand, period=12, seasonal=3).fit().seasonal.plot();

추세와 계절성의 강도

계절성을 조정한 데이터의 분산과 나머지 성분의 분산을 비교해서 추세의 강도를 계산합니다. 이 값은 0~1 범위의 값으로, 0에 가까울 수록 추세가 약하고, 1에 가까울 수록 추세가 강하다고 할 수 있습니다. 이 값을 도출하는 논리는 회귀분석에서 R제곱과 같습니다.

1 - m.resid.var() / (m.trend + m.resid).var()
0.9564002838163896

마찬가지로 추세를 제거한 데이터의 분산과 나머지 성분의 분산을 비교해서 계절성의 강도를 계산할 수 있습니다. 이 값은 0~1 범위의 값으로, 0에 가까울 수록 계절성이 약하고, 1에 가까울 수록 계절성이 강하다고 할 수 있습니다.

1 - m.resid.var() / (m.seasonal + m.resid).var()
0.9307784372113894