머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug

회귀는 지도학습의 또다른 유형 중 하나이다. 보스턴 지역의 주택가격을 예측하는 모델을 만들어보자!

1. 데이터 로딩

보스턴 주색 데이터셋은 14개의 변수(열)로 구성된다. 각 열은 주택의 속성을 나타내는 피처를 말하고, 각 행은 개별 주택에 대한 데이터의 집합(레코드)를 나타낸다. 하나의 행이 하나의 샘플(주택)을 나타내고, 각 열에 맞춰 해당하는 데이터가 입력되어 있다. 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

#보스턴 주택 데이터셋
from sklearn import datasets
housing = datasets.load_boston()

#key 값 확인mport pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

#보스턴 주택 데이터셋
from sklearn import datasets
housing = datasets.load_boston()

#key 값 확인
housing.keys()
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
key값 확인

보스턴 주택 데이터셋도 붓꽃처럼 사이킷런이 제공하는 데이터셋에 포함되어 있다. load_boston()을 이용해 보스턴 데이터셋을 불러왔고, key값도 확인해보았다.

머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
데이터프레임으로 변환

이전과 동일하게 DataFrame()을 이용해 데이터프레임으로 변환해주었다. 13가지 피처 데이터가 들어있는 2차원구조(506행, 13열)이 됐으며, 목표변수 데이터를 데이터프레임으로 변환하고 열 이름을 'Target'으로 설정했다.

머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
데이터프레임 결합

data 데이터프레임과 target 데이터프레임을 결합한다. concat()에 axis=1 옵션을 사용해 좌우 방향으로 연결하듯 붙여줬다.

2. 데이터 탐색

2-1. 기본 정보

머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
info

info()를 사용해 데이터프레임의 기본정보를 확인해봤다. 모든 열이 506개의 유효값을 갖고 있으면, 자료형은 64비트 실수형임을 알 수 있다. 모든 데이터값이 숫자로만 이루어져 있기 때문에, 머신러닝 알고리즘에 바로 입력해 계산이 가능하다.

2-2. 결측값 확인

머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결측값

결측값 없음!

2-3. 상관 관계 분석

#상관 관계 행렬
df_corr=df.corr()

#히트맵
plt.figure(figsize=(10,10))
sns.set(font_scale=0.8)
sns.heatmap(df_corr, annot=True, cbar=False)
plt.show()
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결과창

corr()을 이용해 숫자 데이터를 갖는 변수 간의 상관 계수를 계산했다. heatmap()을 사용해 시각화하였으며, 이미지 크기는 (10,10), 폰트스케일은 0.8로 설정했다. 

머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
상관관계 높은 순으로 출력

목표변수 Target과 상관 계수가 높은 순서대로 출력을 했다. abs()로 상관 계수의 값을 모두 양수로 변경해주었고, sort_values()에 ascending=False 옵션을 적용해 상관 계수 값을 기준으로 내림차순 정렬을 했다.

머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
피처 선택 추출

이젠 데이터분포를 살펴보자! 가장 좋은 방법은 그래프를 그려 시각화 하는 것이 좋다. Target 변수와 함께, 상관 계수 top4 LSTAT, RM, PTRATIO, INDUS를 추출했다. 

※loc 인덱서 짚고 넘어가기※

데이터프레임의 특정 부분을 추출할 때에 loc 인덱서를 사용한다.

형식: loc[행 인덱스, 열 이름]

#regplot으로 선형회귀선 표시
plt.figure(figsize=(10,10))
for idx, col in enumerate(plot_cols[1:]):
  ax1=plt.subplot(2, 2, idx+1)
  sns.regplot(x=col, y=plot_cols[0], data=plot_df, ax=ax1)
plt.show()
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결과 창

사본 regplot 함수로 선형 회귀선을 산점도에 표시할 수 있다.  x변수에는 target을 제외한 4개 피처를, y변수에는 target을 입력한다. subplot()으로 2x2 격자 프레임을 만들어주었다. LSTAT와 RM의 선형관계가 뚜렷하게 나타난다.

2-4. 목표 변수(Target 열) - 주택 가격

머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
Target 데이터분포

Target 열의 주택가격 데이터분포를 displot()으로 그렸다. Target 열은 20을 중신으로 정규분포 형태를 보이며, 최대값에 해당하는 50에 많은 데이터가 분포되어 있는 특이점을 보인다.

3. 데이터 전처리

3-1. 피처 스케일링

각 피처(열)의 데이터 크기에 따른 상대적 영향력의 차이를 제거하기 위해, 피처의 크기를 비슷한 수준으로 맞춰주는 작업이 필요하다. 이 과정을 피처 스케일링(Feature Scaling)이라고 한다.

from sklearn.preprocessing import MinMaxScaler
scaler=MinMaxScaler()

df_scaled=df.iloc[:, :-1]   #마지막열임을 나타내는 -1은 포함하지 않음
scaler.fit(df_scaled)
df_scaled=scaler.transform(df_scaled)

#스케일링 변환된 값을 데이터프레임에 반영
df.iloc[:, :-1]=df_scaled[:, :]
df.head()
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결과창

