[확률] 7.5 공분산과 상관계수

JKH·4일 전
0

확률

목록 보기
10/13

✏️ 데이터 사이언스 스쿨에서 공부한 내용입니다.

표본공분산

표본공분산(sample covariance)은 다음처럼 정의한다. 여기에서 xix_iyiy_i는 각각 ii번째의 xx 자료와 yy자료의 값을 가리키고, xˉ\bar{x}yˉ\bar{y}xx 자료와 yy자료의 표본평균을 가리킨다. 일반적인 분산의 정의 '편차 제곱의 평균'과 유사한 형태이다.

sxy=1Ni=1N(xixˉ)(yiyˉ)(7.5.1)s_{xy} = \dfrac{1}{N}\sum_{i=1}^{N} (x_i-\bar{x})(y_i-\bar{y}) \tag{7.5.1}

표본분산과 마찬가지로 표본공분산도 자료가 평균값으로부터 얼마나 떨어져 있는지를 나타낸 것이다. 공분산은 평균값 위치와 표본 위치를 연결하는 사각형의 면적을 사용한다. 다만 공분산의 경우에는 자료의 위치에 따라 이 값의 부호가 달라진다. 데이터가 1사분면이나 3사분면에 있는 경우에는 양수가 되고 데이터가 2사분면이나 4사분면에 있는 경우에는 음수가 된다. 따라서 공분산의 부호는 XX, YY 데이터가 같은 부호를 가지는지 다른 부호를 가지는지에 대한 지표라고 할 수 있다.

표본상관계수

표본공분산은 평균을 중심으로 각 자료들이 어떻게 분포되어 있는지 크기와 방향성을 같이 보여준다. 그런데 분포의 크기는 공분산이 아닌 분산만으로도 알 수 있기 때문에 대부분의 경우 자료 분포의 방향성만 분리하여 보는 것이 유용하다. 이 때 필요한 것이 표본상관계수(sample correlation coefficient) 다. 이와 다르게 정의한 상관계수도 있기 때문에 다른 종류의 상관계수와 비교하여 말하는 경우에는 피어슨(Pearson) 상관계수라고 하기도 한다. 표본상관계수는 다음과 같이 공분산을 각각의 표본표준편차값으로 나누어 정규화(normalize)하여 정의한다.

rxy=sxysx2sy2(7.5.2)r_{xy} = \dfrac{s_{xy}}{\sqrt{s^2_{x} \cdot s^2_{y}}} \tag{7.5.2}

scipy의 stats 서브패키지는 피어슨 상관계수를 계산하는 pearsonr() 함수를 제공한다. pearsonr() 함수는 상관계수와 유의확률을 반환한다. 유의확률에 대해서는 9장에서 공부한다.

예제

다음 코드는 붓꽃의 꽃받침의 길이와 꽃잎의 길이 사이의 상관계수를 계산하는 코드다. 상관계수가 약 0.87임을 알 수 있다.

import scipy as sp
from sklearn.datasets import load_iris
X = load_iris().data
x1 = X[:, 0]  # 꽃받침의 길이
x2 = X[:, 1]  # 꽃받침의 폭
x3 = X[:, 2]  # 꽃잎의 길이
x4 = X[:, 3]  # 꽃잎의 폭
# statistic = 표본 상관 계수
# pvalue = 한국어로 "유의확률"이라고 합니다. 
# 통계적 가설 검정에서 p-value는 귀무가설이 참이라고 가정했을 때, 
# 관찰된 결과와 같거나 더 극단적인 결과가 발생할 확률을 나타냅니다.
# p-value가 작을수록 귀무가설을 기각할 증거가 더 강력해집니다. 
# 일반적으로 p-value가 0.05보다 작으면 귀무가설을 기각하고, 대립가설을 채택합니다.
# 여기서 이 값이 작으면 우연히 이렇게 나올 확률이 낮다는 뜻이다.
print(sp.stats.pearsonr(x1, x3))
print(sp.stats.pearsonr(x1, x3)[0])
print(sp.stats.pearsonr(x1, x2)[0]) # 연습 문제 7.5.1 (1)
print(sp.stats.pearsonr(x3, x4)[0]) # 연습 문제 7.5.1 (2)
print(sp.stats.pearsonr(x2, x4)[0]) # 연습 문제 7.5.1 (3)
PearsonRResult(statistic=0.8717537758865831, pvalue=1.0386674194498827e-47)
0.8717537758865831

