그래인저 인과관계 - Granger Causality

닭이 먼저인가 달걀이 먼저인가?

닭이 먼저인가 달걀이 먼저인가?와 같은 인과관계를 파악하는 것은 매우 어려운 일이다. 흥미로운 문제이기도 하지만 이런 문제는 사실 확인하는 것이 매우 어렵다.

그래인저 인과관계 (Granger causality)는 일반적으로 사람들이 생각하는 원인을 바로 찾아주고 관련이 있는지를 알려주는 인과관계를 말하는 것은 아니다. 사람들이 생각하는 인과는 매우 추상적이고 포괄적이기 때문에 사실 이런 것을 과학적인 방법으로 알아내는 것은 매우 어렵다. 하지만 그렇다고 해서 포기할 수는 없고 이런 사람들이 알고자 하는 그런 인과관계가 있는지 확인하는 것을 시도할 수 있는 단순하고 잘 알려진 방법 중에 가장 많이 쓰이는 것이 그래인저 인과관계이다.

개요

핵심

두 개의 시계열 데이터에서 한 변수(한 시계열)의 과거데이터와 다른 한 변수(시계열)의 과거데이터의 결합으로 그 변수(처음 시계열)를 선형 예측(linear regression)을 했을 때 다른 한 변수의 과거데이터로만 선형예측 한 것이 통계적으로 유의미하고 예측에 도움을 줬다면 그것을 그래인저 인과(Granger Causality)가 있다고 말한다.

오해석에 대한 유의

이름이 그래인저 인과관계(Granger Causality)라고 되어 있는데 실제 사람들이 흔히 생각하는 인과(causality)와는 다르게 생각해야 하므로 이 검정의 결과를 가지고 확대해석 또는 오해석(착각)하는 것은 매우 경계해야 한다.

달걀의 개체수의 증가가 미래의 닭의 개체수의 증가에 인과영향이 있다는 사실이 밝혀졌다고 해서 반드시 닭의 수의 요인은 달걀의 개체수다라고 확신해서 말하는 것은 무리가 있다. 단순히 달걀의 생산량을 증가시키면 닭의 수가 늘어나게 된다고 확대해석을 하기 때문이다.그래서 그래인저 인과관계는 줄여서 인과관계라고 하지 않고 확실하게 “그레인저 인과관계”라고 명시하는 경우가 많다.
그것은 그래인저 인과관계가 일반적인 인과관계를 말하는 것이 아니며 사람들이 생각하는 추상적인 인과관계를 명확하게 밝혀내서 확실하게 알려줄 것이라는 기대감을 주지 않기 위함이다.

그래인저 인과관계는 상관관계(correlation)처럼 결과를 해석할 때 논리적으로 결함이 없는지 여러번 고찰하고 해석할 때 매우 주의해야 한다. 특히 경제문제가 아닌 자연과학이나 사회과학 문제에 적용할 때는 더더욱 주의해야 한다.

전제 조건

입력 파라미터 - Input parameter

그래인저 인과관계를 확인하기 위해서는 두 개의 시계열 변수, 즉 시계열 데이터 두 세트가 필요하고 시차(lag 또는 지연)를 파라미터로 넣어 주어야 한다.

시차는 2개의 시계열 데이터 세트 A와 B에 대해서 테스트 할 때 A가 B의 몇번째 뒤의 시점까지 영향을 주는 또는 그 반대로 B가 A의 몇번째 뒤의 시점까지 영향을 주는가를 확인하기 위한 것이다.

이 시차값은 사람에 의해 주어져야 하며 적당한 값을가 찾기는 매우 어려우므로 여러 시차를 반복을 통해서 실험해 보거나 경험적인 판단에 의존하여 적절한 구간을 실행해 보고 논리적으로 적당한 값을 찾아서 사용해야 한다.

