- 이번 글에서는 1970년 중반 보스턴 외곽 지역의 범죄율, 지방세율, 주택가격 데이터셋을 활용하여 주택가격을 예측해보는 회귀모델을 구현해보겠습니다.
교재 홍보
- 다음의 교재의 내용을 참고하였습니다.
- 교재 구매 : https://www.yes24.com/Product/Goods/112012471
케라스 창시자에게 배우는 딥러닝 개정 2판 - 예스24
단어 하나, 코드 한 줄 버릴 것이 없다!단 한 권의 딥러닝 책을 선택한다면 바로 이 책이다!케라스 창시자이자 구글 딥러닝 연구원인 저자는 ‘인공 지능의 민주화’를 강조한다. 이 책 역시 많
www.yes24.com
1. 데이터 생성
- Boston 데이터를 가져와 훈련데이터와 테스트 데이터로 분할해 줍니다. 이때 target은 주택의 중간 가격을 의미합니다.
from tensorflow.keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
- 훈련 데이터와 테스트 데이터가 다음과 같이 나뉨을 볼 수 있습니다. 13개의 특성에는 1인당 범죄율, 지방세율, 고속도로 접근성등이 포함되어 있습니다.
train_data.shape, test_data.shape

2. 데이터 전처리
- 각 특성은 다른 단위의 값들을 가지고 있어 모델의 학습에서 스케일이 큰 특성이 보다 영향을 끼치므로 특성별로 표준화를 진행해 줍니다.
- 이때 테스트 데이터의 표준화에 훈련 데이터의 평균과 표준편차를 사용합니다. 만약 테스트 데이터의 평균과 표준편차를 사용하면, 테스트 데이터에 대한 정보가 모델 훈련과정에 노출되는 data leakage가 발생하여 모델의 성능이 과장될 수 있습니다.
mean = train_data.mean(axis=0)
std = train_data.std(axis=0)
train_data -= mean
train_data /= std
test_data -= mean
test_data /= std
3. 모델 생성
- 데이터가 작으므로 2개의 중간층을 가진 작은 모델을 정의하여 과대적합을 피합니다.
- 주택가격을 예측하는 회귀모델이기 때문에 예측값의 범위를 제한하지 않기 위해 마지막층에 활성화 함수를 사용하지 않습니다.
def build_model():
model = keras.Sequential([
layers.Dense(64, activation="relu"),
layers.Dense(64, activation="relu"),
layers.Dense(1)
])
# 컴파일
model.compile(optimizer="rmsprop",
loss="mse", # MSE(평균제곱오차)를 손실함수로 사용
metrics=["mae"]) # 훈련하는 동안 모니터링을 위해 예측과 타깃 사이의 절댓값인 MAE 측정
return model
4. K-겹 검증
- 데이터가 작으므로 검증 세트도 작아지는데, 이를 해결하기 위해 K-겹 검증을 시행한다.
- K겹 검증 : 데이터를 K개의 분할로 나눠 폴드 1로 두고, K-1개의 분할에서는 훈련을 나머지 1개의 분할에서는 검증을 해 폴드1의 검증 점수를 구한 뒤 분할을 바꿔 폴드2, 폴드3, 이런식으로 각각의 폴드에 대한 검증 점수를 구합니다. 이렇게 구한 검증 점수를 모아 평균을 내 최종 검증 점수로 구하는 것을 K겹 검증이라 합니다.

# K겹 검증 코드
k = 4
num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []
for i in range(k):
print(f"#{i+1}번째 폴드 처리중")
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples] # 검증 데이터
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
partial_train_data = np.concatenate(
[train_data[:i * num_val_samples],
train_data[(i + 1) * num_val_samples:]],
axis=0) # 훈련 데이터, 검증 데이터 외의 다른 부분
partial_train_targets = np.concatenate(
[train_targets[:i * num_val_samples],
train_targets[(i + 1) * num_val_samples:]],
axis=0)
model = build_model()
# 모델 훈련
model.fit(partial_train_data, partial_train_targets,
epochs=num_epochs, batch_size=16, verbose=0)
# 모델 평가
val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0)
all_scores.append(val_mae)
all_scores
5. K겹 검증 점수
- 각 에포크마다 모델이 얼마나 개선되는지 보기 위해 에포크마다 폴드의 검증 점수를 저장해봅니다.
num_epochs = 500
all_mae_histories = []
for i in range(k):
print(f"#{i}번째 폴드 처리중")
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples]
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
partial_train_data = np.concatenate(
[train_data[:i * num_val_samples],
train_data[(i + 1) * num_val_samples:]],
axis=0)
partial_train_targets = np.concatenate(
[train_targets[:i * num_val_samples],
train_targets[(i + 1) * num_val_samples:]],
axis=0)
model = build_model()
history = model.fit(partial_train_data, partial_train_targets,
validation_data=(val_data, val_targets),
epochs=num_epochs, batch_size=16, verbose=0)
mae_history = history.history["val_mae"]
all_mae_histories.append(mae_history)
- 모든 폴드에 대한 에포크의 평균 MAE를 구합니다.
average_mae_history = [
np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]
6. 검증 점수 그래프
- 에포크마다의 폴드의 검증 점수를 그래프로 나타냅니다.
plt.plot(range(1, len(average_mae_history) + 1), average_mae_history)
plt.xlabel("Epochs")
plt.ylabel("Validation MAE")
plt.show()

- 결과를 보면 앞쪽의 데이터값이 지나치게 높아 제대로 분포를 볼 수 없으므로 앞쪽 데이터를 10개정도 제거하고 다시 그려봅니다.
truncated_mae_history = average_mae_history[10:]
plt.plot(range(1, len(truncated_mae_history) + 1), truncated_mae_history)
plt.xlabel("Epochs")
plt.ylabel("Validation MAE")
plt.show()

'DeepLearning' 카테고리의 다른 글
| CNN_데이터 증식 (0) | 2023.09.01 |
|---|---|
| CNN_사전훈련된 모델 (0) | 2023.08.31 |
| CNN_데이터 증식 (0) | 2023.08.30 |
| CNN_강아지 vs 고양이 (0) | 2023.08.30 |
| CNN_MNIST (0) | 2023.08.29 |
