[Tensorflow] 2-1 Regression with Boston housing datasets

2023. 1. 7. 01:55·AI/Deep Learning

이번 포스팅에서는 보스턴 하우징이라는 유명한 데이터셋에 저번 포스팅에서 공부한 회귀분석을 통해 분석해보려고 합니다

0. Set Environment and Prepare Data (환경설정 및 데이터준비)

보스턴 주택 가격 데이터셋은 1978년에 발표된 데이터로 주택가격을 포함한 여러가지 변수를 담고 있는 데이터셋 입니다.

참고로 데이터는 14개의 변수를 포함하고 있으며 504개의 샘플을 포함하고 있으며 각 변수와 설명은 아래 표를 참고하면 됩니다.

 

CRIM 자치시(town) 별 1인당 범죄율(%) DIS 5개의 보스턴 직업센터까지의 접근성 지수
ZN 25,000 평방피트를 초과하는 거주지역의 비율 RAD 방사형 도로까지의 접근성 지수
INDUS 비소매 상업 지역이 점유하고 있는 토지의 비율 TAX 10,000 달러 당 재산세율
CHAS 찰스강에 대한 더미변수
(강의 경계에 위치한 경우는 1, 아니면 0)
PTRATIO 자치시(town)별 학생/교사 비율
NOX 10ppm 당 농축 일산화질소 B 1000(Bk-0.63)^2
(여기서 Bk는 자치시별 흑인의 비율을 말함)
RM 주택 1가구당 평균 방의 개수 LSTAT 모집단의 하위계층의 비율(%)
AGE 1940년 이전에 건축된 소유주택의 비율 MEDV 본인 소유의 주택가격(중앙값) (단위: 1,000달러)

이번 분석에서 하고자 하는것은 다른 변수들을 이용해서 주택가격을 예측하는건데요!

만약 모든 변수를 사용하고자 하면 MEDV를 종속변수(Y)로 MEDV외의 13개의 변수들을 독립변수(X)로 놓으면 되겠죠?

선형회귀는 머신러닝 챕터로 코드를 작성하지는 않았지만 단순선형회귀분석을 모델링하고자 하면 다음과 같이 설정할 수 있겠습니다!

$$ \widehat{Y} = \sum_{i=1}^{13}(a_iX_i)+b = a_1X_1 + a_2X_2 + \cdots + a_{13}X_{13} + b $$

 

 

분석에 사용한 데이터는 캐글에서 다운로드 할 수 있습니다.