또 이 검정법은 입력한 시차에 해당하는 것만 사용해서 선형회귀를 수행하는 것이 아니고 시차(lags)가 N으로 주어진다면 1부터 N까지의 지연에 해당하는 모든 데이터를 전부 사용한다는 것을 주의해야 한다. 즉 N시차만 영향을 주는지 확인하는 것이 아니라 N시차까지 영향력이 있는가를 보는 것이다.

전제조건 - 정상성(Stationary)

그래인저 인과관계에서 테스트하려는 두 개의 변수(두 개의 시계열 데이터)는 모두 정상성(stationary)을 만족하는 것을 전제로 하고 있다. 정상성을 만족하지 않은 상태에서 데이터를 입력하면 오해석할 여지가 많은 결과가 나온다는 점을 매우 주의한다. 대부분의 시계열 데이터가 정상성을 바로 만족하지 않기 때문에 정상성을 만족하도록 변형을 시도하게 되는데 그래인저 인과관계도 동일하다. 정상성 만족 여부는 대부분의 시계열 분석에서 전제되는 조건중 하나이다. 정상성을 만족하지 않으면 후속 작업을 진행할 수 없으며 그래인저 인과관계도 이런 이유로 여러 유형의 데이터와 문제의 상황을 통틀어서 그 전반을 일반화해서 자동하화기 어렵다.

결론적으로 한 번에 모든 문제에 대해서 적용이 가능한 일반적인 플로우를 만드는 것은 되지 않는다.

전제조건 - 테스트 방향 (Direction)

테스트하려는 두 개의 변수 변수A와 변수B가 있을 때 양방향으로 총 2회의 검정을 세트로 수행하는 것이 일반적이며 두 번의 결과에 따라 해석(interpreting)이 달라지는 어려움이 있다.

  • A → B. A가 B에 인과영향인지 테스트
  • B → A. B가 A에 인과영향인지 테스트

즉, 그래인저 인과 테스트를 양방향으로 두 번 하는 것이다. 논리적으로 확실하게 한쪽 방향이 성립하지 않다고 확신한다면 한 쪽은 하지 않아도 된다. 하지만 보통의 대부분의 문제는 그렇지 않은 경우가 많다.

두 번의 테스트를 통해서 A가 B에 인과 영향을 주는지 테스트하고 B가 A에 인과 영향을 주는지 테스트하게 된다. 이 결과의 조합을 통해서 4가지 경우의 결과가 나온다.

  1. A가 B에 인과영향을 준다. B는 A에 인과영향을 주지 않는다.
  2. B가 A에 인과영향을 준다. A는 B에 인과영향을 주지 않는다.
  3. A가 B에 인과영향을 준다. 그리고 B도 A에 인과영향을 준다.
  4. A가 B에 인과영향을 주지 않는다. 그리고 B도 A에 인과영향을 주지 않는다.

이것을 다시 논리적으로 해석해야 한다. 위에서 해석이 곤란한 것은 4번째이다. 이 해석이 곤란한 이유는 뒤에 기술할 것이다.

설명

시계열 변수 A, 시계열 변수 B가 있으며 이 두 변수는 충분한 양(대략 30여개 이상의 선형회귀가 작동 가능한 데이터)의 요소들을 가지고 있는 연속형 변수이다. 즉 시간에 따라 순서를 가진 2개의 집계 데이터 또는 관측 데이터가 있고 이들이 가진 시간축은 서로 일치하는 같은 것이다. 이 두 변수를 시계열 또는 변수라고 하고 여기서는 편의상 변수라고 부르기로 하겠다.

  • A의 과거 데이터의 집합 즉, A의 시차(lags)
  • B의 과거 데이터의 집합 즉, B의 시차(lags)

위와 같은 데이터가 있을 때 다음과 같이 결과에 대한 조건이 통계적으로 유의미하면 A가 B에 대해 Granger Causality하다고 표현하며, 이는 인과관계가 있을 여지가 있다고 볼 수 있다. 하지만 명확하게 인과관계가 있다는 의미가 아니므로 매우 주의한다.

