다운로드
작성자: admin 작성일시: 2016-05-07 11:19:39 조회수: 877 다운로드: 164
카테고리: 시계열 분석 태그목록:

시계열 간의 허위 상관관계

사실은 전혀 인과 관계가 없는 두 시계열이 수치상으로는 상관 관계를 가지는 것허위 상관관계(spurious correlation)이라고 한다.

ARMAX 모형과 같이 외부 시계열을 회귀 변수로 추가할 때는 원래의 시계열과 외부 시계열 사이에 허위 상관이 있는지 확인할 필요가 있다.

허위 상관관계가 생기는 일반적인 이유는 다음과 같은 것들이다.

  • 두 시계열이 강한 자기 상관관계 혹은 계절성을 가지는 경우
  • 두 시계열이 비정상 (결정론적 혹은 확률적) 추세를 가지는 경우

독립적인 두 시계열 $X$, $Y$의 자기상관관계 함수가 각각 $\rho_k(X)$, $\rho_k(Y)$이면 이 두 시계열의 샘플 상호상관관계 함수의 분산(variance)은 다음과 같다. 두 시계열이 독립적이므로 두 시계열의 샘플 상호상관관계 함수의 평균은 당연히 0 이다.

$$ \dfrac{1}{\sqrt{n}} \left( 1+2\sum_{k=1}^{\infty} \rho_k(X)\rho_k(Y) \right)$$

만약 두 시계열이 모두 AR(1) 모형을 따르고 AR(1) 계수가 각각 $\phi_X$, $\phi_Y$라면 샘플 상호상관관계 함수의 분산(variance)은 시차와 관계없이 다음과 같아진다.

$$ \dfrac{1+\phi_X \phi_Y}{n (1-\phi_X \phi_Y)} $$

이 식에서 볼 수 있듯이 만약 $\phi = \phi_X = \phi_Y$이 1에 가까워지면 즉, 각각의 시계열 내부의 자기상관관계가 강해지면 두 시계열이 독립적, 즉, 전혀 상관관계가 없음에도 불구하고 샘플 상호상관관계의 분산이 커져서 잘못된 판단을 내릴 가능성이 증가한다.

실제로 독립적인 두 개의 AR(1) 시계열을 시뮬레이션하여 상호상관관계를 계산하여 보면 다음과 같다.

In:
np.random.seed(0); N = 200
p1 = sm.tsa.ArmaProcess([1, -0.95],[1])
plt.stem(sm.tsa.ccf(p1.generate_sample(N), p1.generate_sample(N)), linefmt='g-', markerfmt='go', basefmt='w-');
p2 = sm.tsa.ArmaProcess([1, -0.9],[1])
plt.stem(sm.tsa.ccf(p2.generate_sample(N), p2.generate_sample(N)), linefmt='b-', markerfmt='bo', basefmt='w-');
p3 = sm.tsa.ArmaProcess([1, -0.6],[1])
plt.stem(sm.tsa.ccf(p3.generate_sample(N), p3.generate_sample(N)), linefmt='r-', markerfmt='ro', basefmt='w-');
p4 = sm.tsa.ArmaProcess([1, -0.1],[1])
plt.stem(sm.tsa.ccf(p4.generate_sample(N), p4.generate_sample(N)), linefmt='y-', markerfmt='yo', basefmt='w-');
plt.legend(["$\phi=0.95$","$\phi=0.9$","$\phi=0.6$","$\phi=0.1$"], loc=2);

실제 시계열의 경우를 살펴보자. 다음 시계열은 1994년부터 2005까지의 미국 우유 생산량과 전기 생산량을 보인 것이다.

In:
df1 = pd.read_csv("~/data/tsa/milk.dat")
df1.index = pd.date_range("01/1994", "12/2005", freq="MS") 
df2 = pd.read_csv("~/data/tsa/electricity.dat")
df2.index = pd.date_range("01/1973", "12/2005", freq="MS")
df = pd.concat([df1, df2], axis=1)["1994":"2005"]
plt.subplot(211); df.milk.plot(); plt.ylabel("milk");
plt.subplot(212); df.electricity.plot(); plt.ylabel("electrocity");

이 두 시계열의 상호상관관계를 구하면 다음과 같다. 이러한 강한 상호상관관계를 보이는 이유는 두 시계열 모두 시간이 지날수록 증가하는 추세를 가지고 있기 때문이다.

In:
plt.stem(sm.tsa.ccf(df.milk, df.electricity));