(https://www.kaggle.com/datasets/vikrishnan/boston-house-prices?resource=download)

해당 링크를 누르면 아래와 같은 화면이 보이는데 다운로드 로고를 누르면 됩니다.

 

 

작업하기 편한 폴더에 데이터를 옮겨주기 위해 OS 모듈을 사용하였습니다.

os.getcwd 함수는 get current working directory의 약자로 현재 작업하는 디렉토리가 어딘지 확인하는 코드입니다.

해당 폴더에다가 아까 다운로드 받은 housing.csv를 옮겨주면 분석할 준비는 끝났습니다!

import os
print(os.getcwd())

 

필요한 라이브러리를 불러온 다음 컬럼명 리스트를 생성 후 원하는 데이터를 pd.read_csv를 통해 가지고 왔습니다.

import matplotlib.pyplot as plt
import tensorflow as tf
import pandas as pd
import numpy as np

# column setting and read data
column_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
data = pd.read_csv("housing.csv", header=None, delimiter=r"\s+", names=column_names)

이것으로 기본적인 준비는 끝났습니다!

 

 

1. EDA(Exploratory Data Analysis, 탐색적 데이터 분석)

pd.read_csv 함수를 통해 불러온 데이터는 DataFrame 형식으로 다양한 메서드를 지원하는데요.

여기서는 shape, head, describe 메서드를 통해 형태, 실제 데이터의 생김새, 분포 요약을 살펴보았습니다.

print(data.shape)
data.head()

>> 506개의 행과 14개의 열을 가진 데이터이며 5개의 데이터를 확인할 수 있습니다.

 

# 데이터 분포 요약
data.describe()

  • 14개의 변수들에 대한 요약 통계를 확인할 수 있고 눈에 띄는 점은 ZN변수와 CHAS변수의 대부분이 0으로 이루어져 있네요.
  • 또한, CRIM 변수와 같이 비율로 표시한 데이터 모두  [0, 100] 사이이므로 눈에 보이는 오류는 없다고 생각이 듭니다.
  • 다만, CRIM 변수에서 평균이 3.6, 표준편차가 8.6인데 최댓값이 88.79로 상당히 멀리 떨어져 있습니다. 이런 데이터는 선형회귀분석시 제거해야 좀 더 성능이 좋은 모델을 만들 수 있습니다.

 

 

다음은 seaborn 모듈을 통해 전체 데이터를 시각화 했습니다. 이때 변수가 값의 규모의 차이가 큰 것을 확인할 수 있는데, ML/DL에서는 이를 정규화 시켜주면 좋다고 알려져 있습니다. 따라서 Standardization 또는 Normalization 하는 과정을 포함할 것 입니다.

import seaborn as sns
sns.boxplot(data=data)

 

 

다음은 각 변수를 서로 다른 subplot에서 박스플롯을 생성하였습니다.

수염이후의 점들은 IQR rule에 벗어난 점들로 이상치일 수 있으므로 주의 깊게 처리해야 합니다.

(가능하다면 이상원인을 규명하고 제거하도록 노력해야합니다.)

import seaborn as sns
import matplotlib.pyplot as plt
from scipy import stats

fig, axs = plt.subplots(ncols=7, nrows=2, figsize=(20, 10))
index = 0; axs = axs.flatten()
for val_name, val_data in data.items():
    sns.boxplot(y=val_name, data=data, ax=axs[index])
    index = index + 1
    
plt.tight_layout(pad=20, w_pad=2, h_pad=2)

  • CHAS 변수는 찰스강 경계에 위치한지를 나타내는 변수로 0과 1로 이루어져 있습니다. 따라서 박스플랏에 보이는 점들을 이상치로 처리하면 안됩니다.

 

간단한 EDA(Exploratory Data Analysis, 탐색적 데이터 분석)을 통해 각 변수들 간 어떤 관계가 있는지 시각화 하였습니다.

개인적으로 궁금한 변수들과 주택가격을 시각적으로 확인하였습니다.

plt.figure(figsize=(16,4))
plt.subplot(1,3,1)
sns.scatterplot(y="MEDV", x="LSTAT", data=data)

plt.subplot(1,3,2)
sns.scatterplot(y="MEDV", x="CRIM", data=data)

plt.subplot(1,3,3)
sns.barplot(y="MEDV", x="CHAS", data=data)
plt.show()

  • LSATA은 하위계층의 비율입니다. 해당 자치구에 하위계층이 많으면 주택가격이 내려가는 경향을 확인할 수 있습니다.
  • CRIM은 1인당 범죄율로 범죄율이 높을수록 주택가격이 내려가는 경향이 존재합니다.
  • CHAS는 찰스강 관련 변수로 0이면 찰스강 경계에 있지 않으며 1이면 찰스경 경계에 위치하고 있다는 뜻입니다. 우리나라에서 한강이 보이는 주택가격이 높은 것처럼 찰스강 경계에 있으면 주택가격이 높은 경향을 보였습니다.

찰스강https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Longfellow_pru.jpg/440px-Longfellow_pru.jpg

 

 

마지막으로 상관관계를 시각화하였습니다.

A와 B의 correlation의 절대적인 수치가 높을수록 한쪽이 커지면 다른쪽도 변화할 가능성이 큽니다.

선형회귀 분석시 다중공산성의 문제가 있으므로 Feature Selection와 같은 방법을 통해 처리하는 것이 중요합니다.

# 상관관계 시각화
plt.figure(figsize=(15,10))
sns.heatmap(data.corr().abs(), annot=True)
plt.show()

  • RAD 변수와 TAX 변수의 상관계수의 절댓값이 0.91로 매우 높은 것을 확인 할 수 있습니다.

 

 

2. 신경망 네트워크를 이용한 회귀분석

본격적으로 회귀분석을 수행하여 봅시다.

참고로 딥러닝에서는 이상치에 비교적 덜 민감한것으로 알려져 있으므로 따로 이상치(Outlier)를 진행하지 않았습니다.

이상치를 제거하면 성능차이가 발생할 수 있으므로 클랜징 전후를 비교하고 싶으신 분들은 추가로 분석하셔도 좋을 것 같습니다.

 

앞서 EDA에서 각 변수의 데이터 값의 규모가 차이가 컸던것을 기억하시나요?

TAX 변수는 평균이 300인데 CHAS 변수같은 경우에는 평균이 0.06정도로 규모의 차이가 존재합니다.

딥러닝을 진행할때 이렇게 규모가 차이나는 데이터를 적절하게 처리하는 과정이 필요합니다.

그 이유는 값 자체가 큰 변수들이 딥러닝 네트워크에 더 큰 영향을 줄 가능성이 존재하며 Local Minima에 빠질 위험이 있기 때문인데요.

따라서 MinMaxScaler()를 사용하여 Normalization을 진행하였습니다.

from sklearn import preprocessing
sc = preprocessing.MinMaxScaler().fit(data)
data = sc.transform(data)

  • Normalization을 진행한 후 모든 값들이 0과 1사이에 위치한 것을 확인할 수 있습니다.
  • 참고로 Min-Max scaling은 $ (x-x_{min})/(x_{max}-x_{min}) $ 을 통해 구할 수 있습니다.

 

다음으로는 데이터를 Train 데이터와 Test 데이터를 분리하는 것인데요.

Train 데이터는 모델의 학습에 사용되며 Test 데이터는 최종적으로 성능을 평가할 때 사용합니다.

분리하는 이유는 모든 데이터를 학습에 사용하면 추가로 데이터를 구하지 않는 이상 해당 모델이 데이터에 최적화 되어있기에 모델이 좋아서 데이터를 잘 설명하는지 아니면 모델이 데이터에 너무 과도하게 맞춰져서 데이터를 잘 설명하는지 알 수 없기 때문입니다.

 

보통은 데이터를 train, validation, test로 나눕니다.

train 데이터는 모델학습(파라미터 튜닝)에 사용되며 validation 데이터는 하이퍼 파라미터 튜닝 및 모델 선택에 사용됩니다.

또한 모델 선택이 완료되면 train 데이터와 validation 데이터를 합쳐 학습시켜 최종적으로 test 데이터에 적용시키는 과정을 거칩니다.

train_test_split 함수를 통해 데이터를 test 데이터와 train 데이터로 구분하였습니다.

from sklearn.model_selection import train_test_split
y = data[:,-1]
data = data[:, 0:-1]
train_x, test_x, train_y, test_y = train_test_split(data, y, test_size=0.2)

print(train_x.shape)
print(test_x.shape)
print(train_y.shape)
print(test_y.shape)
  • 테스트 데이터의 비율을 0.2로 설정하였습니다.
  • train 데이터의 수는 404개로 전체데이터(506개)의 약 80%입니다.
  • test 데이터의 수는 102개로 전체데이터(506개)의 약 20%입니다.
  • 또한 딥러닝 프레임워크에서 학습할 수 있도록 종속변수(Y), 독립변수(X)를 다른 변수로 설정하였습니다.

 

이때 4개의 레이어를 사용하여 딥러닝 네트워크를 구성하였습니다.

각 레이어의 뉴런의 수는 64, 32, 16으로 점차 줄여나갔으며 활성화함수는 ReLU를 사용하였습니다.

또한 최적화기는 Adam을 사용하였으며 손실함수는 연속형 변수를 예측하는 것이 목적이므로 MSE를 사용하였습니다.

model = tf.keras.Sequential([
    tf.keras.layers.Dense(units=64, activation="relu", input_shape=(13,)),
    tf.keras.layers.Dense(units=32, activation="relu"),
    tf.keras.layers.Dense(units=16, activation="relu"),
    tf.keras.layers.Dense(units=1)])

model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.05),
              loss = tf.keras.losses.mse)