연습 문제 7.5.1

붓꽃 데이터에서 다음 상관계수를 계산하라.

(1) 꽃받침의 길이와 꽃받침의 폭 사이의 상관계수

(2) 꽃잎의 길이와 꽃잎의 폭 사이의 상관계수

(3) 꽃받침의 폭과 꽃잎의 폭 사이의 상관계수

✏️
코드는 위 예제와 같고 출력값은 다음과 같다.
(1) -0.11756978413300206
(2) 0.962865431402796
(3) -0.36612593253643905

확률변수의 공분산과 상관계수

두 확률변수 XXYY의 공분산, 상관계수는 연산자를 사용하여 다음과 같이 정의된다.

Cov[X,Y]=E[(XE[X])(YE[Y])]\text{Cov}[X, Y] = \text{E}[(X - \text{E}[X])(Y - \text{E}[Y])]
ρ[X,Y]=Cov[X,Y]Var[X]Var[Y]\rho[X,Y] = \dfrac{\text{Cov}[X, Y]}{\sqrt{\text{Var}[X] \cdot \text{Var}[Y]}}

확률변수의 상관계수는 다음과 같은 성질을 가진다.

1ρ1(7.5.5)-1 \leq \rho \leq 1 \tag{7.5.5}
  • ρ=1\rho = 1 : 완전선형 상관관계
  • ρ=0\rho = 0 : 무상관 (독립과는 다름)
  • ρ=1\rho = −1 : 완전선형 반상관관계

이 상관계수의 부호와 크기가 의미하는 바는 다음 스캐터 플롯에서 알 수 있다. 이 스캐터 플롯은 특정한 상관계수를 가지는 데이터를 시뮬레이션을 통해 그린 것이다. 스캐터 플롯의 위에 쓰여진 숫자는 시뮬레이션에 사용된 상관계수를 나타낸다. 스캐터 플롯의 데이터가 양의 기울기를 가지는 직선 혹은 타원 모양을 가지면 상관계수는 양수이고 음의 기울기를 가지는 직선 혹은 타원 모양이 되면 상관계수가 음이 된다. 또한 직선 모양이 뚜렷할수록 상관계수의 절대값이 커지고 원에 가까워질 수록 절대값이 작아진다.

np.random.seed(0)
corrs = [1, 0.7, 0.3, 0, -0.3, -0.7, -1]
plt.figure(figsize=(len(corrs), 2))
for i, r in enumerate(corrs):
    x, y = np.random.multivariate_normal([0, 0], [[1, r], [r, 1]], 1000).T
    plt.subplot(1, len(corrs), i + 1)
    plt.plot(x, y, 'ro', ms=1)
    plt.axis('equal')
    plt.xticks([])
    plt.yticks([])
    plt.title(r"$\rho$={}".format(r))

plt.suptitle("상관계수와 스캐터 플롯의 모양", y=1.1)
plt.tight_layout()
plt.show()

또한 상관계수는 스캐터 플롯의 기울기와는 아무런 상관이 없다.

np.random.seed(1)
slope = [1, 0.7, 0.3, 0, -0.3, -0.7, -1]
plt.figure(figsize=(len(slope), 2))
for i, s in enumerate(slope):
    plt.subplot(1, len(slope), i + 1)
    x, y = np.random.multivariate_normal([0, 0], [[1, 1], [1, 1]], 100).T
    y2 = s * y
    plt.plot(x, y2, 'ro', ms=1)
    plt.axis('equal')
    plt.xticks([])
    plt.yticks([])
    if s > 0:
        plt.title(r"$\rho$=1")
    if s < 0:
        plt.title(r"$\rho$=-1")

