본문 바로가기
에라이, 일단 레츠 두 잇, 회귀분석 - OLS Regression 손으로 풀어보기

자, 이제까지 회귀에 대해서 계속 말만 꺼냈지, 실제로 회귀를 해보지 않았으니까, 서툴더라도 회귀라는 것을 한번 해보자고요.  - 분석 결과의 해석은 이걸 해 보고 하는 것으로... 아직은 회귀에 대하여 똥멍충이니까  - 

회귀는 다음의 회귀식을 구하는 것이 일단 목표입니다. 

 

관측 데이터로부터 회귀식을 구하려면, y절편과 기울기만 구하면 되는데, 잘 보면 보통의 1차식 y = ax + b을 거꾸로 쓴 것을 느낄 수 있을 것인데, 이건  통계적인 Regression Model이라는 것을 표현하기 위해서 그냥 관습적으로 거꾸로 쓰는 것 이긴 합니다만, 실제적인 의미로는 이렇게 표현하면 고차방정식까지의 확장성을 고려하여 2차, 3차... 방정식을 구했을 때 b를 계속적으로 숫자를 늘려서 표현할 수 있는 장점이 있습니다.  b₀는 1차 방정식에서부터 항상 필요한 값이므로 더욱 확장할 수 있도록 b₀에서부터 할당하면 계수들을 표현하기 편리하기 때문입니다. $\hat{y} = b_0 + b_1 x + b_2 x^2 + b_3 x^3 + \cdots $ 머, 이런 식이 되겠습니다. 

자, 일단 회귀식을 구할 떄는 먼저 기울기를 구하고, y 절편을 구합니다. 왜냐하면 y절편을 구하기 위해서는 x=0의 경우가 있어야 하는데, 보통 데이터는 x=0의 경우가 거의 없기 때문에 기울기를 먼저 구합니다. 기울기를 구할 때 이용하는 것이 최소제곱법입니다. 결과만 먼저 얘기한다면, b₁은 

$$b_{1}=\frac{\sum\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right)}{\sum\left(x_{i}-\bar{x}\right)^{2}} $$

이렇게 구합니다. 음. 당연히 b₁을 구할 수 있기만 하면 x=0를 이용하면 y절편 b₀롤 쉽게 구할 수 있을 것 같습니다만. x=0를 회귀식에 곧바로 넣기엔 역시나 x=0에 대한 y값이 없는 경우가 많으니까, y절편을 구할 때의 데이터는 $(\bar{x}, \bar{y})$의 데이터를 이용해서 y절편 b₀를 구합니다. -라고 했지만 실제의 이유로는 우리가 구하는 회귀선은 $(\bar{x}, \bar{y})$를 꼭 지나갑니다. -

$$ \hat{y} = b_0 + b_1x  \,\Biggr\rvert_{\substack{x=\bar{x} \\ y=\bar{y}}} \\ \therefore b_0 = \bar{y} - b_1\bar{x}$$

아 간단하네요. 회귀 끗. 아, 잠깐만 그렇긴 한데, 복잡해 보이는 b₁은 어떻게 구하는가가 많이 궁금하겠습니다. 어떻게 하냐면 Error의 최소화 관점에서 y절편과 기울기를 구하는 것이 일반적인 방법인데 말인데요, 이것이 (에러)최소제곱법이고, 이렇게 계수를 구하는 방법을 OLS, Ordinary Least Squares라고 부릅니다. 왜 Ordinary냐 하면 지금 다루고 있는 최소제곱법 회귀가 가장 기본이 되는 회귀이기 때문입니다. 아무런 기교가 섞이지 않은 Original 같은 느낌이랄까요. 설마 회귀가 여기에서 끝나리라고 생각하진 않았겠죠. 오산입니다. 어쨌거나 오차가 가장 작은 것을 찾는 방법인데, 관측치와 예측치의 오차를 제곱해서 합했을 때, 합이 가장 작아지는 값을 찾는 방법입니다. 어찌 보면 누구나 생각해 낼 수 있는 상식적인 접근입니다. 

