본문 바로가기

파이썬/머신러닝

Linear Regression 선형회귀 파이썬 코드 예제 (보스턴 주택 가격 csv 파일)

선형모델은 아주 기초적이고 간단하지만 설명력이 뛰어나고 다른 모델들의 기초가 되는 모델이기 때문에 반드시 알고 넘어가야 하는 것이 좋다.

 

 

중학교 수학시간에 처음 배웠던 함수인 일차함수를 떠올려보자.

 

y = ax + b

 

이 간단한 식에서 가장 중요한 것은 기울기와 절편이다. 기울기와 절편에 따라서 함수의 모양이 달라지고 x값을 넣었을 때 그에 대한 y값이 달라진다. 이런 단순 선형회귀는 우리가 가진 데이터를 가장 잘 설명할 수 있는 기울기와 절편 값을 찾는 것이다.

 

 

선형회귀는 위와 같이 데이터에 단순한 선을 적합시킨다. 당연히 실제 데이터와 선 사이에는 오차가 생기는데, 그 오차가 얼마나 되는지 모든 손실에 제곱을 해서 구하는게 바로 평균제곱오차, MSE(Mean Squared Error)이다. 이 MSE를 최소화하는 최적의 파라미터를 찾는 것이 Linear Regression의 핵심이다.

 

 

다만 사이킷런의 단순 선형회귀는 최소제곱법(Ordinary Least Squares)를 활용해서 max_iterations, learning_rate와 같은 파라미터를 고려할 필요는 없다.

 

*max_iterations : 반복 횟수

*learning_rate : 학습률

만약 학습률이 너무 크다면 파라미터를 듬성듬성 조정하기 때문에 최적의 값을 찾기 어렵고, 반대로 학습률이 너무 작다면 최적의 값에 도달하는데 시간이 오래걸리기 때문에 적절한 값을 찾아주는 것이 중요함

 

 

 

1. 단순 선형회귀

import numpy as np

#무작위로 선형 데이터셋 생성
X = 2 * np.random.rand(100,1)  #rand: 난수 생성 함수
y = 4 +  3 * X + np.random.randn(100,1) #randn은 정규분포에 대한 난수 생성

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split


lin_reg = LinearRegression()
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

lin_reg.fit(X_train, y_train)

print(lin_reg.intercept_)  #편향(절편)
print(lin_reg.coef_)       #가중치
print(lin_reg.score(X_train, y_train)) #train set 점수
print(lin_reg.score(X_test, y_test)) #test set 점수

 

절편을 알고 싶다면 intercept_를, 가중치(기울기)를 알고 싶다면 coef_함수를 사용하면 된다.

 

 

2. 다중 선형회귀

 

실제 현실의 데이터는 단순 선형회귀로 설명되지 않는 것들이 대부분이다. 이번에는 훨씬 더 복잡하고 여러 변수를 갖고 있는 다중 선형회귀에 대해 알아보자.

 

Boston_house.csv
0.03MB

보스턴 주택가격 데이터로 학습시켜봤다. 보스턴 주택가격 데이터는 범죄율, 주택당 방 개수 등의 변수들이 집값에 미치는 영향을 나타낸 데이터이다.

import pandas as pd

boston = pd.read_csv('Boston_house.csv')
boston.head()

CRIM: 범죄율
INDUS: 비소매상업지역 면적 비율
NOX: 일산화질소 농도
RM: 주택당 방 수
LSTAT: 인구 중 하위 계층 비율
B: 인구 중 흑인 비율
PTRATIO: 학생/교사 비율
ZN: 25,000 평방피트를 초과 거주지역 비율
CHAS: 찰스강의 경계에 위치한 경우는 1, 아니면 0
AGE: 1940년 이전에 건축된 주택의 비율
RAD: 방사형 고속도로까지의 거리
DIS: 직업센터의 거리
TAX: 재산세율'''

 

 

이 중에서 범죄율, 주택당 방 수, 인구 중 하위 계층 비율, 노후 주택 비율과 주택가격과의 상관관계를 예측해보자.

 

from sklearn.model_selection import train_test_split

X = boston[['CRIM','RM', 'LSTAT', 'AGE']]
y = boston[['Target']]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

from sklearn.linear_model import LinearRegression

reg = LinearRegression()
reg.fit(X_train, y_train)
y_pred = reg.predict(X_test)
import matplotlib.pyplot as plt
%matplotlib inline

#실제 주택값과 예측한 주택값 간의 상관관계

plt.scatter(y_test, y_pred, alpha=0.4)
plt.xlabel("Actual Price")
plt.ylabel("Predicted Price")
plt.title("LINEAR REGRESSION")
plt.show()

예측값과 실제값의 상관관계를 그림으로 표현해보면 몇몇 outlier들이 있지만 전체적으로 선형의 모습을 보이고 있어 꽤나 잘 들어맞는 것으로 보인다. 

 

reg.coef_
>>>array([[-0.1298062 ,  5.45294513, -0.60480624,  0.0171971 ]])

coef_값을 구해보면 RM(주택당 방 수)의 가중치가 가장 높다. 이말은 즉 RM이 보스턴 주택가격에 미치는 영향이 가장 높다고 해석할 수 있다. 각각의 변수와 주택가격 간의 상관관계를 직접 눈으로 확인해보자.

 

plt.scatter(boston[['CRIM']], boston[['Target']], alpha=0.4)
plt.show()

 

plt.scatter(boston[['RM']], boston[['Target']], alpha=0.4)
plt.show()

plt.scatter(boston[['LSTAT']], boston[['Target']], alpha=0.4)
plt.show()

plt.scatter(boston[['AGE']], boston[['Target']], alpha=0.4)
plt.show()

 

 

확실히 범죄율과 노후 주택 수는 주택가격과 상관관계가 없어보이고, 방 개수가 가장 큰 양의 상관관계를 보인다. 인구 중 하위 계층 비율은 주택가격과는 음의 상관관계를 보인다.

 

reg.score(X_train, y_train) #train set R^2 점수
>>>0.6633348861314412

reg.score(X_test, y_test) #test set R^2 점수
>>>0.5564675983574296

R² 값을 제공하는 score함수로 train set과 test set의 점수를 구해보면 성능이 그리 좋지는 않다. 4개 변수 중 2개 변수만 설명력이 있기 때문에 어찌보면 당연한 결과이기도 하다. 아무튼 다중선형회귀는 이런식으로 만들면 된다는거! 사실 제대로 하려면 먼저 데이터 전처리 과정도 필요하고 성능 검증도 좀 더 정교하게 해야 하지만 일단 오늘은 여기까지 ㅎㅎ