plt.suptitle("상관계수와 스케터플롯의 기울기", y=1.1)
plt.tight_layout()
plt.show()

연습 문제 7.5.2

(1) 원소의 갯수가 10개인 두 개의 무작위 숫자 벡터를 생성하라. 이 두 벡터가 두 개의 독립적인 확률변수에서 나온 데이터라고 가정한다.

(2) 두 데이터 집합의 표본상관계수를 계산하라. 독립인 확률변수의 상관계수는 0이어야 한다. 표본상관계수의 값도 0인가?

(3) 원소의 갯수를 10,000개로 다시 무작위 숫자 벡터를 생성하고 표본상관계수를 계산하라. 아까와 어떻게 달라졌는가?

(4) 표본상관계수가 이론적 상관계수와 같지 않은 이유는 무엇인가?

✏️

import numpy as np
import scipy.stats as stats
np.random.seed(0)  # for reproducibility
x = np.random.rand(10)
y = np.random.rand(10)
correlation = stats.pearsonr(x, y)[0]
print(f"Sample correlation coefficient: {correlation}")
x2 = np.random.rand(10000)
y2 = np.random.rand(10000)
correlation2 = stats.pearsonr(x2, y2)[0]
print(f"Sample correlation coefficient: {correlation2}")
Sample correlation coefficient: 0.33496904905220537 
Sample correlation coefficient: 0.006574323730456745

상관 계수로 얻은 값은 정확히 0이 아닐 수 있지만, 0에 상대적으로 가까울 것이다. 이는 두 벡터가 독립적으로 생성되었기 때문이다.

이 과정을 10,000개의 요소를 포함하는 벡터로 반복하면, 10개의 요소로 계산한 경우보다 샘플 상관 계수가 훨씬 더 0에 가까워지는 것을 볼 수 있다.

샘플 상관 계수는 이론적인 상관 계수를 추정한 값으로, 실제로 독립적인 확률 변수에 대해 이론적인 상관 계수는 0이다. 하지만 유한한 샘플 수를 가지고 계산할 때는 샘플 상관 계수가 무작위 우연으로 인해 정확히 0이 되지 않는 경우가 많다.

샘플 수가 많아질수록 샘플 상관 계수는 이론적인 상관 계수로 수렴하게 된다. 그래서 10,000개의 요소로 얻은 상관 계수가 10개의 요소로 얻은 값보다 0에 더 가까운 것이다.

비선형 상관관계

두 확률변수가 상관관계가 있으면 두 확률변수의 값 중 하나를 알았을 때 다른 확률변수의 값에 대한 정보를 알 수 있다. 반드시 정확한 값을 알 수 있어야 하는 것은 아니다. 따라서 다음과 같은 경우도 상관관계가 있는 데이터라고 할 수 있다. 선형이 아닌 상관관계를 비선형 상관관계라고 한다. 피어슨 상관계수는 두 확률변수의 관계가 선형적일 때만 상관관계를 제대로 계산할 수 있다.

다음 네가지 데이터는 모두 xx의 값으로부터 yy값을 알 수 있기 때문에 상관관계를 가지고 있다. 하지만 피어슨 상관계수는 모두 0으로 계산된다.

