05-04. 사이킷런 LinearRegression을 이용한 보스턴 주택 가격 예측

Park Jong Hun·2021년 2월 25일
0

위키북스의 파이썬 머신러닝 완벽 가이드 책을 토대로 공부한 내용입니다.


1. LinearRegression 클래스 - Ordinary Least Squares


LinearRegression 클래스는 예측값과 실제 값의 RSS(Residual Sum of Squares)를 최소화해 OLS(Ordinary Least Squares) 추정 방식으로 구현한 클래스이며, fit() method로 X, y 배열을 입력 받으면 회귀 계수(Coefficients)인 W를 coef_ 속성에 저장한다.

 class sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=Flase, copy_X=True, n_jobs=1)
  • 입력 파라미터
    • fit_intercept : boolean 값으로 default는 True이다. Intercept(절편) 값을 계산할 것인지 말지를 지정하고, 만일 False로 지정하면 intercept가 사용되지 않고 0으로 지정된다.
    • normalize : boolean 값으로 default는 False이다. fit_intercept가 False인 경우에는 이 파라미터가 무시되고, True이면 회귀를 수행하기 전에 입력 dataset을 정규화한다.
  • 속성
    • coef_ : fit() method를 수행했을 때 회귀 계수가 배열 형태로 저장하는 속성이며, Shape은 (Targt 값 개수, feature 개수)이다.
    • intercept_ : intercept 값

Ordinary Least Squares 기반의 회귀 계수 계산은 입력 feature의 독립성에 많은 영향을 받는다. feature 간의 상관관계가 매우 높은 경우 분산이 커져서 오류에 매우 민감해진다. 이러한 현상으 공신성(multi-collinearity) 문제라고 한다. 일반적으로 상관관계가 높은 feature가 많은 경우 독립적인 중요한 feature만 남기고 제거하거나 규제를 적용한다. 또한 매우 많은 feature가 다중 공선성 문제를 가지고 있다면 PCA를 통해 차원 축소를 수행하는 것도 고려해 볼 수 있다.


2. 회귀 평가 지표


회귀의 평가를 위한 지표는 실제 값과 예측 값의 차이를 기반으로 한 지표가 중심이다.

평가 지표설명수식
MAE
Mean Absolute Error이며 실제 값과
예측 값의 차이를 절댓값으로 변환해
평균한 것이다.
 MAE=1ni=1nYiYi^MAE={1 \over n}\sum_{i=1}^n \left\vert Y_i- \hat{Y_i} \right\vert
MSE
Mean Squared Error이며 실제 값과
예측 값의 차이를 제곱해 평균한
것이다.
 MSE=1ni=1n(YiYi^)2MSE={1 \over n}\sum_{i=1}^n (Y_i- \hat{Y_i})^2
RMSE
MSE 값은 오류의 제곱을 구하므로 실제
오류 평균보다 더 커지는 특성이
있으므로 MSE에 루트를 씌운 것이
Root Mean Squared Error이다.
 RMSE=1ni=1n(YiYi^)2RMSE=\sqrt{{1 \over n}\sum_{i=1}^n (Y_i- \hat{Y_i})^2}
R2^2
분산 기반으로 예측 성능을 평가한다.
실제 값의 분산 대비 예측값의 분산
비율을 지표로 하며, 1에 가까울수록
예측 정확도가 높다.
 R2=예측값 Variance실제값 VarianceR^2={예측값 \ Variance \over 실제값 \ Variance}

이 밖에 MSE나 RMSE에 로그를 적용한 MSLE(Mean Squared Log Error)와 RMSLE(Root Mean Squared Log Error)도 사용한다.


3. LinearRegression을 이용해 보스턴 주택 가격 회귀 구현


사이킷런은 보스턴 주택 가격 dataset을 load_boston()을 통해 제공한다. 각 feature의 의미를 설명한 후 dataset을 로드하고 DataFrame으로 변경하겠다.

  • feature 설명
    • CRIM: 지역별 범죄 발생률
    • ZN: 25,000평방피트를 초과하는 거주 지역의 비율
    • NDUS: 비상업 지역 넓이 비율
    • CHAS: 찰스강에 대한 더미 변수(강의 경계에 위치한 경우는 1, 아니면 0)
    • NOX: 일산화질소 농도
    • RM: 거주할 수 있는 방 개수
    • AGE: 1940년 이전에 건축된 소유 주택의 비율
    • DIS: 5개 주요 고용센터까지의 가중 거리
    • RAD: 고속도로 접근 용이도
    • TAX: 10,000달러당 재산세율
    • PTRATIO: 지역의 교사와 학생 수 비율
    • B: 지역의 흑인 거주 비율
    • LSTAT: 하위 계층의 비율
    • MEDV: 본인 소유의 주택 가격(중앙값)
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
print('Boston 데이타셋 크기 :',bostonDF.shape)
bostonDF.head()

[output] dataset의 feature는 Null 값은 없으며, 모두 float 형이다. 그 다음 각 feature(column)이 회귀 결과에 미치는 영향이 어느 정도인지 시각화해서 알아보겠다.

# 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])

[output] 다른 feature보다 RM과 LSTAT의 PRICE 영향도가 가장 두드러지게 나타난다. RM(방 개수)는 양 방향의 선형성(Positive Linearity)이 가장 크다. 즉, 방의 크기가 클수록 가격이 증가하는 모습을 확연히 보여준다. LSTAT(하위 계층 비율)는 음 방향으 선형성(Negative Linearity)이 가장 크다. 이제 LinearRegression 클래스를 이용하여 보스턴 주택 가격의 회귀 모델을 만들어 학습/예측을 수행한 후 MSE와 R2 Score를 측정하겠다.

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)))

[output] coef_ 속성은 회귀 계수 값만 가지고 있으므로 feature 별 회귀 계수를 높은 값으로 출력해보겠다.

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

[output] RM이 양의 값으로 회귀 계수가 가장 크며, NOX feature의 회귀 계수 - 값이 가장 크게 나온다. 교차 검증을 통해 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))

[output]

profile
NLP, AI, LLM, MLops

0개의 댓글