Deep Learning with Python - Ch.03


케라스 창시자에게 배우는 딥러닝을 실습하면서 정리한 포스트입니다. 코드 예제와 코드 설명은 역자 깃허브에서 받아볼 수 있습니다. 출판물이고 개인적으로만 참고하기 위한 요약노트이다 보니 설명이 불친절한 점은 양해 바랍니다. 보다 자세한 내용을 원하시는 분은 위 링크의 책을 참고하시기 바랍니다.


3장. 신경망 시작하기

신경망 구조

  • 네트워크(모델)를 구성하는 층
  • 입력데이터, 타겟
  • 손실 함수: 피드백 신호를 정의
  • 옵티마이저: 학습 진행 방식을 결정

층: 딥러닝의 구성 단위

  • 층: 하나 이상의 텐서를 입력받아 하나 이상의 텐서를 출력하는 데이터 처리 모듈
  • 대부분 가중치라는 층의 상태를 가짐(상태가 없는 층도 존재)
  • 가중치는 확률적 경사 하강법에 의해 학습되는 하나 이상의 텐서
  • 층마다 적절한 텐서 포맷과 데이터 처리 방식이 다름
    • 벡터 데이터(2D 텐서) : 밀집 연결 층
    • 시퀀스 데이터(3D 텐서) : LSTM 같은 순환 층
    • 이미지 데이터(4D 텐서) : Conv2D 클래스. 2D 합성곱 층
  • 케라스는 호환 가능한 층(호환성: 각 층이 특정 크기의 입력 텐서만 받고 특정 크기의 출력 텐서를 반환)을 엮어 데이터 변환 파이프라인을 구성해 딥러딩 모델을 만듦
# 첫 번째 차원이 784인 2D 텐서만 입력으로 받는 층
# 첫 번째 차원 크기가 32로 변환된 텐서를 출력
from keras import layers
layer = layers.Dense(32, input_shape=(784,))
  • 위 층에는 32차원의 벡터를 입력으로 받는 하위 층이 연결돼야 함
  • 케라스가 모델에 추가된 층을 자동으로 상위 층에 맞춰줌
from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(32, input_shape=(784,)))
model.add(layers.Dense(10))
  • 두 번째 층에는 input_shape 매개변수를 지정하지 않음(앞 층의 출력 크기를 입력 크기로 자동으로 채택)

모델: 층의 네트워크

  • 딥러닝 모델은 층으로 만든 Directed Acyclic Graph(DAG)
  • 자주 등장하는 네트워크 구조
    • branch가 2개인 네트워크
    • 출력이 여러 개인 네트워크
    • inception 블록
  • 네트워크 구조는 가설 공간(가능성 있는 공간)을 정의
  • 네트워크 구조 선택 : 가설 공간을 입력 데이터에서 출력 데이터로 매핑하는 일련의 특정 텐서 연산으로 제한
  • 딱 맞는 네트워크 구조 찾기는 과학보다 예술
  • 네트워크 구조 정의 후에는 손실함수와 옵티마이저를 선택해야 함

손실 함수와 옵티마이저: 학습 과정을 조절하는 열쇠

  • 손실 함수: 훈련하는 동안 최소화될 값. 문제에 대한 성공 지표
  • 옵티마이저: 손실 함수를 기반으로 네트워크가 어떻게 업데이트될지 결정.
  • 출력 여러 개를 내는 신경망은 여러 개의 손실 함수를 가질 수 있음
  • But, 경사 하강법 과정은 하나의 스칼라 손실 값을 기준으로 함
  • 따라서 손실이 여러 개인 네트워크에서는 모든 손실이 (평균을 내서) 하나의 스칼라 양으로 합쳐짐
  • 문제에 따라 올바른 목적 함수 선택해야
    • 2개의 클래스 분류 문제 : binary crossentropy
    • 여러개 클래스 분류 문제 : categorical crossentropy
    • 회귀 문제 : 평균 제곱 오차
    • 시퀀스 학습 문제 : Connection Temporal Classification
    • 완전히 새로운 연구: 독자적인 목적 함수

케라스 소개

  • 생략

딥러닝 컴퓨터 셋팅

  • 생략

영화 리뷰 분류: 이진 분류 예제

리뷰 텍스트를 기반으로 영화 리뷰를 긍정과 부정으로 분류

IMDB 데이터셋

from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
  • num_words=10000 : 트레이닝셋에서 가장 많이 등장하는 단어 1만 개만 사용
  • labels는 0(부정)과 1(긍정)을 나타내는 리스트