n = 500
np.random.seed(1)
plt.subplot(221)
x1 = np.random.uniform(-1, 1, n)
y1 = 2*x1**2 + np.random.uniform(-0.1, 0.1, n)
plt.scatter(x1, y1)
r1 = sp.stats.pearsonr(x1, y1)[0]
plt.title(r"비선형 상관관계 1: r={:3.1f}".format(r1))
plt.subplot(222)
x2 = np.random.uniform(-1, 1, n)
y2 = 4*(x2**2-0.5)**2 + 0.1 * np.random.uniform(-1, 1, n)
plt.scatter(x2, y2)
r2 = sp.stats.pearsonr(x2, y2)[0]
plt.title(r"비선형 상관관계 2: r={:3.1f}".format(r2))
plt.subplot(223)
x3 = np.random.uniform(-1, 1, n)
y3 = np.cos(x3 * np.pi) + np.random.uniform(0, 1/8, n)
x3 = np.sin(x3 * np.pi) + np.random.uniform(0, 1/8, n)
plt.scatter(x3, y3)
r3 = sp.stats.pearsonr(x3, y3)[0]
plt.title(r"비선형 상관관계 3: r={:3.1f}".format(r3))
plt.subplot(224)
x4 = np.random.uniform(-1, 1, n)
y4 = (x4**2 + np.random.uniform(0, 0.1, n)) * \
    np.array([-1, 1])[np.random.random_integers(0, 1, size=n)]
plt.scatter(x4, y4)
r4 = sp.stats.pearsonr(x4, y4)[0]
plt.title(r"비선형 상관관계 4: r={:3.1f}".format(r4))
plt.tight_layout()
plt.show()

앤스콤 데이터 - 상관계수의 한계

상관계수로 분포의 형상을 추측할 때 개별 자료가 상관계수에 미치는 영향력이 각각 다르다는 점에 유의해야 한다. 다음은 프랭크 앤스콤(Frank Anscombe)의 논문에 예시된 데이터다. 이 데이터는 서로 다른 4종류의 2차원 데이터셋을 포함하는데 4종류 데이터셋 모두 상관계수가 약 0.816로 동일하다.

import statsmodels.api as sm
data = sm.datasets.get_rdataset("anscombe")
df = data.data
df[["x1", "y1", "x2", "y2", "x3", "y3", "x4", "y4"]]
x1 y1 x2 y2 x3 y3 x4 y4
0 10 8.04 10 9.14 10 7.46 8 6.58
1 8 6.95 8 8.14 8 6.77 8 5.76
2 13 7.58 13 8.74 13 12.74 8 7.71
3 9 8.81 9 8.77 9 7.11 8 8.84
4 11 8.33 11 9.26 11 7.81 8 8.47
5 14 9.96 14 8.10 14 8.84 8 7.04
6 6 7.24 6 6.13 6 6.08 8 5.25
7 4 4.26 4 3.10 4 5.39 19 12.50
8 12 10.84 12 9.13 12 8.15 8 5.56
9 7 4.82 7 7.26 7 6.42 8 7.91
10 5 5.68 5 4.74 5 5.73 8 6.89
import matplotlib.pyplot as plt
import seaborn as sns
plt.subplot(221)
sns.regplot(x="x1", y="y1", data=df)
plt.subplot(222)
sns.regplot(x="x2", y="y2", data=df)
plt.subplot(223)
sns.regplot(x="x3", y="y3", data=df)
plt.subplot(224)
sns.regplot(x="x4", y="y4", data=df)
plt.tight_layout()
plt.subplots_adjust(top=0.9)
plt.suptitle("앤스콤의 데이터")
plt.show()

첫번째 데이터셋은 평범한 데이터셋이다.

두번째 데이터셋은 x값을 알면 y값을 완벽하게 알 수 있는 2차함수 형태의 비선형 상관관계를 가진다. 하지만 상관계수는 1인 아닌 약 0.816으로, 비선형 상관관계를 표현하지 못한다.

3, 4번째 데이터셋에서 볼 수 있듯이 단 하나의 특이값(outlier)을 제외한 나머지 데이터의 상관계수가 1 또는 0인 경우에도 특이값이 자료에 포함되면 상관계수가 크게 달라질 수 있다.

다변수 확률변수의 표본공분산

이번에는 스칼라가 아닌 벡터 표본값을 가지는 다변수 확률변수의 공분산에 대해 알아보자. X1,X2,,XMX_1, X_2, \cdots, X_M이라는 MM개의 서로 다른 확률변수가 있다고 하자. 이 확률변수들의 표본 데이터가 각각 NN개가 있으면 j  (j=1,,M)j\;(j=1,\ldots,M)번째 확률변수의 i  (i=1,,N)i\;(i=1,\ldots,N)번째 데이터를 xi,jx_{i,j}로 표기한다. 이를 하나의 행렬로 묶으면 다음과 같은 특징행렬이 된다.

