본문 바로가기
데이터 과학 관련 스터디/모두의 딥러닝

[모두의 딥러닝] 3장 가장 훌륭한 예측선 긋기 : 선형 회귀

by inhovation97 2020. 4. 23.

3장관련 포스팅입니다. 오늘은 드디어 통계학의 꽃이라고 불리는 회귀와 관련된 얘기를 해보겠습니다.

그 중에서도 선형 회귀에 대한 얘기를 할 거예요.

우선 회귀는 독립 변수와 종속 변수간의 관계를 가장 잘 설명해주는 식을 세워 데이터를 예측하는게 최대 목표예요.

근데 회귀라는 말부터가 직관적으로 와닿지가 않죠.

책에서도 딥러닝의 모델을 구현하기 위해서는 그 원리를 알고있는 것이 굉장히 중요하다고 강조하고 있기 때문에 우리는 꼭 한 번쯤은 자세히 이해할 필요가 있어요.

저도 맨 처음에 학교에서 회귀를 처음 접했을 때는, 사전에 회귀라는 단어를 가장 먼저 검색했던게 기억이 나는데, 사전적 의미를 보고도 이해를 못했었어요. 지금 검색해보니 회귀(regression)라고 붙인 이유까지 자세히 나와있네요.

선형 회귀는 크게 단순 선형 회귀(simple linear regression)와 다중 선형 회귀(multiple linear regression)가 있습니다.

책에서 드는 예시로 설명하자면, 학생들의 중간고사 성적을 종속 변수 Y, 이에 영향을 주는 독립 변수를 X 라고 합시다.

학생들의 중간고사 성적을 결정하는 요인은 많을 거예요. 공부한 시간, 이전의 성적, 각 학생들의 사교육비 등등...

이러한 많은 요인들 중에서도, 공부한 시간 하나만을 중간고사 성적과의 관계를 나타내는 식이 바로 단순 선형 회귀이고, 2개 이상의 여러 요인을 중간고사 성적과 관계를 나타내는 식이 다중 선형 회귀인 것이죠.

오늘은 이 중에서도 더 쉬운 단순 선형 회귀(simple linear regression)를 파이썬으로 수식도 세워보며 살펴볼게요.

 

X축이 공부한 시간 Y축이 중간고사 성적입니다.

데이터가 매우 작지만, 비례관계로 회귀선을 그을 수는 있을거 같아요. 이제 여기서 고민인 것입니다. X-Y 의 관계를 가장 잘 나타낼 수 있는 주황색 회귀선을 어떤 기준으로 어떻게 그으면 될까?

가장 좋은 y= ax+b식을 세울 수 있는 방법이 고민인거죠.

미지수 a와 b를 구해야 하는데,우리는 바로 '최소 제곱법(method of least squares)'을 통해서 최적의 회귀식을 세워 a와 b를 구할 것입니다.

 

 

 

최소 제곱법(method of least squares)

오직 독립 변수 X가 1개인 단순 선형 회귀에서만 적용할 수 있습니다. 식을 보면 기울기 a를 구하는 식이니까 순간 변화율의 개념이 보입니다.

 

 

<최소 제곱법 코딩>

# import numpy as np # 연산을 위해 넘파이를 임포트 해줍니다.

x=[2,4,6,8]         # x,y 리스트 생성
y=[81,93,91,97]

mx = np.mean(x)     # 각각 x,y의 평균임
my = np.mean(y)

divisor = sum([(i-mx)**2 for i in x]) # 기울기 a의 분모식

def top (x, mx, y, my):               # 기울기 a의 분자식
    d=0
    for i in range(len(x)):
        d+=(x[i]-mx )*(y[i]-my)
    return d
dividend = top(x,mx,y,my)

a= dividend/divisor
b= my-(mx*a)

print('기울기 a =',a)
print('y절편 b=', b)
기울기 a = 2.3

y절편 b= 79.0

 

 

 

이번에는 평균 제곱 오차(mean square error, MSE)를 살펴볼게요.

회귀 모델을 평가하는 방법은 꽤나 많이 있는데 그 중 하나가 바로 평균 제곱 오차입니다. 우리는 항상 가장 나은 회귀선을 긋기 위해 노력해야한다고 말했어요. 그리고 그 방법 중에 하나가 위에서 말한 최소 제곱법입니다. 하지만 대부분의 데이터셋은 변수가 여러개고, 우리가 만든 회귀선들 중에서 어떤게 가장 뛰어난 회귀선인지 가늠할 지표가 필요하죠. 그때, 평균 제곱 오차를 이용합니다. 식을 살펴보면 이해가 될텐데, 예측값-참값을 제곱해서 다 더합니다. 굉장히 간단한 식이죠? 보통 코딩할 때는 계산에 속도 때문에 아래 RMSE 루트 씌운걸 쓰기도 합니다. 어떤걸 쓰던지 상관은 없어요. 그저 각각의 개체값들이 우리가 예상한 예측치와 평균적으로 어느정도 벗어나 있는지를 알려주는 지표니까요.

<평균 제곱 오차 코딩>

fake_a_b = [3, 76]                      # 기울기 a를 3, y절편 b를 76 이라고 가정합니다.
data = [[2,81],[4,93],[6,91],[8,97]]

x=[i[0] for i in data]
y=[i[1] for i in data]

def predict(x):                         # 3x+76=y 회귀식
    return fake_a_b[0]*x + fake_a_b[1]

def mse(y_hat, y):
    return (((y_hat-y)** 2).mean())    #mse이 도출식

def mse_val(predict_result, y):
    return mse(np,array(predict_result), np.array(y))

predict_result = []

for i in range(len(x)):
    predict_result.append(predict(x[i]))
    print("공부시간=%.f, 실제 점수=%.f,예측 점수=%.f",(x[i],y[i],predict(x[i])))
공부시간=%.f, 실제 점수=%.f,예측 점수=%.f (2, 81, 82)
공부시간=%.f, 실제 점수=%.f,예측 점수=%.f (4, 93, 88)
공부시간=%.f, 실제 점수=%.f,예측 점수=%.f (6, 91, 94)
공부시간=%.f, 실제 점수=%.f,예측 점수=%.f (8, 97, 100)

댓글