데이터 준비

  • 숫자 리스트를 신경망에 넣기 위해 텐서로 바꾸는 두 가지 방법
    • 리스트에 padding을 추가하고 (samples, sequence-length) 크기의 정수 텐서로 변환. 신경망 첫 번째 층으로 사용
    • 리스트를 원핫인코딩해 0, 1 벡터로 변환. (아래 예시)
# 정수 시퀀스를 이진 행렬로 인코딩
import numpy as np

def vectorize_sequences(sequences, dimension=10000):
# (시퀀스 길이, 차원) 크기의 0행렬 만들기
results = np.zeros((len(sequences), dimension))

# results[i]에서 특정 인덱스 위치를 1로 바꾸기
for i, sequence in enumerate(sequences):
results[i, sequence] = 1.

return results

# 데이터를 벡터로 변환
x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)

x_train.shape, x_test.shape는 각각 (25000, 10000) 모양이 됨

# 라벨을 벡터로 바꾸기
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

신경망 모델 만들기

  • 입력 데이터는 벡터, 라벨은 1 or 0의 스칼라
  • 이런 문제에 잘 작동하는 네트워크는 relu 활성화 함수를 사용한 완전 연결 층(Dense(16, activation=’relu’))을 그냥 쌓은 것
  • 16은 은닉 유닛의 수. 하나의 은닉 유닛은 층이 나타내는 표현 공간에서 하나의 차원이 됨.
  • output = relu(dot(W, input) + b)
  • 16개 은닉 유닛이 있다는 건 가중치 행렬 W의 크기가 (input_dimension, 16)이라는 의미. 입력 데이터와 W를 점곱하면 입력 데이터가 16차원으로 표현된 공간으로 투영됨(+ 편향 벡터 b를 더하고 relu 연산 적용)
  • 표현공간의 차원: ‘신경망이 내재된 표현을 학습할 때 가질 수 있는 자유도’
  • 중간의 은닉 층은 활성화 함수로 relu를, 마지막 층은 확률을 출력하기 위해 시그모이드 활성화 함수를 사용.
  • relu는 음수를 0으로 만드는 함수. 시그모이드는 임의의 값을 [0, 1] 사이로 압축-> 출력 값을 확률처럼 해석 가능
# 위 신경망의 케라스 구현
from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
  • 이진 분류 문제고 신경망 출력이 확률 -> binary_crossentropy 나 mean_squared_error
  • binary_crossentropy
    • 확률을 출력하는 모델 사용 시 최선의 선택
    • 크로스엔트로피: 확률 분포 간의 차이를 측정(여기선 원본 분포와 예측 분포 사이를 측정)
# 모델 컴파일하기
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
  • 옵티마이저의 매개변수를 바꾸거나 손실함수, 측정함수를 직접 만들어야 할 경우는 아래와 같이 설정
# 옵티마이저 설정하기
from keras import optimizers
model.compile(optimizer=optimizers.RMSprop(lr=0.001),
loss='binary_crossentropy',
metrics=['accuracy'])
# 손실, 측정함수 객체로 지정하기
from keras import losses
from keras import metrics

model.compile(optimizer=optimizers.RMSprop(lr=0.001),
loss=losses.binary_crossentropy,
metrics=[metrics.binary_accuracy])

훈련 검증

