상관 및 회귀 분석

과목: 데이터 사이언스
주제: 상관계수, 단순/다중 회귀분석, 데이터 해석

들어가기

이번 장에서는 변수들 간의 관계를 이해하기 위한 상관 분석과 회귀 분석을 다룬다.
이는 데이터의 패턴을 이해하고 예측 모델을 구축하는 데 핵심적인 도구이다.

  • 상관 분석(Correlation Analysis): 두 변수 간의 선형적 관계의 강도와 방향을 측정
  • 회귀 분석(Regression Analysis): 하나 또는 그 이상의 독립 변수를 이용하여 종속 변수를 설명하거나 예측

상관 분석

상관의 개념

상관은 두 변수가 함께 변하는 정도를 수치로 나타낸 것이다.

  • 양의 상관 → 두 변수가 함께 증가
  • 음의 상관 → 한 변수가 증가할 때 다른 변수는 감소
  • 0에 가까운 상관 → 선형적 관계가 거의 없음

피어슨 상관계수 (Pearson Correlation Coefficient)

가장 널리 쓰이는 상관계수는 피어슨 상관계수 \(r\) 로, 다음과 같이 정의된다.

\[ r = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n}(x_i - \bar{x})^2} \sqrt{\sum_{i=1}^{n}(y_i - \bar{y})^2}} \]
  • \(r \in [-1, 1]\)
  • \(r = 1\): 완전한 양의 상관
  • \(r = -1\): 완전한 음의 상관
  • \(r = 0\): 선형 상관 없음

⚠️ 상관관계는 인과관계를 의미하지 않는다.

코사인 유사도 (Cosine Similarity)

두 벡터의 내적을 각 벡터의 노름으로 정규화한 값 → 각도 기반 유사도.

\[ \text{cosine\_sim}(x, y) = \frac{x \cdot y}{\|x\| \|y\|} = \frac{\sum_{i=1}^n x_i y_i}{\sqrt{\sum_{i=1}^n x_i^2} \sqrt{\sum_{i=1}^n y_i^2}} \]
  • 범위: 이론상 \([-1, 1]\) (실무에선 비음수 데이터가 많아 0~1로 쓰이는 경우가 많음)
  • 의미: 벡터 방향의 유사성(크기 무시)

차이점

구분 피어슨 상관계수 코사인 유사도
관점 평균을 제거한 선형 관계 크기 무시, 방향(각도)
평균(shift) 영향 제거(중심화)로 영향 적음 평균 이동에 민감
스케일(scale) 영향 표준편차로 정규화 노름 정규화로 크기 영향 제거
주 사용처 통계적 상관, 변수 관계 분석 텍스트 임베딩, 추천, 벡터 검색
해석 같이 오르내리면 높음 같은 방향일수록 높음

한 줄 요약: “같이 오르내리는가?”는 피어슨, “같은 방향을 가리키는가?”는 코사인.

실습 1: 완전 선형 관계(스케일만 다름)

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])  # x와 완전 선형 관계 (배수)

pearson_r = np.corrcoef(x, y)[0, 1]
cos_sim = cosine_similarity([x], [y])[0, 0]

print("피어슨 상관계수:", pearson_r)
print("코사인 유사도:", cos_sim)
  • 출력결과
실행결과
피어슨 상관계수: 1.0
코사인 유사도: 0.9999999999999999

해석: 크기만 달라도 선형 패턴과 방향이 동일하므로 두 값 모두 1에 가깝다.


실습 2: 상수항(평행 이동) 추가

x = np.array([1, 2, 3, 4, 5])
y = x + 100  # 평균이 크게 이동

pearson_r = np.corrcoef(x, y)[0, 1]
cos_sim = cosine_similarity([x], [y])[0, 0]

print("피어슨 상관계수:", pearson_r)
print("코사인 유사도:", cos_sim)
  • 출력결과
실행결과
피어슨 상관계수: 1.0
코사인 유사도: 0.9786043735886338

해석:

  • 피어슨: 평균을 뺀 뒤 보는 지표라서 “형태가 같은가?”만 보며 1.0 유지

  • 코사인: 평균 이동으로 각도가 미세하게 변해 1에서 멀어진다


언제 무엇을 쓸까?

  • 피어슨 상관계수

  • 목적: 통계적 상관(공분산 기반)

  • 데이터: 연속형 변수, 선형적 관계 가정

  • 사용처: 변수 간 관계 탐색, 회귀 전 상관 검토

  • 코사인 유사도

  • 목적: 벡터 의미 유사성(방향 기반)

  • 데이터: 고차원 임베딩(문장/문서/이미지), sparse 벡터

  • 사용처: 검색/추천, 최근접 이웃 탐색, 문장 의미 비교


