본문 바로가기

파이썬 머신러닝 완벽가이드

5.2 LinearRegression을 이용한 보스턴 주택 가격 예측

728x90

이번 시간에는 지난 시간에 이야기했듯이 회귀 라이브러리를 이용하여

보스턴 주택 가격 예측을 진행해보도록 하겠습니다.

 

해당 내용은 '파이썬 머신러닝 완벽가이드'를 정리한 내용입니다.


1. LinearRegression 클래스

먼저 LinearRegression 클래스에 대해서 살펴보도록 하겠습니다. 주요 파라미터는 다음과 같습니다.

 

fit_intercept : 회귀 모델의 절편 값을 계산할 것인지 말지를 결정

normalize : 입력 데이터 세트를 정규화할 것인지 결정

coef_ : 회귀 계수가 배열 형태로 저장

intercept_ : intercept 값

 

LinearRegression 클래스와 같은 Ordinary Least Squares 기반의 회귀 모델은 입력 피처의 독립성에 영향을 많이 받습니다. 즉, 피처 간의 상관관계가 매우 큰 경우 오류에 상당히 민감해집니다. 이를 다중 공선성(multi-collinearity)라고 합니다. 상관관계가 높은 피처가 많은 경우 규제를 사용하거나 PCA를 통해 차원 축소를 고려합니다. 이에대한 자세한 내용은 뒤에서 좀 더 다루도록 하겠습니다.

 

2. 회귀 평가 지표

다음은 일반적으로 회귀 모델을 평가하는데 사용되는 회귀 평가 지표입니다.

하지만 사이킷런에서는 RMSE를 제공하지 않습니다. 다음은 사이킷런에서 제공하는 회귀 평가 지표입니다.

위 평가 지표에서 확인해야될 것은 바로 Scoring 함수 적용 값에 대한 것입니다. 해당 값들을 살펴보면 'neg_'라는 값이 붙은 것을 볼 수 있습니다. 이는 기존 MAE, MSE 값에 음수(-1)를 곱한다는 의미인데 이는 cross_val_score, GridSearchCV와 같은 Scoring함수가 score값이 크면 클 수록 좋은 평가 결과로 평가되기 때문입니다. 하지만 회귀에서는 오류값이 클수록 좋은 평가 지표로 연결되면 안되겠죠? 따라서 음수(-1)를 곱해주는 것입니다.

3. 보스턴 주택 가격 회귀 구현

이제 본격적으로 실제 데이터에 회귀를 적용해보도록 하겠습니다. 먼저 데이터를 로드하고 이를 데이터프레임으로 변환하도록 하겠습니다.

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from scipy import stats
from sklearn.datasets import load_boston
%matplotlib inline

# boston 데이타셋 로드
boston = load_boston()

# boston 데이타셋 DataFrame 변환 
bostonDF = pd.DataFrame(boston.data , columns = boston.feature_names)

# boston dataset의 target array는 주택 가격임. 이를 PRICE 컬럼으로 DataFrame에 추가함. 
bostonDF['PRICE'] = boston.target
bostonDF.head()

 

 

모두 float형식으로 null값이 없는 것을 확인할 수 있습니다. 그럼 각각의 피처와 결정값 사이의 상관관계를 살펴보도록 하겠습니다.

 

# 2개의 행과 4개의 열을 가진 subplots를 이용. axs는 4x2개의 ax를 가짐.
fig, axs = plt.subplots(figsize=(16,8) , ncols=4 , nrows=2)
lm_features = ['RM','ZN','INDUS','NOX','AGE','PTRATIO','LSTAT','RAD']
for i , feature in enumerate(lm_features):
    row = int(i/4)
    col = i%4
    # 시본의 regplot을 이용해 산점도와 선형 회귀 직선을 함께 표현
    sns.regplot(x=feature , y='PRICE',data=bostonDF , ax=axs[row][col])

 

상관관계 그래프를 보면 RM, LSTAT가 결정값과 비교적 확실한 상관관계를 보여줌을 확인할 수 있습니다.

이를 바탕으로 학습을 진행하고 회귀 계수를 구한 후, 평가를 진행하도록 하겠습니다.

 

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error , r2_score

y_target = bostonDF['PRICE']
X_data = bostonDF.drop(['PRICE'],axis=1,inplace=False)

X_train , X_test , y_train , y_test = train_test_split(X_data , y_target ,test_size=0.3, random_state=156)

# Linear Regression OLS로 학습/예측/평가 수행. 
lr = LinearRegression()
lr.fit(X_train ,y_train )
y_preds = lr.predict(X_test)
mse = mean_squared_error(y_test, y_preds)
rmse = np.sqrt(mse)

print('MSE : {0:.3f} , RMSE : {1:.3F}'.format(mse , rmse))
print('Variance score : {0:.3f}'.format(r2_score(y_test, y_preds)))

 

MSE : 17.297 , RMSE : 4.159
Variance score : 0.757

 

평가 결과를 보면 0.757로 썩 만족스러운 결과는 아니군요...

우선 구해진 회귀 계수를 확인해보겠습다.

 

print('절편 값:',lr.intercept_)
print('회귀 계수값:', np.round(lr.coef_, 1))

 

절편 값: 40.995595172165
회귀 계수값: [ -0.1   0.1   0.    3.  -19.8   3.4   0.   -1.7   0.4  -0.   -0.9   0.
  -0.6]

 

배열로된 회귀계수를 각 피쳐와 맵핑하여 정렬하도록 하겠습니다.

# 회귀 계수를 큰 값 순으로 정렬하기 위해 Series로 생성. index가 컬럼명에 유의
coeff = pd.Series(data=np.round(lr.coef_, 1), index=X_data.columns )
coeff.sort_values(ascending=False)

 

결과를 보면 NOX가 매우 높은 회귀 계수 음의 값이 매우 큰 것을 볼 수 있습니다. 이는 나중에 최적화하도록 하겠습니다.

 

다음은 5개의 폴드 세트에서 교차 검증을 통해 MSE, RMSE를 측정해보겠습니다.

from sklearn.model_selection import cross_val_score

y_target = bostonDF['PRICE']
X_data = bostonDF.drop(['PRICE'],axis=1,inplace=False)
lr = LinearRegression()

# cross_val_score( )로 5 Fold 셋으로 MSE 를 구한 뒤 이를 기반으로 다시  RMSE 구함. 
neg_mse_scores = cross_val_score(lr, X_data, y_target, scoring="neg_mean_squared_error", cv = 5)
rmse_scores  = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)

# cross_val_score(scoring="neg_mean_squared_error")로 반환된 값은 모두 음수 
print(' 5 folds 의 개별 Negative MSE scores: ', np.round(neg_mse_scores, 2))
print(' 5 folds 의 개별 RMSE scores : ', np.round(rmse_scores, 2))
print(' 5 folds 의 평균 RMSE : {0:.3f} '.format(avg_rmse))

 

5 folds 의 개별 Negative MSE scores:  [-12.46 -26.05 -33.07 -80.76 -33.31]
 5 folds 의 개별 RMSE scores :  [3.53 5.1  5.75 8.99 5.77]
 5 folds 의 평균 RMSE : 5.829

이번 시간에는 우선 단순하게 실제 데이터에서 회귀 모델을 구해보는 과정을 

살펴봤습니다. 아직 이것만으로는 회귀가 어디에 사용되고 어떤게 

좋은 회귀모델인지 감이 안오는군요... 뒤에서 최적화 등 

더 자세히 살펴봐야될꺼 같아요...

반응형