# 원본 훈련 데이터에서 1만개 샘플 떼어내 검증 셋 만들기
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
v_val = y_train[:10000]
partial_y_train = y_train[10000:]
# 512개 샘플씩 미니 배치를 만들어 20번의 에포크 동안 훈련
history = model.fit(partial_x_train,
partial_y_train,
epochs=20,
batch_size=512,
validation_data=(x_val, y_val))
Train on 15000 samples, validate on 10000 samples
Epoch 1/20
15000/15000 [==============================] - 3s 200us/step - loss: 0.5084 - acc: 0.7810 - val_loss: 0.3798 - val_acc: 0.8683
Epoch 2/20
15000/15000 [==============================] - 1s 95us/step - loss: 0.3005 - acc: 0.9043 - val_loss: 0.3002 - val_acc: 0.8901
Epoch 3/20
15000/15000 [==============================] - 1s 95us/step - loss: 0.2179 - acc: 0.9289 - val_loss: 0.3083 - val_acc: 0.8711
Epoch 4/20
15000/15000 [==============================] - 2s 124us/step - loss: 0.1750 - acc: 0.9437 - val_loss: 0.2843 - val_acc: 0.8835
Epoch 5/20
15000/15000 [==============================] - 1s 95us/step - loss: 0.1426 - acc: 0.9542 - val_loss: 0.2842 - val_acc: 0.8870
Epoch 6/20
15000/15000 [==============================] - 1s 94us/step - loss: 0.1150 - acc: 0.9653 - val_loss: 0.3154 - val_acc: 0.8772
Epoch 7/20
15000/15000 [==============================] - 1s 95us/step - loss: 0.0978 - acc: 0.9709 - val_loss: 0.3129 - val_acc: 0.8846
Epoch 8/20
15000/15000 [==============================] - 1s 94us/step - loss: 0.0807 - acc: 0.9765 - val_loss: 0.3857 - val_acc: 0.8650
Epoch 9/20
15000/15000 [==============================] - 2s 107us/step - loss: 0.0660 - acc: 0.9820 - val_loss: 0.3636 - val_acc: 0.8782
Epoch 10/20
15000/15000 [==============================] - 2s 134us/step - loss: 0.0561 - acc: 0.9849 - val_loss: 0.3844 - val_acc: 0.8793
Epoch 11/20
15000/15000 [==============================] - 2s 137us/step - loss: 0.0436 - acc: 0.9899 - val_loss: 0.4151 - val_acc: 0.8783
Epoch 12/20
15000/15000 [==============================] - 2s 117us/step - loss: 0.0379 - acc: 0.9920 - val_loss: 0.4542 - val_acc: 0.8684
Epoch 13/20
15000/15000 [==============================] - 2s 109us/step - loss: 0.0300 - acc: 0.9929 - val_loss: 0.4703 - val_acc: 0.8728
Epoch 14/20
15000/15000 [==============================] - 2s 125us/step - loss: 0.0247 - acc: 0.9945 - val_loss: 0.5042 - val_acc: 0.8718
Epoch 15/20
15000/15000 [==============================] - 2s 132us/step - loss: 0.0192 - acc: 0.9964 - val_loss: 0.5316 - val_acc: 0.8704
Epoch 16/20
15000/15000 [==============================] - 2s 109us/step - loss: 0.0164 - acc: 0.9969 - val_loss: 0.5650 - val_acc: 0.8690
Epoch 17/20
15000/15000 [==============================] - 1s 99us/step - loss: 0.0125 - acc: 0.9981 - val_loss: 0.5973 - val_acc: 0.8668
Epoch 18/20
15000/15000 [==============================] - 2s 108us/step - loss: 0.0108 - acc: 0.9983 - val_loss: 0.6285 - val_acc: 0.8670
Epoch 19/20
15000/15000 [==============================] - 2s 109us/step - loss: 0.0079 - acc: 0.9991 - val_loss: 0.7197 - val_acc: 0.8553
Epoch 20/20
15000/15000 [==============================] - 1s 100us/step - loss: 0.0048 - acc: 0.9998 - val_loss: 0.6812 - val_acc: 0.8674
  • model.fit() 메서드는 History 객체를 반환
# 훈련과 검증 손실
import matplotlib.pyplot as plt

history_dict = history.history
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(loss) + 1)

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('훈련과 검증 손실')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

# 훈련과 검증 정확도
plt.clf()
acc = history_dict['acc']
val_acc = history_dict['val_acc']
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('훈련과 검증 정확도')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

  • 훈련 손실은 에포크마다 감소, 훈련 정확도는 에포크마다 증가
  • 트레이닝셋에서 잘 작동하지만 테스트셋에서는 아님(overfitting 됐기 때문)
  • 오버피팅을 막기 위해 세번째 에포크 이후 훈련을 중지
# 처음부터 다시 훈련하기
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])

model.fit(x_train, y_train, epochs=4, batch_size=512)
model.evaluate(x_test, y_test)
Epoch 1/4
25000/25000 [==============================] - 3s 102us/step - loss: 0.4749 - acc: 0.8216
Epoch 2/4
25000/25000 [==============================] - 2s 76us/step - loss: 0.2659 - acc: 0.9096
Epoch 3/4
25000/25000 [==============================] - 2s 70us/step - loss: 0.1983 - acc: 0.9298
Epoch 4/4
25000/25000 [==============================] - 2s 67us/step - loss: 0.1678 - acc: 0.9403
25000/25000 [==============================] - 3s 140us/step
[0.3244189430713654, 0.87316]
  • 87%의 정확도 달성

훈련된 모델로 새로운 데이터에 대해 예측하기

model.predict(x_test)
array([[0.23489225],
[0.99956626],
[0.95799285],
...,
[0.16514498],
[0.11655141],
[0.74928373]], dtype=float32)

뉴스 기사 분류: 다중 분류 문제

  • 로이터 뉴스를 46개 토픽으로 분류하는 신경망 만들기
  • 각 데이터가 하나의 카테고리로 분류되는 단일 레이블 다중 분류 문제
  • 각 데이터가 여러 개의 카테고리에 속할 수 있다면 다중 레이블 다중 분류 문제

