728x90
반응형

선형 회귀(Linear Regression)

 통계학의 꽃이라고도 불리는 선형 회귀(Linear Regression)는 수많은 머신러닝 알고리즘의 기반이 되기도 하기 때문에, 반드시 그 원리를 이해해야하는 알고리즘 중 하나다.

 선형 회귀의 원리를 단순하게 말하자면, 관찰값으로부터 가장 거리가 짧은 데이터를 대표할 수 있는 선을 긋는 것이며, 그 선을 회귀식이라고 한다. 관찰값으로부터 가장 짧은 거리인지를 평가하는 방법은 최소제곱법(Least Square Method)이 주로 사용된다.

 

 

 

 

1. 회귀식


$$\hat{y} = \theta_0 + \theta_1x_1 + \theta_2x_2 + \cdots + \theta_nx_n \ \ \ \cdots①$$

$$\hat{y} = h_\theta(x) = \theta \cdot x   \ \ \ \cdots②$$


  • 회귀식은 기본적으로 해가 $n$개인 일차 연립방정식의 형태이며, 계수와 특성의 값의 곱의 합에 편향(Bias, 절편 - Intercept)을 더한 것이다.
  • $\theta_n$는 해당 관찰값의 계수로, 관찰값 $x_n$가 예측값에 미치는 영향을 보여준다.
  • 계수 $\theta$는 음과 양의 부호를 가질 수 있으며, 이를 통해 해당 특성(변수, 필드)가 종속변수(예측값)에 어떠한 영향을 주는지 볼 수 있다.

1.1. 식 ①의 설명

  • $\hat{y}$: 예측값으로, 종속변수(Dependent variable)이라 한다.
  • $n$: 특성의 수, 독립변수(Independent variable)의 수이다.
  • $x_i$: $i$번째 특성값으로, $i$번째 독립변수를 의미한다.
  • $\theta_j$: $j$번째 모델 파라미터로, 머신러닝 알고리즘 스스로가 학습을 통해 찾아내는 값이다.

1.2. 식 ②의 설명

  • 식 ①을 벡터 형태로 바꾼 것으로, $\theta$와 $x$가 열 벡터(Column vector) 라면, 예측은 $\hat{y} = \theta^Tx$가 된다.
  • 열 벡터란 하나의 열(Column)을 가진 2D 배열이며, $\theta^T$는 열벡터 $\theta$의 전치(Transpose)이다.
  • 두 열 벡터 $\theta$와 $x$의 길이는 서로 동일하므로, 전치 벡터와 길이가 동일한 벡터를 곱하면, 동일한 위치의 원소끼리 곱하고, 더하는 효과가 발생한다.
  • $\theta$: 편향 $\theta_0$와 계수 $\theta_1, \theta_2, \cdots, \theta_n$에 대한 모델 파라미터 벡터다.
  • $x$: $x_0, x_1, \cdots, x_n$까지의 데이터의 특성 벡터다. $x_0$는 편향과 곱해지는 값이므로 무조건 1이다.
  • $\theta \cdot x$: 벡터 $\theta$와 $x$의 점곱으로, $\theta_0x_0 + \theta_1x_1 + \theta_2x_2 + \cdots + \theta_nx_n$과 같다.
  • $h_\theta$: 모델 파라미터 $\theta$를 사용한 가설(Hypothesis) 함수다.

 

 

 

 

 

2. 손실함수 RMSE & MSE

  • 선형 회귀 모델의 학습은 훈련 데이터 셋(Train dataset)에 가장 잘 맞는 모델 파라미터($\theta$)를 찾아내는 것이다.
  • 이를 위해 모델이 훈련 데이터에 얼마나 잘 맞는지 측정해야한다.
  • 선형 회귀 모형은 평균 제곱근 오차(Root Mean Square Error, RMSE)를 사용하여, 모델의 성능을 평가하며, RMSE를 최소화하는 $\theta$를 찾아내는 것이 선형 회귀 모델의 학습 과정이다.
  • RMSE 공식은 다음과 같다.

$$RMSE = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(\hat{y_i} - y_i)^2}$$

$$ RMSE(X, h_{\theta}) = RMSE(\theta) = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(\theta^Tx^{(i)} - y^{(i)})^2} $$


  • 평균 제곱근 오차(RMSE)의 원리는 표준편차와 동일하다. 예측값과 실제 관측값의 편차 제곱의 합의 평균에 제곱근을 씌워 제곱의 합을 보정해주는 것이다.
  • 평균 제곱근 오차(RMSE)에 대하여 더 자세히 알고자하는 경우, 다음 포스트 "딥러닝-5.2. 손실함수(3)-평균제곱근오차(RMSE)"를 참고하길 바란다.
  • 예측값과 실제값의 편차의 평균에 가장 근사한 지표는 RMSE지만, 실제 선형 회귀 모델을 만들 때는 평균 제곱 오차(Mean Square Error, MSE)가 더 많이 사용된다.
  • MSE 공식은 다음과 같다.