오차를 다음과 같이 정의한다면, 
$$E= \sum\left(y_{i}-\hat{y_i}\right)^{2} = \sum\left(y_{i}-a-b x_{i}\right)^{2} = \sum {(y_i - b_0 - b_1 x_i)^2}$$

오차의 제곱의 합을 정의했으니까, 어쨌든 최소값을 구하기 위하여 오차제곱의합을 b₀ 즉, y절편에 대해 편미분을 하고,
$$
\frac{\partial E}{\partial b_0}=\sum 2\cdot\left(y_{i}-b_0-b_1 x_{i}\right)(-1)=0 \\
\sum y_{i}=\sum b_0+b_1 \sum x_{i} \\
\sum y_{i}=n b_0+b_1 \sum x_{i}
 \cdots(1)$$
오차제곱의합을 기울기 b₁에 대해서 편미분을 하면, 
$$
\frac{\partial E}{\partial b_1}=\sum 2\cdot\left(y_{i}-b_0-b_1 x_{i}\right)\left(-x_{i}\right)=0
\\ \sum\left(y_{i}-b_0-b_1 x_{i}\right)\left(x_{i}\right)=0 \\
\sum x_{i} y_{i}=b_0 \sum x_{i}+b_1 \sum x_{i}^{2} \cdots(2)
$$
이렇게 2개의 연립방정식이 나옵니다. 두식 모두 계수에 대하여 아래로 볼록한 convex 함수로부터 미분한 것이니까 두 식을 0으로 만드는 계수 값들은 최소값입니다. 그러니까, 결국 (1), (2) 연립방정식을 풀면, b₀와 b₁에 대한 오차제곱합의 최소값을 구할 수 있겠습니다.라고 간단하게 말했지만, 방정식을 풀기에는 좀 복잡해 보이죠. -  그러니까 어쨌든 어쩌고 저쩌고 해서 정리하면 아래와 같이 기울기와 y절편을 구할 수 있게 되는 것입니다. 

$$
\begin{aligned}
b_1 \,&=\frac{n \sum x_i y_i-\sum x_i \sum y_i}{n \sum x_i^{2}-\left(\sum x_i\right)^{2}} \\
&=\frac{\sum\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right)}{\sum\left(x_{i}-\bar{x}\right)^{2}}
\end{aligned}
$$
$$
b_0=\frac{\sum y \sum x^{2}-\sum x \sum x y}{n \sum x^{2}-\left(\sum x\right)^{2}}
=\bar{y}-b_1 \bar{x}
$$

이렇게 구할 수 있습니다. 오, 그렇군요. 

b₁은 대충 Covariance를 Variance로 나눈 것 같은 느낌적인 느낌이죠. 이 느낌 잊으면 안 돼요. Regression Coefficent, 즉 기울기는 x에 대한 x, y의 공동 변화량 느낌으로 다가가면 딱 맞습니다. 그리고, 잔차라는 걸 잠시 코멘트하자면, 원래 회귀선은 각각의 xᵢ에서의 관측치 yᵢ는 정규 분포를 갖고, 그때 각각의 xᵢ에 대한 y 예측값을 $\hat{y_i}$라고 볼 수 있겠습니다.  

예를 들어,
$\hat{y_i} = 10 + 20 x_i $ 이고, (회귀)
$ y_i = 10 + 20 x_i + \epsilon_i $ (관측) 
일 때, 실제 관측값이 (2, 55)라면 
회귀식에 의한 yᵢ값은 10+20×2 = 50
실제관측값은 55니까 εᵢ = 5 가 되는 셈입니다. 요게 잔차라는 것과 연결됩니다. 

자, 이제 잔차와 오차라는 것을 다루게 되는데, 잔차와 오차의 정의는 아래와 같습니다. 

 

잔차의 정의가 자꾸 헷갈릴 수 있으니, 다른 건 모르겠고, 그냥 회귀 모델과 관측값의 차이만 관심 있다고 생각하고, 그 차이가 잔차 Residual라고 생각하면 조금 더 기억하기 좋겠습니다.   

그런데, 이 잔차를 보면 처음에 우리가 오차 Error를 정의해서 편미분 했던 것 있잖아요?