로이터 데이터셋

# 케라스에서 데이터셋 불러오기
from keras.datasets import reuters

(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)
  • num_words=10000 : 데이터에서 가장 자주 등장하는 단어 10000개로 제한
# 샘플 수 확인하기
len(train_data), len(test_data)
(8982, 2246)
  • 트레이닝셋 8982개, 테스트셋 2246개
train_data[-1]
[1,
227,
2406,
91,
2,
125,
2855,
21,
4,
3976,
76,
7,
4,
757,
481,
3976,
790,
5259,
5654,
9,
111,
149,
8,
7,
10,
76,
223,
51,
4,
417,
8,
1047,
91,
6917,
1688,
340,
7,
194,
9411,
6,
1894,
21,
127,
2151,
2394,
1456,
6,
3034,
4,
329,
433,
7,
65,
87,
1127,
10,
8219,
1475,
290,
9,
21,
567,
16,
1926,
24,
4,
76,
209,
30,
4033,
6655,
5654,
8,
4,
60,
8,
4,
966,
308,
40,
2575,
129,
2,
295,
277,
1071,
9,
24,
286,
2114,
234,
222,
9,
4,
906,
3994,
8519,
114,
5758,
1752,
7,
4,
113,
17,
12]
  • 각 샘플은 정수 리스트
# 텍스트로 디코딩
word_index = reuters.get_word_index()
reverse_word_index = dict((value, key) for (key, value) in word_index.items())
decoded_newswire = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[-1]])
# 0, 1, 2는 각각 '패딩, 문서 시작, 사전에없음' 인덱스이므로 3을 뺌
decoded_newswire
"? currency fluctuations may ? their influence on the bullion market in the near future bullion bankers samuel montagu and co ltd said in a market report but the firm said silver may lag behind gold in any reactions to movements on foreign exchanges opec's failure to address the recent decline in oil prices remains a worrying factor however and on balance it appears that the market should be approached cautiously montagu said the bank said the us economy has shown no ? long term improvement and that both latin american debt and the iranian arms affair could undermine confidence in the dollar reuter 3"
train_labels.min(), train_labels.max()
(0, 45)
  • 라벨은 0과 45 사이의 정수

데이터 준비

# 데이터를 벡터로 변환
def vectorize_sequences(sequences, dimension=10000):
results = np.zeros((len(sequences), dimension))
for i, sequence in enumerate(sequences):
results[i, sequence] = 1.
return results

# 데이터를 벡터로 변환
x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)
  • 라벨을 벡터로 바꾸는 두 가지 방법
    • 라벨의 리스트를 정수 텐서로 변환한따
    • 원 핫 인코딩(범주형 인코딩)(아래 예시)
# 케라스 내장 함수를 사용한 원핫인코딩
from keras.utils.np_utils import to_categorical

one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)

모델 구성

  • 출력 클래스는 46개. 규모가 작은 층을 사용하면 병목현상으로 유용한 정보를 잃게될 수 있다. 따라서 아래에선 64개 유닛을 사용한다.
from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
  • 마지막 Dense 층의 크기는 46. (각 입력 샘플에 대해 46차원의 벡터를 출력)
  • 마지막 층의 softmax 활성화 함수 : 각 입력 샘플마다 46개 출력 클래스에 대한 확률 분포를 출력. 46개의 값을 더하면 1이 됨
# 모델 컴파일하기
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
  • 카테고리컬 크로스엔트로피 손실함수는 두 확률 분포 사이의 거리를 측정
  • 여기선 네트워크가 출력한 확률 분포와 진짜 라벨의 분포 사이의 거리를 측정
  • 두 분포 사이의 거리를 좁힐수록 진짜 라벨에 가까운 출력을 내도록 훈련시킨다

훈련 검증

# 테스트셋에서 1000개 샘플을 따로 떼어내 검증셋 준비하기
x_val = x_train[:1000]
partial_x_train = x_train[1000:]
y_val = one_hot_train_labels[:1000]
partial_y_train = one_hot_train_labels[1000:]
# 모델 트레이닝(에포크 20번)
history = model.fit(partial_x_train,
partial_y_train,
epochs=20,
batch_size=512,
validation_data=(x_val, y_val))
# 훈련과 검증 손실
import matplotlib.pyplot as plt

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(loss) + 1)

plt.plot(epochs, loss, 'bo', label='훈련 손실')
plt.plot(epochs, val_loss, 'b', label='검증 손실')
plt.title('훈련과 검증 손실')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

# 훈련과 검증 정확도
plt.clf()