위는 사이킷런의 MinMaxScaler를 활용한 정규화방법이다. 목표변수 Target을 제외한 나머지 13개 열의 데이터를 iloc 인덱서로 추출한다. 이 데이터를 MinMaxScaler 인스턴스 객체에 fit()으로 각 열의 데이터를 최소값 0, 최대값 1 사이로 변환하는 식을 학습한다. transform()을 사용하면 학습한 변환식을 실제로 적용해 데이터를 정규화 변환한다.

※iloc 인덱서 짚고 넘어가기※

loc인덱서는 인덱스 이름을 사용하지만, iloc 인덱서는 원소의 순서를 나타내는 정수 인덱스(0, 1, 2, ...)를 사용한다. 즉, iloc 인덱서는 행과 열의 위치 순서만 골한다. loc 인덱서는 범위의 끝을 포함하지만, iloc 인덱서는 포함하지 않는다.

3-2. 학습 데이터와 테스트 데이터 분할

#학습데이터와 테스트데이터 분할
from sklearn.model_selection import train_test_split
x_data=df.loc[:, ['LSTAT', 'RM']]
y_data=df.loc[:, 'Target']
x_train, x_test, y_train, y_test=train_test_split(x_data,
                                                  y_data,
                                                  test_size=0.2,
                                                  shuffle=True,
                                                  random_state=12)
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결과창

Target과 상관 계수가 가장 큰 LSTAT와 RM을 학습데이터 x_data로 선택한다. 그리고 506개의 주택 샘플 중 20%를 모델 평가에 사용한다. train_test_split()의 test_size 옵션에 0.2(20%)를 입력하면, 404개의 학습데이터 x_train, y_train과 102개의 테스트 데이터 x_test, y_test로 분할된다. 

4. 베이스라인 모델-선형 회귀

#선형 회귀 모형
from sklearn.linear_model import LinearRegression
lr=LinearRegression()
lr.fit(x_train, y_train)

print("회귀계수(기울기):", np.round(lr.coef_, 1)) #np: numpy, coef_: 피처에 대한 회귀 계수 값
print("상수항(절편):", np.round(lr.intercept_, 1))  #intercept_: 상수항(절편) 값
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결과창

선형 회귀 모델의 예측력은 꽤 좋다. LinearRegression 클래스 객체를 생성하고, fit 메소드에 학습데이터인 x_train. y_train을 입력하면 선형 회귀식을 찾는다.

선형 회귀 모델의 coef_ 속성으로부터 각 피처에 대한 회귀 계수 값을 얻고 intercept_ 속성에서 상수항(절편)값을 얻는다. 이를 통해 LSTAT에 대한 회귀 계수는 -23.2이고, RM에 대한 회귀 계수는 25.4 임을 알 수 있다.

#예측값 저장
y_test_pred=lr.predict(x_test)

#예측값과 실제값의 분포
plt.figure(figsize=(10, 5)) #표 크기 지정
plt.scatter(x_test['LSTAT'], y_test, label='y_test')  #파란점, 실제값
plt.scatter(x_test['LSTAT'], y_test_pred, c='r', label='y_pred')  #빨간점, 예측값
plt.legend(loc='best')  #범례(오른쪽 상단 박스)가 표시되는 위치 지정
plt.show()
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결과창

예측값(y_test_pred)와 실제값(y_test)의 분포를 확인해보았다.

y_test_pred: 목표변수인 Target에 대한 예측값 (predict 함수에 테스트 데이터 x_test 입력)

맷플롯립의 scatter 함수를 이용해보았다. x축 값과 y축 값을 순서대로 입력한 뒤, 범례에 표시할 값을 lable 옵션에 지정했다. (-c : 색상 지정 옵션)

legend(): 범례를 표시하는 명령 (loc 옵션: 범례가 표시되는 위치를 지정, best/right/left 등)

5. 모델 성능 평가

예측값과 실제값의 오차는 꽤 있는 편이다.

잔차(residuals): 실제값(정답)과 예측값의 차이로, 값이 작을 수록 모델의 성능이 좋다.

모델 성능을 평가할 때에는 수치화된 성능 지표를 사용한다. 회귀모델의 성능을 평가하는 지표는 MAE, MSE, RMSE 등이 있다. 사이킷런의 metrics 모듈에는 다양한 성능 평가 지표가 정의 되어 있다. 

구분 설명
MAE(Mean Absolute Error) 실제값과 예측값의 차이
잔차의 절대값을 평균한 값
MSE(Mean Squared Error) 실제값과 예측값의 차이
잔차의 제곱을 평균한 값
RMSE(Root Mean Squared Error) MSE의 제곱근
#성능 평가
from sklearn.metrics import mean_squared_error
y_train_pred=lr.predict(x_train)

train_mse=mean_squared_error(y_train, y_train_pred) #훈련 데이터의 평가 점수
print("Train MSE:%.4f" % train_mse)

test_mse=mean_squared_error(y_test, y_test_pred)
print("Test MSE:%.4f" % test_mse)
머신러닝 보스턴 집값 예측 - meosinleoning boseuteon jibgabs yecheug
결과창

mean_squared_error(): 테스트오차(Test MSE)를 계산하는 함수

평가 지표 함수에 테스트 데이터의 실제값(y_test)와 예측값(y_test_pred)를 입력한다. 비교를 위해 훈련 데이터의 평가 점수인 Train MSE도 계산했다.

결과를 보면 Train MSE는 30.8, Test MSE는 29.5의 결과가 나왔다.