model.summary()

 

앞서 구분한 데이터인 train_x와 train_y로 모델을 학습시켰습니다.

총 반복수는 50회이고 한번에 처리할 배치(batch)의 크기는 64로 하였습니다.

이때 train 데이터에서 25%를 validation 데이터로 설정하였습니다.

history = model.fit(train_x, train_y, epochs=50, batch_size=64, validation_split=0.25)

  • 50 번째 반복에서 train_data의 손실은 0.0043, validation_data의 손실은 0.0098 입니다.
  • train_data의 손실은 반복할수록 작아지는 경향이 있으므로 검증손실인 validation_data의 손실이 작아질수록 좋습니다.
  • 만일 train loss가 작아질때 validation loss가 증가하면 overfitting(과적합)된 것으로 판단할 수 있습니다.

 

최종적으로 학습에 사용안한 test 데이터를 평가하면 0.008 정도의 손실이 나오는 것을 확인할 수 있습니다.

model.evaluate(test_x, test_y)
pred = model.predict(test_x)
real = test_y
plt.scatter(pred, real)
plt.plot([0,1],[0,1],"r-")
plt.xlabel("Predict")
plt.ylabel("Real value")
plt.show()

그래프를 보면 예측한값과 실제값이 상당히 유사한 것을 알 수 있습니다.

'AI > Deep Learning' 카테고리의 다른 글

[밑시딥1] 챕터 1~4 요약  (0) 2023.03.26
[Tensorflow] 3. 분류 (Classification)  (0) 2023.01.07
[Tensorflow] 2. 회귀(Regression)  (0) 2023.01.05
[Tensorflow] 1. 논리연산을 위한 신경망 네트워크 생성  (0) 2023.01.04
[Tensorflow] 0. 신경망 네트워크의 구성  (0) 2023.01.04
'AI/Deep Learning' 카테고리의 다른 글
  • [밑시딥1] 챕터 1~4 요약
  • [Tensorflow] 3. 분류 (Classification)
  • [Tensorflow] 2. 회귀(Regression)
  • [Tensorflow] 1. 논리연산을 위한 신경망 네트워크 생성
임파카
임파카
[ML & Statistics] 모바일 버전에서 수식 오류가 있어 PC 환경에서 접속하는 것을 권장합니다.
  • 임파카
    무기의 스탯(Stat)
    임파카
  • 전체
    오늘
    어제
    • Study (149)
      • Data Science (44)
        • Modeling (18)
        • Manipulation (21)
        • Visualization (4)
      • Statistics (59)
        • Mathmetical Statistics (53)
        • Categorical DA (1)
      • Web Programming (17)
      • AI (26)
        • Machine Learning (16)
        • Deep Learning (10)
      • 활동 및 프로젝트 (3)
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
임파카
[Tensorflow] 2-1 Regression with Boston housing datasets
상단으로

티스토리툴바