acc = history.history['acc']
val_acc = history.history['val_acc']

plt.plot(epochs, acc, 'bo', label='훈련 정확도')
plt.plot(epochs, val_acc, 'b', label='검증 정확도')
plt.title('훈련과 검증 정확도')
plt.xlabel('에포크')
plt.ylabel('정확도')
plt.legend()

plt.show()

  • 아홉 번째 에포크 이후 오버피팅이 시작됨. 에포크 9로 새로운 모델 훈련하고 테스트셋에서 평가
model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))

model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(partial_x_train,
partial_y_train,
epochs=9,
batch_size=512,
validation_data=(x_val, y_val))
results = model.evaluate(x_test, one_hot_test_labels)
results
# 78%의 정확도
[0.9839374910797907, 0.7858414960459524]
import copy

test_labels_copy = copy.copy(test_labels)
np.random.shuffle(test_labels_copy)
float(np.sum(np.array(test_labels) == np.array(test_labels_copy))) / len(test_labels)
0.19100623330365094
  • 무작위 분류시의 19%에 비하면 좋은 결과!

새로운 데이터에 대해 예측하기

# 테스트셋 예측하기
predictions = model.predict(x_test)
  • predictions
    • 각 항목은 길이가 46인 벡터
    • 이 벡터의 원소의 합은 1
    • 가장 큰 값이 가장 확률이 높은 클래스(np.argmax 사용)

레이블과 손실을 다루는 다른 방법

  • 라벨을 정수 텐서로 변환해서 인코딩 할때는 손실 함수 하나만 바꾸면 된다
    • loss=sparse_categorical_crossentropy

주택 가격 예측: 회귀 문제

보스턴 주택 가격 데이터셋

  • 506개 데이터 포인트: 트레이닝셋 404개, 테스트셋 102개
  • 각 피쳐는 스케일이 다름
from keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()

print(train_data.shape)
print(test_data.shape)
(404, 13)
(102, 13)

데이터 준비

  • 상이한 스케일을 가진 값을 신경망에 주입하면 문제(학습을 어렵게 만든다)
  • 특성별로 정규화를 해보자
  • 각 특성에 대해 특성의 평균을 빼고 표준편차로 나눔
# 데이터 정규화하기
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 keras import models
from keras import 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))
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
return model
  • 마지막 층은 선형층(하나의 유닛, 활성화 함수 없음)
    • 전형적인 스칼라 회귀(하나의 연속적인 값을 예측하는 회귀)를 위한 구성
    • sigmoid 활성화 함수를 적용하면 네트워크가 0과 1 사이의 값을 예측하도록 학습될 것. 여기선 선형이므로 범위 제한이 없음
  • mse(평균 제곱 오차) 손실 함수로 컴파일(예측과 타깃 사이 거리의 제곱)
  • 훈련하는 동안 mae(평균 절대 오차)를 측정(예측과 타깃 사이의 절대값)

K-겹 검증을 사용한 훈련 검증

  • 데이터셋이 작으면 트레이닝셋과 테스트셋으로 어떤 데이터가 선택됐는지에 따라 검증 점수가 크게 달라지는데 이럴 때 사용
  • 데이터를 K개로 나누고 K개의 모델을 각각 만들어 K-1개의 분할에서 훈련하고 나머지 분할에서 평가
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)
# 검증 데이터 준비: k번째 분할
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()

# 모델 훈련(verbose=0 이므로 훈련 과정 출력은 없다)
model.fit(partial_train_data, partial_train_targets,
epochs=num_epochs, batch_size=1, verbose=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))
[2.0463592958922434, 2.3122981940165603, 3.0172314785494665, 2.323145497553419]
2.4247586165029222
  • 4가지 검증 점수는 2.04부터 3.01까지 편차가 크지만 평균값인 2.42는 이보다 신뢰할 만하다
  • 다음은 신경망을 500 에포크 동안 훈련
# 각 폴드에서 검증점수 로그에 저장하기
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]
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()
hisgory = model.fit(partial_train_data, partial_train_targets,
validation_data=(val_data, val_targets),
epochs=num_epochs, batch_size=1, verbose=0)
mae_history = history.history['val_mean_absolute_error']
all_mae_histories.append(mae_history)

**

정리

  • 회귀는 손실함수로 평균제곱오차(MSE)를 자주 사용한다
  • 회귀는 평가 지표로 평균절대오차(MAE)를 자주 사용한다
  • 입력 피쳐들이 서로 다른 범위면 스케일을 하자
  • 트레이닝셋이 적다면 은닉층을 한 두개 정도만 사용하자
© 2019 THE DATASCIENTIST All Rights Reserved.
Theme by hiero