$$E= \sum\left(y_{i}-\hat{y_i}\right)^{2} =  \sum {(y_i - b_0 - b_1 x_i)^2}$$ 

요기에서 

$$ \left(y_{i}-\hat{y_i}\right) $$

요게 잔차입니다. 

그러니까, 다시 한번 정리해 보면, 단순 선형회귀는 잔차의 제곱의 합을 최소화하는 계수를 찾아내는 것이라고 정리할 수 있겠습니다. 

최소제곱법 = $ minimize(\sum(Residual)^2) = minimize \left(\sum\left(y_{i}-\hat{y_i}\right)^{2}\right) $ 이런 스토리입니다. 

아하. 이제 회귀라는 것의 정체가 제대로 보이는군요. 조금 이른 이야기이지만 잔차 제곱의 합이 cost라는 건데, 이 cost를 최소화하는 것. 그것이 기계학습에서의 통계적 접근을 일컫는 것입니다. 매우 중요한 이야기입니다.

어쨌든 그러면 회귀분석을 어떤 식으로 하는지 직접 해보자고요.

배달거리x 100 200 300 400 500
배달시간y 30 56 76 140 197

이런 데이터가 있다고 합시다. 갑자기 짜장면이 먹고 싶어 지는데, 짜파게티라도 끓여먹을까 하는 생각이 절로 드는군요. 

요런 데이터들이고요. 배달이라고 하니, 자, b₀, b₁을 계산하기 위해서 다음의 테이블처럼 계산해 봅시다. 

$$ b_1 = \cfrac{\sum(x_i-\bar{x})(y_i-\bar{y}))}{\sum{(x_i - \bar{x})^2}} = \cfrac{42600}{100000} = 0.426 \\
b_0= \bar{y}-b_1 \bar{x} = 100-0.426 \times 300 = -27.8
$$

오, 결국 구해진 값은,  
$b_1$ 0.426, $b_0$ -27.8 이니까, 회귀식은 $\hat{y} = -27.8 + 0.426x$ 라고 구할 수 있습니다.

 

요런 식의 추세선이 그려질 것입니다. 뭐, 대~충 잘 그린 것 같습니다. 

막상 해 보니, 너무 많은 계산과 노력이 소요되는군요. 매일매일 이걸 해야 한다고 하면, 너무 슬픈 얘기입니다. 그럼, 이걸 python의 sklearn으로 구해볼까요? 세상 고마운 컴퓨터. 세상을 너~무 쉽게 만들어줍니다~

from sklearn.linear_model import LinearRegression # Package를 import하고요,
x = [[100], [200], [300], [400], [500]] # x데이터
y = [28, 56, 76, 142, 198] # y데이터
line_fitter = LinearRegression() 
line_fitter.fit(x, y) # Regression 실행
print (line_fitter.coef_) # Slope 출력
print (line_fitter.intercept_) # Intercept 출력
>
[0.426]
-27.79999999999994

 

오, 우리가 계산했던 것과 똑같이 나왔군요. 이런 식으로 Regression을 할 수 있는데, 더 자세한 데이터에 대한 회귀 모델의 분석 결과를 얻을 수도 있고, pandas Dataframe을 이용할 수 있는 조금 더 편리한 방식으로 Regression을 하는 방법도 있습니다. (statsmodel에 OLS Regression Package가 또 있습니다.)

from statsmodels.formula.api import ols
import pandas as pd
x = [100, 200, 300, 400, 500] # x데이터
y = [28, 56, 76, 142, 198] # y데이터
intercept = [0, 0, 0, 0, 0]
df = pd.DataFrame({'x':x, 'y':y, 'intercept':intercept})
res = ols('y ~ x', data=df).fit() # y~x는 y=... x라는 뜻
res.summary()

 

이렇게 Regression을 한 후, summary()를 실행하면 결과값이  주르륵 나오는데, 한번 봅시다.

R-squared:	0.952
Adj. R-squared:	0.936
F-statistic:	59.41
Prob (F-statistic):	0.00454

		coef	std err	t	P>|t|	[0.025	0.975]
