728x90
반응형
보스턴 주택 가격 데이터셋
- 1970년 중반 보스턴 외곽 지역의 범죄율, 지방세율 등의 데이터
- 데이터 포인트가 506개로 404개 훈련 샘플, 102개가 테스트 샘플로 나뉘어 있다.
- 입력 데이터에 있는 특성(feature)은 스케일이 서로 다르다.
- 0과1사이, 1과12사이, 1과 100사이의 값도 있다.
# 보스턴 주택 가격 데이터셋
from tensorflow.keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
print("train_data.shape : ",train_data.shape, "test_data.shape : ",test_data.shape)
print("train_targets: ", train_targets[:10]) # 대략 1만 달러에서 5만 달러 사이 - 70년대라서 인플레이션에 영향을 받지 않았다.
- 13개의 수치 특성(feature)가 있다.
- 1인당 범죄율, 주택당 편균 방의 개수, 고속도로 접근성 등이다.
- 주택 가격은 1970년대에서는 인플레이션에 영향을 받지 않아서 그렇다.
데이터 준비
- 상이한 스케일을 가진 값을 신경망에 주입하면 문제가 된다.
- 특성별로 정규화를 하는 방법이 있다.
- 입력 데이터에 있는 각 특성(입력 데이터 행렬의 열)에 대해서 특성의 평균을 빼고 표준 편차로 나눈다.
- 특성의 중앙이 0근처로 표준 편차가 1이 된다.
# 데이터 정규화하기
mean = train_data.mean(axis=0) # 열
train_data -= mean # 평균을 빼기
std = train_data.std(axis = 0) # 표준편차
train_data /= std # 표준 편차로 나누기
test_data -= mean # 테스트 샘플도 똑같이 평균 빼기
test_data /= std # 표준 편차로 나누기
모델 정의
# 모델 정의
from tensorflow.keras import models,layers
def build_model(): #동일한 모델 여러 번 생성할 예정
model = models.Sequential()
model.add(layers.Dense(64, activation='relu',
input_shape=(train_data.shape[1],)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(1)) # 활성화 함수가 없다. 선형층이라고도 부른다.
# 전형적인 스칼라 회귀(하나의 연속적인 값을 예측하는 회귀)를 위한 구성이다.
# 활성화 함수를 사용시 제한된 값을 예측하므로 x
model.compile(optimizer = 'rmsprop',
loss='mse', metrics=['mae'])
return model
- mse 손실 함수를 사용해 컴파일
- 평균 제곱 오차(mean squared error)의 약어로 예측과 타깃 사이 거리의 제곱이다.
- 회귀문제에서 널리 사용되는 손실 함수
- 훈련동안에는 평균 절대 오차(Mean Absolute Error, MAE)를 측정한다.
- 예측과 타깃 사이 거리의 절댓값이다.
- 0.5면 500달러의 차이
K-겹 검증을 사용한 훈련 검증
- 데이터 샘플이 얼마 없을 경우 K-겹 교차 검증(K-fold cross-validation)을 사용하는 방법이 있다.
- 데이터를 K개의 분할(즉 폴드(fold))로 나누고(일반적으로 K = 4 or 5), K개의 모델을 각각 만들어 K-1개의 분할에서 훈련하고 나머지 분할에서 평가하는 방법이다.
K=5 일 경우의 K-겹 교차 검증
- 데이터를 5개의 분할로 나누고 훈련4 검증1로 나오게 만들고 결과 5개를 합쳐 최종 점수 : 평균을 만든다.
K-겹 검증
# K-겹 검증
import numpy as np
k=4
num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []
for i in range(k):
print('처리중인 폴드 #',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() # 케라스 모델 구성 컴파일 포함
model.fit(partial_train_data, partial_train_targets,
epochs = num_epochs, batch_size =1, verbose = 0) # 모델 훈련(vervose=0)과정이 출력되지 않는다.
val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0)
all_scores.append(val_mae)
print(all_scores)
print(np.mean(all_scores))
- 평균 2550달러정도 차이가 난다.
- 주택 가격은 1만~5만 달러이므로 비교적 큰 값이다.
검증 점수 로그에 저장
num_epochs = 500
all_mae_histories = []
for i in range(k):
print('처리중인 폴드 #', i)
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples] #검증 데이터 준비: k번째 분할 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, # 모델 훈련(verbose=0이므로 훈련 과정이 출력되지 않습니다.)
validation_data=(val_data, val_targets),
epochs=num_epochs, batch_size=1, verbose=0)
mae_history = history.history['mae']
all_mae_histories.append(mae_history)
평균 기록
# 평균 기록
average_mae_history = [
np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]
검증 점수 그래프
# 검증 점수 그래프
import matplotlib.pyplot as plt
plt.plot(range(1, len(average_mae_history) + 1), average_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()
- 변동이 심해 보기 어려울 경우
- 곡선의 다른 부분과 스케이링 많이 다른 첫 10개의 데이터 포인트를 제외시킨다.
- 부드러운 곡선을 얻기 위해 각 포인트를 이전 포인트를 이전 포인트의 지수 이동 평균(exponential moving average)으로 대체한다.
# 처음 10개 데이터 포인트 제외한 검증 점수 그리기
def smooth_curve(points, factor=0.9):
smoothed_points = []
for point in points:
if smoothed_points:
previous = smoothed_points[-1]
smoothed_points.append(previous * factor + point * (1-factor))
else:
smoothed_points.append(point)
return smoothed_points
smooth_mae_history = smooth_curve(average_mae_history[10:])
plt.plot(range(1, len(smooth_mae_history)+1), smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()
# 최종 모델 훈련
model = build_model()
model.fit(train_data, train_targets,
epochs = 80, batch_size = 16, verbose=0)
test_mse_score, test_mae_score = model.evaluate(test_data, test_targets)
print("test_mae_score : ",test_mae_score, "test mse_score : ", test_mse_score)
728x90
반응형
최근댓글