차분 연산을 통해 두 시계열의 추세를 없앤 다음에도 상호상관관계가 강하게 계산된다. 그 이유는 두 시계열 모두 강한 계절성 즉, 자기상관관계를 가지고 있기 때문이다.

In:
plt.stem(sm.tsa.ccf(df.milk.diff()[1:], df.electricity.diff()[1:]));

이 두 시계열을 ARMAX 모형으로 추정해 보면 다음과 같이 두 시계열의 상관계수 $\beta$가 유의한 값을 보인다.

In:
m = sm.tsa.ARMA(df.electricity.diff()[1:], (1, 0), df.milk.diff()[1:])
r = m.fit()
print(r.summary())
                              ARMA Model Results                              
==============================================================================
Dep. Variable:            electricity   No. Observations:                  143
Model:                     ARMA(1, 0)   Log Likelihood               -1636.815
Method:                       css-mle   S.D. of innovations          22619.345
Date:                Sat, 07 May 2016   AIC                           3281.630
Time:                        02:19:01   BIC                           3293.482
Sample:                    02-01-1994   HQIC                          3286.446
                         - 12-01-2005                                         
=====================================================================================
                        coef    std err          z      P>|z|      [0.025      0.975]
-------------------------------------------------------------------------------------
const                18.7380   3372.166      0.006      0.996   -6590.586    6628.062
milk                197.4054     20.356      9.697      0.000     157.508     237.303
ar.L1.electricity     0.4421      0.076      5.852      0.000       0.294       0.590
                                    Roots                                    
=============================================================================
                 Real           Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
AR.1            2.2619           +0.0000j            2.2619            0.0000
-----------------------------------------------------------------------------

이러한 모형이 문제가 되는 이유는 실제 존재하지 않는 관계를 마치 존재하는 것처럼 보인다는 점, 그리고 추정에 사용한 자료의 시점이 달라지면 전혀 다른 모수가 추정된다는 점이다.

In:
m = sm.tsa.ARMA(df.electricity.diff()[1:60], (1, 0), df.milk.diff()[1:60])
r = m.fit()
print(r.summary())
                              ARMA Model Results                              
==============================================================================
Dep. Variable:            electricity   No. Observations:                   59
Model:                     ARMA(1, 0)   Log Likelihood                -672.297
Method:                       css-mle   S.D. of innovations          21466.887
Date:                Sat, 07 May 2016   AIC                           1352.593
Time:                        02:19:01   BIC                           1360.903
Sample:                    02-01-1994   HQIC                          1355.837
                         - 12-01-1998                                         
=====================================================================================
                        coef    std err          z      P>|z|      [0.025      0.975]
-------------------------------------------------------------------------------------
const              -368.3207   4768.292     -0.077      0.939   -9714.002    8977.360
milk                183.8646     32.043      5.738      0.000     121.062     246.667
ar.L1.electricity     0.4209      0.119      3.546      0.001       0.188       0.654
                                    Roots                                    
=============================================================================
                 Real           Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
AR.1            2.3758           +0.0000j            2.3758            0.0000
-----------------------------------------------------------------------------
In:
m = sm.tsa.ARMA(df.electricity.diff()[-60:], (1, 0), df.milk.diff()[-60:])
r = m.fit()
print(r.summary())
                              ARMA Model Results                              
==============================================================================
Dep. Variable:            electricity   No. Observations:                   60
Model:                     ARMA(1, 0)   Log Likelihood                -687.845
Method:                       css-mle   S.D. of innovations          22996.434
Date:                Sat, 07 May 2016   AIC                           1383.690
Time:                        02:19:01   BIC                           1392.067
Sample:                    01-01-2001   HQIC                          1386.966
                         - 12-01-2005                                         
=====================================================================================
                        coef    std err          z      P>|z|      [0.025      0.975]
-------------------------------------------------------------------------------------
const                29.2541   5489.339      0.005      0.996   -1.07e+04    1.08e+04
milk                203.2976     29.798      6.822      0.000     144.894     261.701
ar.L1.electricity     0.4667      0.114      4.092      0.000       0.243       0.690
                                    Roots                                    
=============================================================================
                 Real           Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
AR.1            2.1426           +0.0000j            2.1426            0.0000
-----------------------------------------------------------------------------

질문/덧글

시계열 모양이 비슷한 것끼리 클러스터링하고 싶은데 chai*** 2018년 3월 31일 12:43 오전

시계열 모양이 비슷한 것끼리 클러스터링하고 싶은데 어떤 알고리즘을 쓸 수 있을까요?

구체적으로는
연중 비슷한 모양의 주가패턴을 갖는 주식 종목을 분류하고 싶은데 어떻게 접근하면 좋을까요?