X=[x1,1x1,2x1,Mx2,1x2,2x2,MxN,1xN,2xN,M](7.5.6)X = \begin{bmatrix} x_{1, 1} & x_{1, 2} & \cdots & x_{1, M} \\ x_{2, 1} & x_{2, 2} & \cdots & x_{2, M} \\ \vdots & \vdots & \ddots & \vdots \\ x_{N, 1} & x_{N, 2} & \cdots & x_{N, M} \\ \end{bmatrix} \tag{7.5.6}

MM개의 서로 다른 확률변수의 모든 조합에 대한 공분산을 한꺼번에 표기하기 위해 다음처럼 표본공분산행렬(Sample Covariance Matrix) 을 정의한다. 대각성분은 각각의 확률변수의 분산, 비대각성분은 서로 다른 두 확률변수의 공분산으로 정의되는 행렬이다. 예를 들어 두번째 행, 세번째 열의 원소 s2,3s_{2,3}은 두번째 확률변수와 세번째 확률변수의 공분산이다.

S=[sx12sx1x2sx1xMsx1x2sx22sx2xM    sx1xMsx2xMsxM2](7.5.7)S = \begin{bmatrix} s_{x_1}^2 & s_{x_1x_2} & \cdots & s_{x_1x_M} \\ s_{x_1x_2} & s_{x_2}^2 & \cdots & s_{x_2x_M} \\ \vdots & \;\; \vdots& \ddots & \vdots \\ s_{x_1x_M} & s_{x_2x_M} & \cdots & s_{x_M}^2 \\ \end{bmatrix} \tag{7.5.7}

위 행렬의 값은 다음처럼 구한다.

(1) 각 확률변수 xj(j=1,,M)x_j\,(j=1, \cdots, M)의 표본평균을 계산한다.

xˉj=1Ni=1Nxi,j(7.5.8)\bar{x}_j = \dfrac{1}{N} \sum_{i=1}^N x_{i,j} \tag{7.5.8}

(2) 각 확률변수 xj(j=1,,M)x_j\,(j=1, \cdots, M)의 분산을 계산한다.

sj2=1Ni=1N(xi,jxˉj)2(7.5.9)s_j^2 = \dfrac{1}{N} \sum_{i=1}^N (x_{i,j} - \bar{x}_j)^2 \tag{7.5.9}

(3) 두 확률변수 xj,xkx_j, x_k의 공분산을 계산한다.

sj,k=1Ni=1N(xi,jxˉj)(xi,kxˉk)(7.5.10)s_{j,k} = \dfrac{1}{N} \sum_{i=1}^N (x_{i,j} - \bar{x}_j)(x_{i,k} - \bar{x}_k) \tag{7.5.10}

만약 xi(i=1,,N)x_i (i=1,\ldots, N)가 다음과 같은 MM-차원 표본 벡터로 정의하면

xi=[xi,1xi,M](7.5.11)x_i = \begin{bmatrix}x_{i,1} \\ \vdots \\ x_{i,M} \end{bmatrix} \tag{7.5.11}

표본공분산행렬 SS는 다음 식으로 구할 수 있다.

S=1Ni=1N(xixˉ)(xixˉ)T(7.5.12)S = \dfrac{1}{N}\sum_{i=1}^N (x_i-\bar{x})(x_i-\bar{x})^T \tag{7.5.12}
S=1NX0TX0(7.5.13)S = \dfrac{1}{N} X_0^TX_0 \tag{7.5.13}

xˉ\bar{x}MM-차원 평균벡터이고 X0X_0는 평균이 제거된 N×MN \times M 크기의 데이터 행렬이다.