$$ MSE = \frac{1}{n}\sum_{i=1}^{n}(\hat{y_i} - y_i)^2 $$

$$ MSE(X, h_{\theta}) = MSE(\theta) = \frac{1}{n}\sum_{i=1}^{n}(\theta^Tx^{(i)} - y^{(i)})^2 $$


  • RMSE보다 MSE를 사용하는 이유는 제곱근을 사용하지 않았기 때문에 실제 값보다 증폭된 결과가 도출되긴 하지만, 공식이 더 간단하며, 미분하기도 쉽다.
    어차피 MSE로 도출된 결과들을 비교하기 때문에 다른 모델과 비교할 때, 보다 엄격한 결과가 나오는 RMSE를 굳이 사용할 필요가 없다.
  • MSE에 대해 보다 자세히 알고자 하는 경우, 다음 포스트 "딥러닝-5.1. 손실함수(2)-평균제곱오차(MSE)"를 참고하기 바란다.
  • 선형 회귀 모델에서의 학습은 비용 함수(Cost function, 손실 함수 - Loss function)인 RMSE나 MSE를 최소로 만드는 $\theta$를 찾는 것이다.

 

 

 

 

 

3. 정규방정식(Normal equation)


$$\hat{\theta} = (X^TX)^{-1}X^Ty$$


  • $\hat{\theta}$: 비용 함수를 최소화하는 $\theta$값이다.
  • $y$: $y^(1)$부터 $y^{(m)}$까지 포함하는 타깃 벡터다.
  • 정규방정식(Normal equation, Ordinary least squares, linear least squrares)는 선형 회귀에서 모델 파라미터인 $\theta$를 예측하기 위해 사용하는 최적화 알고리즘이다.
  • 위 정규방정식은 MSE를 통해 유도 된다.

 

3.1. 정규방정식의 유도

  • MSE 공식은 다음과 같다. $MSE(\theta) = \frac{1}{n}\sum_{i=1}^{n}(\theta^Tx^{(i)} - y^{(i)})^2$ 
  • 위 공식을 보면, MSE 공식은 $\theta^T$에 대하여 이차함수의 개형을 갖는 것을 알 수 있다.
  • 그러므로, MSE을 $theta^T$에 대하여 편미분의 결과가 0이 나오게 하는 $\theta^T$의 값이 MSE를 최소로 만드는 값임을 알 수 있다.
  • 위 내용을 이용하여, 정규방정식을 유도해보자.

 

3.2. 정규방정식과 경사하강법의 차이점

  • 대표적인 최적화 알고리즘인 경사하강법(참고: "딥러닝-6.0. 최적화(1)-손실함수와 경사하강법")은 학습률(Learning rate)를 기반으로 점진적으로 최적해를 찾아간다.
  • MSE를 유도하여 만들어진 정규방정식은 행렬 연산을 통해 한 번에 최적해를 구한다.
  • 정규방정식은 행렬 연산을 통해 결과를 구하기 때문에 피처의 크기(Column * Row의 양)가 커지면 커질수록 계산 시간이 오래 걸린다.
  • 경사하강법은 계산이 일어나 기본적으로 소모되는 시간이 크긴 하지만, 아무리 피처의 크기가 크더라도 일정 시간 안에 최적해를 찾아낼 수 있다.
  • 즉, 피처의 크기가 지나치게 크다면 선형 회귀에서도 경사하강법을 사용하는 것이 좋으며, 피처의 크기가 적당한 수준이라면, 정규방정식을 사용하도록 하자.

 

 

[참고]

 

 

 

 다음 포스트에서는 파이썬 넘파이(Numpy) 함수만을 사용해서 선형 회귀 모델을 구현해보고, 사이킷런을 사용해서 선형 회귀 모델을 사용해보도록 하자.

728x90
반응형
728x90
반응형

 이전 포스트에서는 제곱오차(Square Error, SE)와 제곱오차를 기반으로 만들어진 손실함수인 오차제곱합(Sum of Squares for Error, SSE)에 대해 알아보았다. 이번 포스트에서는 이 SSE를 기반으로 만들어진 평균제곱오차(MSE)에 대해 알아보도록 하겠다.

 

 

평균제곱오차(Mean Square Error, MSE)

  • 단순히 실제 데이터와 예측 데이터 편차의 제곱 합이었던 오차제곱합(SSE)을 데이터의 크기로 나눠 평균으로 만든 것이 평균제곱오차다.
  • 그 공식은 다음과 같다.

$$ \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y_i})^2 $$

  • 이전에 봤던 오차제곱합(SSE)는 델타 규칙에 의해 $\frac{1}{2}$을 곱해주었으나, 평균제곱오차(MSE)는 $\frac{1}{n}$이 곱해지므로, 굳이 $\frac{1}{2}$를 곱하지 않아도 된다.

 

 

 

