1부 딥러닝의 기초
3장 신경망 시작하기
3.5 뉴스 기사 분류: 다중 분류 예제
로이터 데이터셋 (Reuter)
1986년 로이터에서 공개한 짧은 뉴스 기사와 토픽의 집합인 데이터셋
텍스트 분류를 위해 널리 사용되는 간단한 데이터셋
1. 데이터셋 로드
rom keras.datasets import reuters
(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)
train_data, test_data : 단어 인덱스의 정수 리스트
train_labels, test_labels : 0~45 사이의 정수
2.데이터 준비
숫자 리스트에서 텐서로 변경하는 2가지 방법
(1)같은 길이가 되도록 리스트에 패딩(pading)을 추가하고 (sample, sequence_length)크기의 정수 텐서로 변환
그 다음 정수 텐서를 다룰 수 있는 층을 신경망의 첫 번째 층으로 사용(Embedding 층)
(2) 리스트를 원-핫 인코딩(one-hot encoding)하여 0과 1의 벡터로 변환
시퀀스[3, 5]를 인덱스 3과 5의 위치는 1이고 그 외는 모두 0인 10,000차원의 벡터로 각각 변환
그 다음 부동 소수 벡터 데이터를 다룰 수 있는 Dense층을 신경망의 첫 번째 층으로 사용
#(2)방법 사용
import numpy as np
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)
레이블을 벡터로 변경하는 2가지 방법
(1) 레이블의 리스트를 정수 텐서로 변환하는 것
(2) 원-핫 인코딩(one-hot encoding)을 사용
범주형 데이터에 널리 사용됨.
레이블의 인덱스 자리는 1이고 나머진 모두 0인 벡터
def to_one_hot(labels, dimension=46):
results = np.zeros((len(labels), dimension))
for i, label in enumerate(labels):
results[i, label] = 1.
return results
# 훈련 레이블 벡터 변환
one_hot_train_labels = to_one_hot(train_labels)
# 테스트 레이블 벡터 변환
one_hot_test_labels = to_one_hot(test_labels)
[내장함수 사용해 원-핫 인코딩하는 법]
from keras.utils.np_utils import to_categorical
one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)
3. 신경망 모델 만들기 - 모델 정의하기
relu함수
입력 데이터가 벡터고 레이블은 스칼라(1 또는 0)과 같은 문제에 잘 작동하는 네트워크 종류는 relu 활성화 함수를 사용한 완전 연결층(Dense(16, activation='relu'))을 그냥 쌓은 것
Dense층에 전달한 매개변수(16)는 은닉 유닛(hidden unit)의 개수
하나의 은닉 유닛은 층이 나타내는 표현 공간에서 하나의 차원이 됨.
output = relu(dot(W,input) + b)
16개의 은닉 유닛이 있다는 것은 가중치 행렬 W의 크기가 (input_dimension, 16)이라는 뜻
입력 데이터와 W를 점곱하면 입력 데이터가 16차원으로 표현된 공간으로 투영됨.
그리고 편향 벡터 b를 더하고 relu연산을 적용
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'))
4. 신경망 모델 만들기 - 모델 컴파일하기
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
손실 함수에서, 많은 출력 클래스의 갯수가 필요하기에 categorical_crossentropy가 적합
이 함수는 두 확률 분포 사이의 거리를 측정
(네트워크가 출력한 확률 분포와 진짜 레이블의 분포 사이의 거리)
두 분포 사이의 거리를 최소화하면 진짜 레이블에 가능한 가까운 출력을 내도록 모델을 훈련
5. 훈련 검증
훈련하는 동안 처음 본 데이터에 대한 모델의 정확도를 측정하기 위해 원본 훈련 데이터에서 10,000개의 샘플을 준비
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:]
512개의 샘플씩 미니 배치를 만들어 20번의 에포크 동안 훈련
x_train과 y_train 텐서에 있는 모든 샘플에 대해 20번 반복
동시에 따로 떼어 놓은 1만 개의 샘플에서 손실과 정확도를 측정하기 위해 validation_data 매개변수에 검증 데이터 넣기
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='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
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='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
9번째 에포크 이후부터 훈련 데이터에 과도하게 최적화된 과대 적합(overfitting)인 걸 확인할 수 있음.
따라서, 에포크를 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)
최종 결과 : 약 78%의 정확도
>>> results
[1.022498257544459, 0.7756010686194165]
6. 훈련된 모델로 새로운 데이터에 대해 예측하기
predictions = model.predict(x_test)
레이블과 손실을 다루는 다른 방법
정수 텐서로 변환하는 것
y_train = np.array(train_labels)
y_test = np.array(test_labels)
이 방식을 사용하려면 손실 함수 하나만 바꾸면 됨.
categorical_crossentropy -> sparse_categorical_crossentropy
model.compile(optimizer='rmsprop',
loss='sparse_categorical_crossentropy',
metrics=['acc'])
중간층을 충분히 크게 둬야 하는 이유
많은 정보를 중간층의 저차원 표현 공간으로 압축하려 하면 정확도가 작게 나오게 됨.
'MLOps 프로젝트 > 도서 '케라스 창시자에게 배우는 딥러닝'' 카테고리의 다른 글
1부 4.1 머신 러닝의 네 가지 분류 (0) | 2021.08.30 |
---|---|
1부 3.6 주택 가격 분류: 회귀 문제 (0) | 2021.08.29 |
1부 3.4 영화 리뷰 분류: 이진 분류 예제 (0) | 2021.08.29 |
1부 3.3 딥러닝 컴퓨터 셋팅 (0) | 2021.08.28 |
1부 3.2 케라스 소개 (0) | 2021.08.28 |