A lags + B lags로 B의 데이터를 선형회귀한 것의 예측력 > B lags로만 B의 데이터를 선형회귀한 것의 예측력

즉 위의 것을 체크하는 것이다. 풀어서 설명하면 다음과 같다.

  1. A 데이터의 미래 데이터를 선형회귀로 예측을 해보는데 A의 미래를 A의 과거 데이터들로만 예측해 본다
  2. A의 과거데이터들에 A를 기준으로 B의 과거데이터를 같이 합쳐서 A의 미래를 예측해 본다
  3. 2가 1보다 통계적으로 유의미하게 예측값에 긍정적인 영향을 주었는가를 검정한다

두 상황에서 2번이 1번 보다 더 낫다는 것이 확인되면 그래인저 인과가 있다고 말할 수 있고 통계값은 그것을 기준으로 나오게 된다.

일반적인 통계툴에서 지원하는 그레인저 인과관계는 위의 과정을 진행해 주는 것이다.

실제 사용 방법

  1. 변수A → 변수B의 방향을 두고 테스트로 결정한 lags(시차)를 입력하고 그래인저 인과관계 검정(Granger Causality test)를 수행한다. 이 때 시차는 테스트를 하는 사람이 결정해서 넣어주어야 하는데 결정해야 한다. 만약 적절한 Lags를 찾기 아렵다면 알려진 몇가지 방법을 활용한다.
  2. 유의 수준을 0.05(5%)로 설정하였고 테스트를 통해서 검정값(p-value)가 0.05이하로 나오면 귀무가설을 기각할 수 있다. 귀무가설은 “Granger Causality를 따르지 않는다” 이다.
  3. 변수B → 변수A의 방향으로 위와 동일한 방법으로 그레인저 인과관계 검정을 한 번 더 수행한다.
  4. 시차(lags) 바꾸어가며 반복해서 테스트한다. 이때 lags는 경험적으로 잘 알려진 것을 사용하거나 논리적으로 적당한 수준까지 입력한다.

적정한 lags는 어떻게 구하는가?

적정한 lags를 찾아내는 좋은 방법은 별로 없다. 재귀적이 되겠지만 그래인저 인과관계가 적정한 시차를 찾아내는 방법이다. 주어진 데이터와 데이터에서 얻어지는 배경지식으로 얼마까지 하는 것이 유의미한지 경험적으로 알려진 것이 있으나 명확하게 정돈된 가이드는 없다. 경험을 통해서 체득하거나 유사한 사례를 참고하는 것이 좋다.

결과 해석

앞서 언급헜지만 위의 사용과정을 거쳐서 시차(lag)가 정해진 경우에는 경우의 수를 보면 총 4개의 결과가 나올 수 있다.

변수A → 변수B = Granger Causality 성립, 변수B → 변수A = Granger Causality 성립하지 않음

이 경우는 변수A가 변수B에 선행한다고 볼 수 있다. 즉 변수A가 변수A의 인과요인이 될 가능성이 높다.

변수A → 변수B = Granger Causality 성립하지 않음, 변수B → 변수A = Granger Causality 성립

이 경우는 변수B가 변수A에 선행한다고 볼 수 있다. 즉 변수B가 변수A의 인과요인이 될 가능성이 높다.

변수A → 변수B = Granger Causality 성립, 변수B → 변수A = Granger Causality 성립

쌍방으로 Granger Causality가 성립하는 경우로 이 경우는 제3의 외부변수(Exogenous Variable)가 영향을 공통으로 주었을 가능성이 높다. 이 경우 제3의 외부변수를 알아내던가 포기하던가 해야 한다.
VAR모형(사실 Granger Causality도 VAR모형중 하나이다)을 사용해야 할 수 있다.

변수A → 변수B = Granger Causality 성립하지 않음, 변수B → 변수A = Granger Causality 성립하지 않음