Intercept	-27.8	18.331	-1.517	0.227	-86.136	30.536
X		0.426	0.055	7.708	0.005	0.25	0.602

 

왓더... 뭐 이상한 값들이 드르륵 나옵니다만, 여기에서 쉽게 알아 볼 수 있는 값들은 기울기가 0.426이고, y절편이 -27.8 정도는 알아볼 수 있겠습니다. 그리고 나머지 이상한 값들이 잔뜩 있는데, 검정에서 보던 F 검정 통계량값들이 보입니다. 오. 검정 통계량이 나오는 걸 보니 뭔가 회귀도 통계가 맞긴 한가 보네... 검정도 하는 걸 보니. 하는 생각이 듭니다. 

사실 회귀분석을 하면서 고려되어야 하는 사항이 몇 개 있습니다. 
정규성 : Residual잔차의 분포가 정규분포를 따르는지
등분산성 : Residual잔차의 분포가 등분산성인지 그러니까, Residual잔차가 서로 같은 분포를 가진 iid인지입니다.   
이 정도는 원래 확인해야 하지만, 지금은 아주 작은 표본으로 공부하는 목적으로 하는 것이니까, 그냥 마구마구 한다는 점 이해해 주세요.

 b₁을 구할 때 미분해서 구할 수도 있지만, 공분산 느낌 잊지 않았겠죠.

$$b_{1}=\frac{\sum\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right)}{\sum\left(x_{i}-\bar{x}\right)^{2}} = \cfrac{Cov(x,y)}{Var(x)}$$

x,y공분산과 x의 분산을 이용해서 기울기를 구할 수도 있습니다. 최소제곱법을 이용해서 방정식을 풀 수도 있지만 다음과 같은 방법으로 기울기를 구할 수도 있다는 점. 

$\begin{aligned} \operatorname{Cov}(x, y) &=\operatorname{Cov}\left(x, \, b_{0}+b_{1} x+\varepsilon\right) \\ &=b_{0} \operatorname{Cov}(x, 1)+b_{1} \operatorname{Cov}(x, x)+\operatorname{Cov}(x, \varepsilon) \end{aligned}$ 

자, x, y의 공분산은 이렇게 표현할 수 있겠습니다.  이때  $\operatorname{Cov}(x, 1)=0$ 이고, $x$ 와 $\varepsilon$ 는 서로 독립이니까, 위의 식은 

$\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,=0+b_{1} \operatorname{Cov}(x, x)+0$ 가 될 수 있겠습니다. 

$\operatorname{Cov}(x, x)=\operatorname{Var}(x)$ 이므로, 위의 식은 또다시,
$\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,=b_{1} \operatorname{Var}(x)$ 가 됩니다.

결국, 

$\operatorname{Cov}(x, y)=b_{1} \operatorname{Var}(x)$ 이므로, 양변을 정리하면,

$$ b_{1}=\cfrac{\operatorname{Cov}(x, y)}{\operatorname{Var}(x)}$$

이 되겠습니다. 결국 기울기는 x,y공분산/x분산의 형태라는 점 알고 있으면 매우 편리합니다. 이렇게 해도 저렇게 해도 뭔가 서로 맞닿아 있는 느낌이군요. 

$$b_{1}=\frac{\sum\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right)}{\sum\left(x_{i}-\bar{x}\right)^{2}}= \frac{\cfrac{\sum\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right)}{n-1}}{\cfrac{\sum\left(x_{i}-\bar{x}\right)^{2}}{n-1}}  = \cfrac{Cov(x,y)}{Var(x)}$$ 

사실은 이런 식으로 원래의 b₁에 대하여 걍 분자와 분모를 n-1로 나눠도 익숙한 공분산/분산의 형태가 됩니다. 공분산은 처음에 정의했을 때에는 pca부터 시작해서 이렇게까지 계속 다시 만나게 될 줄 몰랐는데, 참 여러모로 많이 관련되어 있으니 친해져야 하겠습니다. 

친절한 데이터 사이언스 강좌 글 전체 목차 (정주행 링크) -



댓글





친절한 데이터 사이언스 강좌 글 전체 목차 (정주행 링크) -