xˉ=1NXT1N(7.5.14)\bar{x} = \dfrac{1}{N} X^T\mathbf{1_N} \tag{7.5.14}
X0=X1NxˉT=X1N1N1NTX(7.5.15)X_0 = X - \mathbf{1_N}\bar{x}^T = X - \dfrac{1}{N} \mathbf{1_N}\mathbf{1_N}^TX \tag{7.5.15}

연습 문제 7.5.4

붓꽃 데이터에서 4가지 확률변수의 표본공분산행렬을 구하라.

✏️

import numpy as np
from sklearn.datasets import load_iris

X = load_iris().data

def S(data):
    x_bar = np.mean(data, axis=0)
    X0 = data - x_bar
    N = data.shape[0]
    return (1/N) * ( X0.T @ X0 )

print(S(X))

# np.cov(X, rowvar=False) 로 구하는 방법도 있다.
[[ 0.68112222 -0.04215111  1.26582     0.51282889]
 [-0.04215111  0.18871289 -0.32745867 -0.12082844]
 [ 1.26582    -0.32745867  3.09550267  1.286972  ]
 [ 0.51282889 -0.12082844  1.286972    0.57713289]]

다변수 확률변수의 공분산

MM개의 다변수 확률변수 벡터의 이론적 공분산행렬은 Σ\Sigma로 표기하며 다음처럼 정의한다.

X=[X1X2XM](7.5.16)X = \begin{bmatrix} X_1 \\ X_2 \\ \vdots \\ X_M \end{bmatrix} \tag{7.5.16}
Σ=Cov[X]=[σx12σx1x2σx1x3σx1xMσx1x2σx22σx2x3σx2xMσx1xMσx2xMσx3xMσxM2]=E[(X1E[X1])2(X1E[X1])(XME[XM])(X1E[X1])(X2E[X2])(X2E[X2])(XME[XM])(X1E[X1])(XME[XM])(XME[XM])2](7.5.17)\begin{aligned} \Sigma = \text{Cov}[X] &= \begin{bmatrix} \sigma_{x_1}^2 & \sigma_{x_1x_2} & \sigma_{x_1x_3} & \cdots & \sigma_{x_1x_M} \\ \sigma_{x_1x_2} & \sigma_{x_2}^2 & \sigma_{x_2x_3} & \cdots & \sigma_{x_2x_M} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ \sigma_{x_1x_M} & \sigma_{x_2x_M} & \sigma_{x_3x_M} & \cdots & \sigma_{x_M}^2 \\ \end{bmatrix} \\ &= \text{E} \begin{bmatrix} (X_1 - \text{E}[X_1])^2 & \cdots & (X_1 - \text{E}[X_1])(X_M - \text{E}[X_M]) \\ (X_1 - \text{E}[X_1])(X_2 - \text{E}[X_2]) & \cdots & (X_2 - \text{E}[X_2])(X_M - \text{E}[X_M]) \\ \vdots & \ddots & \vdots \\ (X_1 - \text{E}[X_1])(X_M - \text{E}[X_M]) & \cdots & (X_M - \text{E}[X_M])^2 \end{bmatrix} \end{aligned} \tag{7.5.17}

다음과 같이 표기할 수도 있다.

Σ=E[(XE[X])(XE[X])T]=E[[X1E[X1]X2E[X2]XME[XM]][X1E[X1]X2E[X2]XME[XM]]](7.5.18)\begin{aligned} \Sigma &= \text{E} \left[ (X - \text{E}[X])(X - \text{E}[X])^T \right] \\ &= \text{E} \left[ \begin{bmatrix} X_1 - \text{E}[X_1] \\ X_2 - \text{E}[X_2] \\ \vdots \\ X_M - \text{E}[X_M] \\ \end{bmatrix} \begin{bmatrix} X_1 - \text{E}[X_1] & X_2 - \text{E}[X_2] & \cdots & X_M - \text{E}[X_M] \end{bmatrix} \right] \end{aligned} \tag{7.5.18}
profile
Connecting my favorite things

0개의 댓글