두 변수가 서로 인과영향을 주지 않는다고 볼 수도 있지만 단언하지는 못한다. ARIMA모형으로 추가 확인이 가능한 것으로 알려져 있다.
주의 할 점은 위의 결과가 입력값으로 주는 시차에 따라서 달라질 수 있으므로 시차에 따른 해석을 달리해야 하는 문제가 있다.
즉 해석에 있어서 사람의 경험과 판단이 개입되어야 한다.

관련 기법

다음과 같은 시계열 관련이 알고리즘은 그래인저 인과와 관련이 있다. 그래인저 인관관계는 경제문제에 많이 사용되고 대부분의 시계열 문제는 경제 문제에 많이 활용되므로 그런 의미에서 관련이 있다고 보면 좋을 것이다.

VAR, ARIMA, …

활용 예시

다음과 같은 연구결과나 예시가 잘 알려져 있다.

  • 닭과 달걀의 생산량의 인과관계
  • 단기금리와 중기, 단기 금리와의 인과관계
  • 강수량과 동물원방문객수의 인과관계
  • 급여인상액과 소비금액의 인과관계
  • 어떤 회사의 광고비지출액와 매출액의 인과관계
  • 강수량과 인터넷사용량의 인과관계
  • 어떤 광고캠페인의 수치형 설정조건과 클릭수와 인과관계

참조 코드

R 예제 - 닭과 달걀의 인과관계

R에는 Granger causality를 지원하는 패키지가 2개 이상 있다.

  • lmtest
  • MSBVAR

위 두개에서 지원하는 패키지내의 함수들은 사용법이 다소 다른데 lmtest에 있는 grangertest함수를 사용하는 것이 더 잘 알려져 있다. 우선 두 패키지를 모두 설치한다.

패키지 설치

install.packaegs("lmtest")
install.packages("MSBVAR")

ChickEgg 데이터 확인

lmtest 패키지의 내부에 ChickEgg 라는 이름의 데이터가 내장되어 제공된다.
다음과 같이 패키지에서 ChickEgg 데이터를 불러온다.

library(lmtest)
data(package="lmtest")
data(ChickEgg)
ChickEgg

ChickEgg 데이터는 chicken, egg 두 개의 시계열을 가지고 있고 1930년부터 1983년까지 각각 닭과 달걀의 생산량이다.

이 데이터와 관련된 논문을 살펴보면 chicken은 식용 고기로 사용하기 위한 용도도 길러진 것들은 모두 제외했다고 되어 있으며 egg는 유정란(병아리가 되는 것이 가능한)만을 집계했다고 되어 있다. 여기의 닭은 병아리를 만들기 위한 닭들이라는 의미이다. 즉 식용 닭의 소비에는 영향을 거의 받지 않을 것이므로 다른 외생 변수를 크게 고민하지 않아도 된다.

위의 코드의 결과는 다음과 같이 보여질 것이다.

Time Series:
Start = 1930
End = 1983
Frequency = 1
     chicken  egg
1930  468491 3581
1931  449743 3532
1932  436815 3327
1933  444523 3255
1934  433937 3156
1935  389958 3081
1936  403446 3166
1937  423921 3443
1938  389624 3424
1939  418591 3561
1940  438288 3640
1941  422841 3840
1942  476935 4456
1943  542047 5000
1944  582197 5366
1945  516497 5154
1946  523227 5130
1947  467217 5077
1948  499644 5032
1949  430876 5148
1950  456549 5404
1951  430988 5322
1952  426555 5323
1953  398156 5307
1954  396776 5402
1955  390708 5407
1956  383690 5500
1957  391363 5442
1958  374281 5442
1959  387002 5542
1960  369484 5339
1961  366082 5358
1962  377392 5403
1963  375575 5345
1964  382262 5435
1965  394118 5474
1966  393019 5540
1967  428746 5836
1968  425158 5777
1969  422096 5629
1970  433280 5704
1971  421763 5806
1972  404191 5742
1973  408769 5502
1974  394101 5461
1975  379754 5382
1976  378361 5377
1977  386518 5408
1978  396933 5608
1979  400585 5777
1980  392110 5825
1981  384838 5625
1982  378609 5800
1983  364584 5656

