선형회귀 분석은 독립 변수(independent)와 종속(dependent) 변수 간의 관계를 찾는 통계적 방법이다.

여기에 주중 총 학습 시간에 따른 학생들의 성적 상관 관계를 보여주는 데이터가 있다. 이 데이터 셋을 예로 들어 선형회귀분석에 대해 알아보자.

시간(Hours) 성적(Marks)
3 35
4 50
5 45
6 64
7 66
8 70

위 표에서 시간(Hours)는 독립 변수이고 성적(Marks)는 종속 변수이다. 유일한 종속 변수는 성적(Marks)이다. 다른 학생들의 성적을 예측할 수 있도록 주어진 데이터를 표현해야한다. 가장 좋은 방법은 평균값을 가진 1차 함수 그래프를 나타내는 것이다.

데이터 6개의 성적 평균 값은 $55((35+50+45+64+66+70)/2)$이다. 따라서 $y = 55$방정식을 직선으로 표현할 수 있다. 이 직선은 선형 회귀에 얼마나 잘 부합하는지 확인할 때 레퍼런스로 활용된다. 이 직선과의 거리를 비교하기 위해 '제곱 오류 합계(SSE: Sum of Squared errors)' 매트릭을 사용한다.

SSE(제곱 오류 합계) 계산하기

각 데이터 포인트에 대해, 실제 값 (예: $35$)과 예측 값 (평균값 : $55$)의 차이를 찾는다. 이 차이를 "오류(error)"(예: $35-55 = -20$)라고 한다. 그런 다음이 오류($(-20 * -20) = 400$)를 제곱한다. 제곱하는 이유는 서로 값의 차이를 높이면서 동시에 절대값을 만들어줌으로 서로 SSE를 비교하기 쉽기 때문이다.이 프로세스를 모든 데이터마다 반복한다. 그 다음으로 모든 데이터 포인트에 대해 계산된 모든 제곱 오류(squared error)를 합산한다. 그러면 SSE(Sum of Aquared Error; 제곱 오류 합계)가 된다.

Hours Marks error=Marks-55 $error^2$
3 35 -20 400
4 50 -5 25
5 45 -10 100
6 64 9 81
7 66 11 121
8 70 15 225
Avg=55 SSE=952

따라서 SSE는 $952$가 된다.

독립 변수(Hours)를 사용해 선형 회귀 분석을 수행하여 최상의 결과를 얻은 후 SSE가 크게 감소해야한다. 만약 SSE 값이 커졌다면 데이터 셋에 부합한 일차함수식과 멀어진 것이다.

선형회귀는 직선의 방정식(Slope intercept form)인 $y = mx + b$을 사용한다. '$x$'는 독립 변수,'$m$'은 기울기, '$b$'는 $y$절편이다. SSE가 최솟값인 방정식의 해를 찾기 위해 '최소제곱법(OLS; Ordinary Least Squares)' 메서드를 사용한다.

최소제곱법(OLS; Ordinary Least Squares)

$\overline{y}=m\overline{x}+b$ 일차 방정식일 때, 최고제곱법의 기울기 $m$ 공식은 다음과 같다.

$m =\dfrac{\displaystyle\sum_{i=1}^n (x_i- \overline{x})(y_i- \overline{y})}{ \displaystyle\sum_{i=1}^n(x_i- \overline{x})^2}$

위 공식에서 $x_i$는 독립 변수(시간), $\overline{x}$는 독립 변수(시간)의 평균 , $y_i$는 종속 변수(성적), $\overline{y}$는 종속 변수(성적)의 평균이다.

각각 계산해보면 아래와 같이 나온다.

Hours Marks $ x_i - \overline{x}$ $y_i- \overline{y}$ $ (x_i-\overline{x})(y_i-\overline{y})$ $ (x_i-\overline{x})^2$
x y $=x_i - 5.5$ $=y_i - 55$
3 35 -2.5 -20 50 6.25
4 50 -1.5 -5 7.5 2.25
5 45 -0.5 -10 5 0.25
6 64 0.5 9 4.5 0.25
7 66 1.5 11 16.5 2.25
8 70 2.5 15 37.5 6.25
$ \Sigma$=121 $ \Sigma$=17.5

최소 제곱법 공식에 대입하여 계산해보면 $m=\frac{121}{7.5}$, 즉 $6.914$이다.

이제 일차 방정식의 $b$를 구하면 된다. $b=\overline{y}-m \cdot \overline{x}$으로, $b=55 - 6.914 \cdot 5.5 = 16.973$가 된다.

따라서 일차 방정식은 $y=6.914x+16.973$가 된다. 그래프를 다시 그려보자.

sse-graph

이제 이 방정식으로 SSE를 다시 계산해보자.

Hours Marks 방정식 error
x y $y_p=6.194x + 16.973$ $y - y_p$ $error^2$
3 35 37.672 -2.672 7.139584
4 50 44.586 5.414 29.3114
5 45 51.5 -6.5 42.25
6 64 58.414 5.586 31.2034
7 66 65.328 0.672 0.451584
8 70 72.242 -2.242 5.026564
SSE=115.3

SSE가 $952$에서 $115.3$으로 오차가 감소했기 때문에 선형 회귀를 사용해 데이터 셋에 최적화된 방정식을 찾을 수 있게 된다.

이제 주중 총 22시간을 공부한 학생의 예상 성적을 유추할 수 있을 것이다.

자바스크립트 ES6 코드 구현

바닐라 ES6로 OLS(최소제곱법)를 사용한 선형회귀함수를 만들어보았다.
따로 math 라이브러리는 사용하지 않았으므로 배열 요소의 총 합(sum), 평균(average)를 구할 수 있는 간단한 utils 함수를 만들었다.


const utils = {
	sum: (arr) => arr.reduce((total, amount) => total + amount),
	avg: (arr) => utils.sum(arr) / arr.length
}

const LinearRegression = (data) => {
	
	let
		x_avg, 		// average of independent variable x
		y_avg, 		// average of dependent variable y
		num, 		  // numerator : Sum of (xi - x)(yi - y)
		den, 	    // denominator : (xi - x)**2
		m, 		    // slope
		b, 		    // intercept
		sse 		  // the sum of squared error: sum of (y - (mx + b))
	
	x_avg = utils.avg(data.x)
	
	y_avg = utils.avg(data.y)
	num = utils.sum(data.x.map((x, i) => (x - x_avg) * (data.y[i] - y_avg)))
	den = utils.sum(data.x.map(x => ((x - x_avg) ** 2)))
	

	if (num === 0 && den === 0) {
		m = 0
		b = data.x[0]
		
	}
	else {
		m = num / den
		b = y_avg - m * x_avg
	}
	
	
	sse = utils.sum(data.y.map((y, i) => (y - (m * data.x[i] + b)) * 2))
	
	return {
		slope: m,
		intercept: b,
		y: `${m}x + ${b}`,
		SSE: `${sse}`
	}
}