보스턴 주택 가격 예측
- 연속적인 값을 예측하는 회귀 문제이다.
- 1970년대 보스턴 지역의 범죄율, 토지 지역의 비율, 방의 개수 등 정답을 포함한 14개의 특성으로 이루어져 있다.
1. 데이터 다운 및 전처리
from tensorflow.keras.datasets.boston_housing import load_data
# 데이터를 다운받습니다.
(x_train, y_train), (x_test, y_test) = load_data(path='boston_housing.npz',
test_split=0.2,
seed=777)
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
import numpy as np
# 데이터 표준화
mean = np.mean(x_train, axis = 0)
std = np.std(x_train, axis = 0)
x_train = (x_train - mean) / std
x_test = (x_test - mean) / std
# 검증 데이터셋을 만듭니다.
from sklearn.model_selection import train_test_split
x_train, x_val, y_train, y_val = train_test_split(x_train, y_train,
test_size = 0.33,
random_state = 777)
- 범죄율과 같은 값의 특성은 0
1의 값을 가지지만, 방의 개수 같은 값은 39의 값을 가진다. 이러한 스케일 문제
는 신경망의 성능에 큰 영향을 미친다.
- 따라서 신경망 데이터로 넣기 위해서는 각 데이터의 범위가 동일하도록 조정해야 한다.
- 여기에서 사용하는 방법이
표준화Standardization
이다.
2. 모델의 구성
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
model = Sequential()
# 입력 데이터의 형태를 꼭 명시해야 합니다.
# 13차원의 데이터를 입력으로 받고, 64개의 출력을 가지는 첫 번째 Dense 층
model.add(Dense(64, activation = 'relu', input_shape = (13, )))
model.add(Dense(32, activation = 'relu')) # 32개의 출력을 가지는 Dense 층
model.add(Dense(1)) # 하나의 값을 출력합니다.
model.compile(optimizer = 'adam', loss = 'mse', metrics = ['mae'])
history = model.fit(x_train, y_train,
epochs = 300,
validation_data = (x_val, y_val))
print(model.evaluate(x_test, y_test))
# 결과값 : [9.451594831896763, 2.2150924] 평균, 표준편차
- 마지막 Dense층에서
sigmoid
또는 softmax
함수를 사용하지 않는다.
- 정답의 범위가 제한되지 않고, 회귀문제이기 때문이다.
activation
의 인자를 설정하지 않을 경우, 자동으로 linear
로 설정된다.
- 회귀문제에서는 손실 함수를 주로
평균제곱오차MSE:Mean_Absolute_Error
를 사용한다.
- 결과값은 평균 9.45 * 100 달러, 표준편차 2.215 * 100달러로 나왔다. 예상치가 평균 2215달러의 차이를 보인다는 뜻.
3. 모델 학습 및 평가
K-폴드 교차 검증 기법
- 데이터셋을 K개의 그룹(폴드)으로 나눈 후에, 하나의 그룹을 제외한 후 모든 그룹을 학습 데이터로 사용한다.
- 제외한 그룹은 검증 데이터로 사용된다.
- 각 폴드는 학습 데이터셋과 테스트 데이터셋으로 나눈다.
- 각 폴드마다 저장된 모델을 통해 결과를 도출하고, 결과를 평균내어 최종 성능을 검증한다.
- 계층적 K-폴드 교차검증, 임의 분할 교차 검증, 그룹별 교차 검증, LOOCV(Leave-One-Out CV) 등이 있다.
from tensorflow.keras.datasets.boston_housing import load_data
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
import numpy as np
from sklearn.model_selection import KFold
(x_train, y_train), (x_test, y_test) = load_data(path='boston_housing.npz',
test_split=0.2,
seed=777)
# 데이터 표준화
mean = np.mean(x_train, axis = 0)
std = np.std(x_train, axis = 0)
# 여기까진 전부 동일합니다.
x_train = (x_train - mean) / std
x_test = (x_test - mean) / std
#----------------------------------------
# K-Fold를 진행해봅니다.
k = 3
# 주어진 데이터셋을 k만큼 등분합니다.
# 여기서는 3이므로 훈련 데이터셋(404개)를 3등분하여
# 1개는 검증셋으로, 나머지 2개는 훈련셋으로 활용합니다.
kfold = KFold(n_splits=k, random_state = 777)
# 재사용을 위해 모델을 반환하는 함수를 정의합니다.
def get_model():
model = Sequential()
model.add(Dense(64, activation = 'relu', input_shape = (13, )))
model.add(Dense(32, activation = 'relu'))
model.add(Dense(1))
model.compile(optimizer = 'adam', loss = 'mse', metrics = ['mae'])
return model
mae_list = [] # 테스트셋을 평가한 후 결과 mae를 담을 리스트를 선언합니다.
# k번 진행합니다.
for train_index, val_index in kfold.split(x_train):
# 해당 인덱스는 무작위로 생성됩니다.
# 무작위로 생성해주는 것은 과대적합을 피할 수 있는 좋은 방법입니다.
x_train_fold, x_val_fold = x_train[train_index], x_train[val_index]
y_train_fold, y_val_fold = y_train[train_index], y_train[val_index]
# 모델을 불러옵니다.
model = get_model()
model.fit(x_train_fold, y_train_fold, epochs = 300, validation_data = (x_val_fold, y_val_fold))
_, test_mae = model.evaluate(x_test, y_test)
mae_list.append(test_mae)
K-폴드 결과 확인하기
print(mae_list)
print(np.mean(mae_list))
결과
[2.0994895, 2.1043642, 2.1410992]
2.1149843
- 이전의 2215달러의 표준편차보다 낮은, 2114달러 표준편차 값을 보이므로 성능이 향상되었음을 알 수 있다.