이제 위의 시계열을 한 번 플롯으로 살펴본다.

chickegg_df <- as.data.frame(ChickEgg)
par(mfrow=c(2, 1))
plot.ts(chickegg_df$chick

위의 시각화 결과는 다음과 같다.

우선 위 시계열은 서로 상관성이 없어보이고 정상 시계열이 아닌 것을 눈으로 확인할 수 있다. Granger causaility는 시계열의 정상성을 요구하므로 정상시계열로 변환해야 한다. 간단하게 바꾸기 위해 forecast 패키지를 사용한다.

install.packages("forecast")
require(forecast)

유의 수준 0.05 (alpha)를 기준으로 KPSS 테스트를 수행해서 정상성을 만족시키기 위한 시차를 알아낼 수 있다.

ndiffs(chickegg_df$chicken, alpha=0.05, test=c("kpss"))

결과는 1이다.

ndiffs(chickegg_df$chicken, alpha=0.05, test=c("kpss"))

결과는 1이다. 즉, chicken, egg 모두 차분을 1로 두면 간단하게 정상시계열로 변환이 가능하다.

diff1_chicken <- diff(chickegg_df$chicken, 1)
diff1_egg <- diff(chickegg_df$egg, 1)
plot.ts(diff1_chicken)
plot.ts(diff1_egg)

육안으로 볼 때는 정상시계열인 것으로 보인다. 이제 Granger causality를 수행한다. Granger causaility 테스트를 할 때는 lag값을 넣어주어야 하는데 실험을 통해서 알아내야 한다. 위의 데이터에서는 3, 4 또는 적당한 것으로 이미 알려져 있다. 적절한 lag를 알아내는 다른 방법은 여기서는 생략한다. 이제 달걀이 닭에 영향을 주는지 lag값 4를 주어 검정을 실행한다.

grangertest(d1_chicken ~ d1_egg, order=4)

다음과 같이 결과가 나올 것이다.

Granger causality test
Model 1: d1_chicken ~ Lags(d1_chicken, 1:4) + Lags(d1_egg, 1:4)
Model 2: d1_chicken ~ Lags(d1_chicken, 1:4)
  Res.Df Df      F   Pr(>F)  
1     40                     
2     44 -4 4.1762 0.006414 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

p-value가 0.006414이므로 egg가 chicken의 Granger causality가 없을 것이라고는 귀무가설을 기각할 수 있고, 대립 가설인 egg는 chicken에 Granger causality가 있다를 유력하게 채택할 수 있다. 즉, egg는 chicken에 그래인저 방식으로 볼 때는 인과관계가 성립한다. 이제 반대 방향으로 살펴본다.

즉 chicken이 egg의 인과요인인지 Granger causality로 확인해 보겠다.

grangertest(d1_egg ~ d1_chicken, order=4)

결과는 다음과 같다.

Granger causality test
Model 1: d1_egg ~ Lags(d1_egg, 1:4) + Lags(d1_chicken, 1:4)
Model 2: d1_egg ~ Lags(d1_egg, 1:4)
  Res.Df Df      F Pr(>F)
1     40                
2     44 -4 0.2817 0.8881

p-value가 0.8881이므로 Granger causality가 없다. 즉, chicken은 egg에 인과요인이 아니다.

결과를 해석하면 다음과 같다.

닭이 달걀을 낳으면 그 수는 그로부터 약 4년 후까지의 닭의 개체수에 영향을 준다. 하지만 닭의 개체수가 많아졌다고 해서 달걀을 많이 낳지는 않는다. Granger Causality가 확실한 인과관계를 뜻하는 것은 아니어서 다소 억지가 될 수 있지만 위의 결과로만 볼 때 달걀이 닭보다 먼저이다.

R 예제 - 이스라엘과 팔레스타인의 침공문제, 누가 먼저 싸움을 걸었는가?

MSBVAR 패키지에서 제공하는 데이터중에 IsraelPalestineConflict라는 데이터가 있는데 이 데이터는 이스라엘과 팔레스타인의 충돌에 대한 데이터로 1주일을 단위로 집계된 데이터이다. 흥미로운 주제의 데이터인데 이 데이터를 통해서 이스라엘가 팔레스타인 중에 누가 먼저 공격을 시작했고 누가 따라서 보복을 했는지를 확인해 본다. 이 데이터에 대한 자세한 내용은 R에서 ?IsraelPalestineConflict 명령으로 확인해 보도록 한다. 다음과 같이 데이터를 로딩해서 확인해본다.

require(MSBVAR)
data(package="MSBVAR")
data(IsraelPalestineConflict)
head(as.data.frame(IsraelPalestineConflict))
?IsraelPalestineConflict

1979년부터 2003년까지 주단위로 Goldestein scaled 로 요약 집계한 데이터이다. 우선 시각화를 통해서 확인해 본다.

plot(IsraelPalestineConflict)

다음과 같은 플롯을 볼 수 있다. 정상 시계열 여부는 플롯상으로는 뚜렷하게 확인할 수 없지만 이 시계열은 정상시계열인 것으로 이미 알려져 있다. 그래서 정상시계열 변환 과정을 진행하지 않고 그대로 사용한다.

이제 granger.test라는 MSBVAR패키지내에서 있는 Granger causality 함수들 사용해 본다. lmtest내의 grangertest 함수와 MSBVAR의 granger.test 함수의 차이점은 granger.test함수는 방향을 서로 바꿔가고 결합해서 테스트 해 준다는 차이점이다. 조금 더 편리하다. 우선 각각의 침공을 기준으로 6주후까지의 반응을 볼 때 결과가 어떻게 나오는지 보겠다.

granger.test(IsraelPalestineConflict, p=6)

위의 코드 실행 결과는 다음과 같다.

           F-statistic      p-value
p2i -> i2p    17.63100 0.000000e+00
i2p -> p2i    10.91235 7.134737e-12

p2i는 팔레스타인이 이스라엘을 공격한 것, i2p는 이스라엘이 팔레스타인을 공격한 것을 말한다. 위의 결과에서는 p-value가 모두 0.05이하로 Granger causality가 양쪽으로 모두 성립한다.

이 결과로는 누가 먼저 도발이나 공격을 시작했는지 알 수 없다. 쌍방이 복합하게 서로 공격, 보복, 공격을 반복하거나 했을 것을 예상할 수 있다. 하지만 위에서 F통계값을 보면 어느쪽이 더 먼저인지 간접적으로 유추가 가능하다.

F통계값이 첫번째 줄의 것이 더 높은 것을 볼 때 이스라엘이 먼저 시작하면 팔레스타인은 대략 6주후까지 보복공격을 한다고 볼 수 있다.

즉 이스라엘이 먼저 공격하고 팔레스타인이 보복하는 경향이 더 강하다.

1주 후까지 의 관계를 다음과 같이 살펴보자.

granger.test(IsraelPalestineConflict, p=1)

결과는 다음과 같다.

#            F-statistic p-value
# p2i -> i2p    72.52305       0
# i2p -> p2i   129.37023       0

1주 후까지의 시차 (lag)를 볼 때 둘 다 우열을 가리기 힘들다.

이스라엘은 팔레스타인이 공격하면 1주이내에 즉각 보복한다고 할 수 있다. 물론 팔레스타인도 보복을 하지만 바로 하지는 않는다. 이 것은 경제적으로 더 나은 위치에 있고 집단응집력이 강한 이스라엘은 반격의 준비가 되어 있어 바로 보복이 가능하지만 팔레스타인은 그렇지 않기 때문에 바로 보복을 하지 못하는 것이라고 볼 수도 있다.

참고자료