머신러닝 관련 포스팅을 하면서 아주 기본적이지만 이론적으로 강력한 선형 회귀 관련 내용을 포스팅하지 않았다는 것에 매우 놀랐다.
이번 포스팅에서는 선형 회귀 모형에 대해서 알아보고 파이썬(Python)을 이용하여 구현해보는 방법을 알아보려고 한다.
여기서 다루는 내용은 다음과 같다.
1. 선형 회귀(Linear Regression) 모형이란?
2. 선형 회귀(Linear Regression) 파이썬(Python) 구현하기
이 곳은 꽁냥이가 머신러닝을 공부한 내용을 정리하는 곳입니다.
이 포스팅에서는 수식을 포함하고 있습니다. 티스토리 피드에서는 수식이 제대로 표시되지 않을 수 있으니 웹브라우저 또는 모바일 웹브라우저로 보시길 바랍니다.
1. 선형 회귀(Linear Regression) 모형이란?
- 정의 -
선형 회귀 모형은 반응 변수를 설명 변수들의 선형 결합을 이용하여 예측하는 모형으로 최소제곱법을 이용하여 관련 모수를 추정하게 된다.
위 정의를 하나씩 살펴보자.
a. 선형 회귀 모형은 반응 변수를 설명 변수들의 선형 결합으로 설명 또는 예측할 수 있다고 가정한다.
먼저 반응 변수(또는 종속 변수)는 특정 변수에 종속적으로 반응하는 변수라 할 수 있고 예측 대상이 되는 변수다. 그리고 설명 변수(또는 독립변수)는 반응 변수에 영향을 끼치리라 생각되는 변수를 말한다.
우리에게 데이터 $(\tilde{x}_i, y_i), i=1, \ldots, n$이 있다. 이때 $y_i$는 반응 변수, $\tilde{x}_i \in \mathbb{R}^p$는 $p$ 차원 설명 변수 벡터이다.
설명 변수는 반응 변수에 영향을 미친다고 했다. 이 말은 설명 변수가 반응 변수를 설명 또는 예측할 수 있다는 것과 같다. 이를 수식으로 표현하면 아래와 같다.
$$y_i = f(\tilde{x}_i) + \epsilon_i, i=1, \ldots, n\tag{1}$$
여기서 $f$는 $\mathbb{R}^p$에서 실수 집합 $\mathbb{R}$로 가는 함수이며 $\epsilon_i$ 오차항으로 설명 변수로는 도저히 예측할 수 없는 부분이다.
즉, $\tilde{x}$라는 설명 변수가 주어지면 $f$라는 함수 관계를 통하여 오차 범위 내에서 설명할 수 있다는 뜻이며 설명한다는 것은 설명 변수가 주어지면 식 (1)의 관계를 통하여 오차 범위 내에서 $y$를 생성할 수 있다는 것이다(오차항때문에 설명 변수와 반응 변수는 정확한 함수 관계가 아닌 것이다).
하지만 $f$ 집합이 너무 광범위하여 최적 함수를 찾기가 어렵다. 따라서 이를 제약할 필요가 있는데 선형 회귀 모형은 함수 $f$의 집합을 다음과 같이 제약한다.
$$f(\tilde{x}) = \beta_0 + \beta_1x_1+\cdots +\beta_px_p$$
즉, 선형 회귀 모형은 설명 변수의 선형 함수를 통하여 반응 변수를 설명 또는 예측할 수 있다고 가정하는 것이다(설명 변수의 선형식을 이용하여 오차 범위 내에서 반응 변수를 재생성할 수 있다).
b. 선형 회귀 모형 관련 모수는 최소제곱법을 이용하여 추정한다.
먼저 설명 변수가 한 개 있다고 생각해보자. 그리고 데이터는 $(x_i, y_i), i=1, \ldots, n$이 주어졌다.
그렇다면 선형 회귀 모형은 반응 변수 $y_i$를 다음과 같이 설명 변수와의 관계를 다음과 같다고 가정하는 것이다.
$$y_i = \beta_0 + \beta_1 x_i + \epsilon_i$$
일단 $\epsilon_i$은 설명 변수와 관계없다는 가정이 있으니 신경 쓰지 않아도 된다(즉 오차는 당연히 있다고 생각하는 것이다). 현재 우리가 직면하고 있는 가장 큰 문제는 $\beta_0, \beta_1$을 모른다는 것이다. 그렇다면 이를 데이터로부터 추정해야 한다.
우리에게 주어진 것은 $x_i, y_i$ 이므로 아래와 같이 xy 평면으로 시각화할 수 있다(그림 왼쪽). $\beta_0, \beta_1$를 추정한다는 것은 오른쪽 그림에서 여러 직선 후보 중에서 하나를 선택하는 것과 같다.
만약 오른쪽 그림의 세 개 직선(빨강, 파랑, 보라 선)에서 데이터 구조를 잘 반영하는 직선을 선택해야 한다면 어떤 것을 선택할까?
우리는 본능적으로 파란 직선을 고르게 된다. 빨강, 보라 직선은 데이터와의 거리 좀 더 엄밀히 말하면 ($y$축 과 평행한) 데이터와의 수직 거리가 멀기 때문에 적절한 직선이 아니기 때문일 것이다. 결국 우리는 본능적으로 최소제곱법이라는 것을 적용한 것이다.
이를 수식화하면 다음과 같다. 즉, 우리는 직선 중에서 데이터와의 수직 거리의 제곱합을 최소화시키는 직선을 고르는 것이다.
$$\DeclareMathOperator*{\argminA}{arg\,min} \hat{\beta}_0, \hat{\beta}_1 = \argminA_{\beta_0, \beta_1} \sum_{i=1}^n(y_i-\beta_0-\beta_1x_i)^2\tag{2}$$
이를 $p$ 차원 설명 변수 벡터 $\tilde{x}_i$로 확장하고 행렬을 이용하면 식 (2) 문제를 다음과 같이 표현할 수 있다.
$$\DeclareMathOperator*{\argminA}{arg\,min} \hat{\beta} = \argminA_{\beta\in \mathbb{R}^{p+1}}(\tilde{y}-X\beta)^t(\tilde{y}-X\beta)\tag{3}$$
여기서 $\tilde{y} = (y_1, \ldots, y_n)^t, X = (\tilde{1}, \tilde{x}_1, \ldots, \tilde{x}_p)$로 $n\times (p+1)$ 행렬이다. $\tilde{1}$은 모든 원소가 1인 $n$차원 벡터이다.
즉, 선형 회귀 모형은 데이터의 수직거리의 제곱을 최소화하는 모수를 선택하게 된다. 최소제곱법을 이용하여 추정한다는 것이다.
- 가정에 대한 고찰 -
선형 회귀 모형에서 관련 모수는 특별한 가정 없이 추정할 수 있다. 하지만 여러 가지 이유로 몇몇 가정을 하게 된다. 이러한 가정을 하는 이론적인 이유에 대해서 알아보자.
(1) 설명 변수 상관관계가 크면 안 된다. 다중 공선성이 약해야 한다.
이 가정이 필요한 이유에 대해서 알아보자. 먼저 식 (3)의 해는 항상 존재하며 그 해는 다음과 같다.
$$\hat{\beta} = (X^tX)^{-}X^ty \tag{4}$$
여기서 $A^{-}$은 $A$의 일반화 역행렬(Generalized Inverse)이다.
이 얘기를 왜 하느냐고 할 수 있지만 다중 공선성이 극단적으로 강한 경우, 즉 완벽한 선형 관계를 갖는 두 설명 변수 벡터가 있다면 (4)는 무한히 많게 된다. 무한히 많아서 어떤 추정량을 선택해야하는가에 대한 문제가 생긴다. 따라서 이러한 문제를 해결하기 위하여 다중 공선성이 약하다는 가정을 하게 된다. 이 경우 최소제곱추정량은 유일하게 결정된다.
다중 공선성이 강한 경우 해결 방법은 아래 포스팅을 참고하기 바란다.
[회귀 분석] 7. 다중공선성 확인하기 - 분산 팽창 인자 with Python
(2) 오차의 분산은 등분산성을 가져야 한다.
여기서 등분산성이란 오차의 분산이 설명 변수에 의존하지 않는 것을 말한다. Gauss-Markov 정리에 의하면 반응 변수의 선형 결합 불편 추정량 중에서 최소제곱추정량이 가장 작은 분산을 갖는 BLUE(Best Linear Unbiased Estimator)이다. 이러한 Gauss-Markov 정리에 필요한 가정이 오차의 등분산성이다.
오차의 등분산성을 만족하는지 확인하는 검정방법은 아래 포스팅을 참고하기 바란다.
[회귀 분석] 4. 오차의 등분산성 검정(테스트)하기 with Python
(3) 오차항 간에는 상관성이 없어야 한다(Uncorrelated).
이 또한 Gauss-Markov 정리에서 필요한 조건이다.
(4) 오차항의 분포는 정규분포이어야 한다.
오차항의 정규 분포를 따른다고 한다면 우리는 회귀 모형의 추정치에 대한 신뢰 구간을 계산할 수 있고 통계적 검정을 수행할 수 있게 된다. 또한 Gauss-Markov의 가정에서 오차항의 정규성을 포함하게 된다면 최소제곱추정량은 모든 불편추정량 중에서 최소 분산을 갖게 된다(BUE : Best Unbiased Estimator).
오차항의 정규성 검정은 아래 포스팅을 참고하기 바란다.
[회귀 분석] 3. 정규분포에 대한 가정 검정하기 with Python
- 장단점 -
- 장점 -
a. 설명 변수 변화에 따른 반응 변수의 변화를 해석할 수 있다.
추정된 모수(다른 말로 회귀 계수)는 (다른 변수는 고정시켜놓고) 특정 설명 변수가 한 단위 변화할 때 반응 변수의 변화량으로 해석할 수 있다.
b. 구현이 쉬우며 특별한 가정을 필요로 하지 않는다.
선형 회귀 모형에서 최소 제곱 추정량 계산은 구현이 매우 쉬우며 특별한 가정을 하지 않아도 구할 수 있다.
c. 가정이 맞다면 최적화된 추정량을 제공한다.
오차에 대한 특정 가정을 만족한다면 Gauss-Markov 정리에 의하여 최소제곱추정량은 최소 분산을 갖는 추정량이 될 수 있다.
- 단점 -
a. 예측력이 안 좋다.
선형 함수의 제약으로 인하여 반응 변수와 설명 변수 간에 복잡한 관계가 있다면 예측력이 매우 안 좋을 수 있다.
b. 다중 공선성이 존재할 경우 모수 추정치를 신뢰할 수 없다.
다중 공선성이 존재하는 경우 모수 추정치의 분산이 매우 커져서 추정치를 신뢰할 수 없다.
c. 이상치에 매우 민감하다.
최소제곱추정량은 이상치에 매우 민감하다.
2. 선형 회귀(Linear Regression) 파이썬(Python) 구현하기
이번엔 선형 회귀 모형을 적합하는 과정을 파이썬(Python)으로 구현해보자. 먼저 필요한 모듈을 불러온다.
import numpy as np
import pandas as pd
from sklearn.datasets import load_boston
그리고 선형 회귀 모형을 적합하는 클래스를 만들어 주었다. predict 함수는 반응 변수의 추정값(또는 예측값) $X\hat{\beta}$를 계산한다.
class LinearRegression():
def __init__(self):
self.params = None # 회귀 계수 추정치 벡터
def fit(self, X, y):
X_tX_inv = np.linalg.inv(X.T.dot(X))
X_ty = X.T.dot(y)
params = X_tX_inv.dot(X_ty) # 최소제곱추정치
self.params = params
def predict(self, X):
pred = X.dot(self.params) # 예측
return pred
이제 선형 회귀 모형을 적합해보자. 이를 위해 보스턴 집값 데이터를 가지고 왔다. 이때 설명 변수는 'RM'과 'LSTAT'을 (그냥) 선정했다. 그리고 절편 모수를 추가하기 위하여 1로 이루어진 const 칼럼을 추가했다.
boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['y'] = boston.target
X = df[['RM', 'LSTAT']]
X.insert(0, 'const', [1]*X.shape[0]) ## 1로 이루어진 칼럼 추가
y = df['y'].values
이제 직접 구현한 선형 회귀 모형을 적합시키고 회귀 계수와 성능을 평가하기 위해 잔차 제곱합의 평균을 계산하여 출력해보자.
reg = LinearRegression()
reg.fit(X,y) # 선형 회귀 모형 적합
print('회귀 계수 :' ,reg.params)
print('잔차 제곱합 :', np.mean(np.square(y-reg.predict(X))))
최종 모형은
$$\hat{y}_i = -1.36 + 5.09\cdot RM-0.64\cdot LSTAT$$
이고 잔차 제곱합 평균은 30.51이 나왔다.
이번 포스팅에서는 선형 회귀 모형에 대한 내용을 소개했는데 내 스스로 복습이 되어 좋았다.
참고자료
'통계 > 머신러닝' 카테고리의 다른 글
18. 다중 클래스(Multi-Class) 분류를 위한 One vs Rest, One vs One 방법을 알아보자. (397) | 2022.05.09 |
---|---|
17. Dunn Index와 실루엣(Silhouette) 계수를 이용하여 최적 클러스터(군집, Cluster)개수 정하기 with Python (388) | 2022.05.07 |
15. AdaBoost(Adaptive Boost) 알고리즘에 대해서 알아보자 with Python (382) | 2022.05.06 |
14. 클러스터링(군집화) 평가지표 Silhouette(실루엣) 지수(계수)에 대해서 알아보자 with Python (410) | 2022.05.01 |
13. Box-Cox Transformation(변환)에 대해서 알아보자 with Python (385) | 2022.05.01 |
댓글