실무 팁 & 주의사항

  • 상관 ≠ 인과: 높은 피어슨 값이 원인-결과를 의미하진 않는다.
  • 비선형 관계: 피어슨은 선형성에 민감. 비선형이라면 스피어만 순위 상관(ρ), 켄달 τ 고려.
  • 스케일 & 평균 처리:
  • 피어슨은 평균 중심화가 내장
  • 코사인은 크기를 무시하지만 평균 이동에는 민감 → 필요 시 중앙값/평균 보정 고려
  • 희소 벡터(예: TF–IDF): 코사인이 안정적이고 빠르게 동작하는 편
    ### 상관행렬 및 히트맵 시각화
    
    ```python
    import seaborn as sns
    import matplotlib.pyplot as plt
    
    # 여러 변수 예시
    np.random.seed(42)
    df_multi = pd.DataFrame({
        'X1': np.random.normal(50, 10, 100),
        'X2': np.random.normal(30, 5, 100),
        'X3': np.random.normal(100, 20, 100)
    })
    
    corr_matrix = df_multi.corr()
    
    plt.figure(figsize=(6, 4))
    sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt=".2f")
    plt.title("상관행렬 히트맵")
    plt.show()
    
    실행결과
    그래프 출력됨
    

단순 회귀 분석

개념

단순 회귀분석(Simple Linear Regression) 은 하나의 독립 변수 \(x\)종속 변수 \(y\) 사이의 선형 관계를 모델링한다.

\[ y = \beta_0 + \beta_1 x + \varepsilon \]
  • \(\beta_0\): 절편
  • \(\beta_1\): 기울기
  • \(\varepsilon\): 오차항

파이썬 예제: 단순 회귀

from sklearn.linear_model import LinearRegression
import numpy as np

X = df[['공부시간']]  # 2차원 배열
y = df['점수']

model = LinearRegression()
model.fit(X, y)

print("절편 (β0):", model.intercept_)
print("기울기 (β1):", model.coef_[0])

# 공부시간이 7시간일 때 점수 예측
y_pred_7 = model.predict([[7]])
print("예측 점수 (x=7):", y_pred_7[0])
실행결과
[오류 발생] name 'df' is not defined

회귀직선 시각화

plt.scatter(X, y, color='blue', label='데이터')
plt.plot(X, model.predict(X), color='red', label='회귀직선')
plt.xlabel('공부 시간(시간)')
plt.ylabel('점수')
plt.legend()
plt.show()
실행결과
그래프 출력됨


다중 회귀 분석

개념

다중 회귀분석(Multiple Regression)두 개 이상의 독립 변수를 사용해 종속 변수를 설명한다.

\[ y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \cdots + \beta_p x_p + \varepsilon \]

파이썬 예제: 다중 회귀

# 가상의 데이터 생성
np.random.seed(0)
n = 100
X1 = np.random.normal(50, 10, n)
X2 = np.random.normal(30, 5, n)
y = 5 + 0.8*X1 + 1.2*X2 + np.random.normal(0, 5, n)

df_multi = pd.DataFrame({'X1': X1, 'X2': X2, 'y': y})

X = df_multi[['X1', 'X2']]
y = df_multi['y']

model_multi = LinearRegression()
model_multi.fit(X, y)

print("절편:", model_multi.intercept_)
print("회귀계수:", model_multi.coef_)
실행결과
[오류 발생] name 'np' is not defined

회귀계수 해석

  • 절편: 모든 독립변수가 0일 때의 예측값
  • 회귀계수: 다른 변수를 고정했을 때 각 독립변수가 종속 변수에 미치는 영향

모델 평가 지표

결정계수 (\(R^2\))

모델이 종속 변수의 변동을 얼마나 잘 설명하는지를 나타낸다.

\[ R^2 = 1 - \frac{\text{SS}_{\text{res}}}{\text{SS}_{\text{tot}}} \]
  • \(R^2 \approx 1\): 설명력이 매우 좋음
  • \(R^2 \approx 0\): 설명력이 낮음

r2 = model_multi.score(X, y)
print("R^2 점수:", r2)
실행결과
[오류 발생] name 'model_multi' is not defined


잔차(Residual) 분석

잔차 = 실제값 - 예측값
잔차 분석을 통해 회귀모형이 적절한지 판단할 수 있다.

y_pred = model_multi.predict(X)
residuals = y - y_pred

plt.scatter(y_pred, residuals)
plt.axhline(0, color='red', linestyle='--')
plt.xlabel("예측값")
plt.ylabel("잔차")
plt.title("잔차도")
plt.show()
실행결과
그래프 출력됨

좋은 회귀 모델의 잔차는 0을 중심으로 무작위로 퍼져 있어야 하며, 뚜렷한 패턴이 없어야 한다.


요약

  • 상관분석은 변수 간 선형 관계의 강도를 수치로 측정한다.
  • 회귀분석은 변수 간의 함수적 관계를 추정하고 예측에 활용할 수 있다.
  • 시각화 및 잔차 분석은 모델의 적절성을 평가하는 중요한 과정이다.
  • 높은 상관계수나 \(R^2\) 값이 인과관계를 보장하지는 않는다는 점에 유의하자.

⬆️목차이동