1. 오차제곱합(SSE) 대신 평균제곱오차(MSE)를 주로 사용하는 이유

  • 평균제곱합은 단순히 오차제곱합을 평균으로 만든 것에 지나지 않으므로, 이 둘은 사실상 같다고 볼 수 있다. 그럼에도 평균제곱오차(MSE)를 주로 사용하게 되는 이유는 다음과 같다.
  • 오차의 제곱 값은 항상 양수이며, 데이터가 많으면 많을수록 오차 제곱의 합은 기하급수적으로 커지게 된다.
  • 이로 인해, 오차제곱합으로는 실제 오차가 커서 값이 커지는 것인지 데이터의 양이 많아서 값이 커지는 것인지를 구분할 수 없게 된다.
  • 그러므로, 빅데이터를 대상으로 손실함수를 구한다면, 오차제곱합(SSE)보다 평균제곱오차(MSE)를 사용하는 것을 추천한다.

 

 

 

2. 평균제곱오차(MSE)는 언제 사용하는가?

  • 평균제곱오차(MSE)는 통계학을 한 사람이라면 굉장히 익숙한 단어일 것이다. 
  • 바로, 통계학의 꽃이라고 불리는 회귀분석에서 모델의 적합도를 판단할 때 사용하는 값인 결정 계수 $R^2$를 계산할 때, 분자로 사용되기 때문이다.
  • 딥러닝에서도 평균제곱오차(MSE)는 회귀분석과 유사한 용도로 사용된다.
  • 회귀분석이 연속형 데이터를 사용해 그 관계를 추정하는 방식이듯, 평균제곱오차(MSE) 역시 주식 가격 예측과 같은 연속형 데이터를 사용할 때 사용된다.

 

 

 

3. 구현해보자

  • MSE를 구현하고, SSE와의 차이를 비교해보자.
>>> import numpy as np

>>> def MSE(real, pred):
>>>     return (1/len(real)) * np.sum((real - pred)**2)

>>> def SSE(real, pred):
>>>     return 0.5 * np.sum((real - pred)**2)
# sample Data를 만들어보자.
>>> def make_sample_dataset(data_len, one_index):

>>>     label = np.zeros((data_len,))
>>>     pred = np.full((data_len,), 0.05)

>>>     # 특정 index에 실제 데이터엔 1을 예측 데이터엔 0.8을 넣어보자.
>>>     label[one_index] = 1
>>>     pred[one_index] = 0.8
    
>>>     return label, pred
    
>>> label1, pred1 = make_sample_dataset(100, 30)
>>> label2, pred2 = make_sample_dataset(10000, 30)
>>> label1
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
       
       
>>> pred1
array([0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.8 , 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05])
  • 자, 위에서 만든 샘플 데이터셋 함수는 개수만 다르지, 나머지 원소는 전부 동일한 데이터셋을 반환하는 함수다.
  • 즉, 데이터의 수만 다르지, 편차는 동일한 형태의 데이터셋을 반환한다.
>>> print("Data가 100개일 때, SSE의 결과:", np.round(SSE(label1, pred1), 5))
>>> print("Data가 1000개일 때, SSE의 결과:", np.round(SSE(label2, pred2), 5))
>>> print("----"*20)
>>> print("Data가 100개일 때, MSE의 결과:", np.round(MSE(label1, pred1), 5))
>>> print("Data가 1000개일 때, MSE의 결과:", np.round(MSE(label2, pred2), 5))


Data가 100개일 때, SSE의 결과: 0.14375
Data가 1000개일 때, SSE의 결과: 12.51875
--------------------------------------------------------------------------------
Data가 100개일 때, MSE의 결과: 0.00288
Data가 1000개일 때, MSE의 결과: 0.0025
  • 위 결과를 보면, 어째서 SSE를 사용하면 위험한지를 알 수 있다.
  • 두 데이터셋은 데이터의 양만 다를 뿐 편차는 같은데, SSE는 90배에 가까운 차이를 반환하였다.
  • 물론, 최적의 가중치를 찾아가면서 손실함수 SSE 역시 감소하긴 하겠으나, Data의 양이 지나치게 많다면, 실제로 오차가 거의 없다 할지라도 오차가 굉장히 크게 나올 위험이 있다.
  • 그러므로, 가능한 SSE보다는 MSE를 사용하길 바란다.

 

 

 

 지금까지 연속형 데이터를 다룰 때, 가장 많이 사용되는 손실함수 중 하나인 평균제곱오차(MSE)에 대하여 알아보았다. 다음 포스트에서는 MSE에서 유도되어 나온 또 다른 손실함수인 평균제곱근편차(RMSE)에 대하여 알아보도록 하겠다.

728x90
반응형

+ Recent posts