- 이번 글에서는 Reuter에서 공개한 짧은 뉴스 기사와 토픽의 집합인 Reuter데이터셋을 활용하여 다중 분류모델을 구현해보겠습니다.
교재 홍보
- 다음의 교재의 내용을 참고하였습니다.
- 교재 구매 : https://www.yes24.com/Product/Goods/112012471
케라스 창시자에게 배우는 딥러닝 개정 2판 - 예스24
단어 하나, 코드 한 줄 버릴 것이 없다!단 한 권의 딥러닝 책을 선택한다면 바로 이 책이다!케라스 창시자이자 구글 딥러닝 연구원인 저자는 ‘인공 지능의 민주화’를 강조한다. 이 책 역시 많
www.yes24.com
데이터 생성
- Reuter 데이터셋을 가져와 훈련데이터와 테스트데이터로 나눕니다.
from tensorflow.keras.datasets import reuters
(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words = 10000)
# 가장 자주 등장하는 단어 1만개로 제한
# train_data와 test_data는 기사와 토픽을 담은 리스트로 단어가 숫자로 인코딩되어 있음
# labels는 토픽의 인덱스로 0~45의 46개 숫자입니다.
데이터 전처리
- IMDB 블로그 글에서 사용한 vectorize_sequences함수로 훈련 데이터를 벡터로 변환해줍니다(멀티-핫 인코딩 사용)
x_train = vectorize_sequences(train_data) # 훈련 데이터 벡터 변환
x_test = vectorize_sequences(test_data) # 테스트 데이터 벡터 변환
- 레이블 또한 벡터로 변환해줘야 하는데, 아래 두 가지 방법 중 하나를 선택해 진행해야 한다. 여기서는 원-핫 인코딩이 범주형 데이터에 더 적합하므로 방법 2로 진행한다.
- 방법 1 : 레이블의 리스트를 정수 텐서로 변환한다.
- 방법 2 : 레이블의 리스트를 원-핫 인코딩하여 0과 1의 벡터로 변환한다.
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
y_train = to_one_hot(train_labels) # 훈련 레이블 벡터 변환
y_test = to_one_hot(test_labels) # 테스트 레이블 벡터 변환
# 위는 함수를 정의하여 원-핫 인코딩을 수행하는 방법이고,
# 아래는 keras에 내장된 함수를 이용해 원-핫 인코딩을 수행
from keras.utils.np_utils import to_categorical
y_train = to_categorical(train_labels) # 훈련 레이블 벡터 변환
y_test = to_categorical(test_labels) # 테스트 레이블 벡터 변환
- 만약 레이블을 방법 1로 하여 정수 텐서로 변환해 진행한다면 다음과 같이 레이블을 변환해 주고, 손실 함수만
모델 정의 및 컴파일
- IMDB 블로그에서의 이진분류 모델과 달리 출력 클래스의 개수가 46개이므로 출력 공간의 차원이 더 큰 모델이 필요하고, 따라서 서 정보의 병목현상을 방지하기 위해 은닉층의 차원도 출력층 보다는 커져야 한다.
- 출력값이 확률 표현이지만 3개이상을 분류한다면 sigmoid 대신 softmax활성화 함수를 사용한다.
- 아래와 같이 64개의 유닛을 가진 2개의 은닉층과 46개의 값을 출력하는 출력 층으로 된 모델을 정의한다. 이때 46개의 각 출력 값들은 어떤 샘플이 그 출력 클래스에 속할 확률을 나타내고 따라서 모든 출력 값을 합하면 1이 된다.
rom tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
layers.Dense(64, activation='relu'),
layers.Dense(64, activation='relu'),
layers.Dense(46, activation='softmax') # 3개이상 분류는 softmax
])
- 모델이 훈련을 마칠 수 있도록 손실 함수와 옵티마이저를 선택해 컴파일 한다.
model.compile(
optimizer="rmsprop",
loss="categorical_crossentropy", # 원-핫 인코딩된 벡터를 입력으로 받고, 확률을 출력하기 때문에 설정
metrics=["accuracy"]
)
검증 데이터 준비
- 훈련 과정 중 모델의 정확도를 모니터링하기 위해 원본 훈련 데이터를 검증데이터와 훈련데이터로 분리한다.
x_val = x_train[:1000]
partial_x_train = x_train[1000:]
y_val = y_train[:1000]
partial_y_train = y_train[1000:]
모델 훈련
- 훈련 데이터에서 512개의 배치사이즈로 샘플을 만들고, 20번의 에포크 동안 모든 샘플에 대해 모델을 훈련시킵니다.
- 만들어 둔 검증데이터로 에포크가 끝날 때마다 손실과 정확도를 계산한다.
history = model.fit(partial_x_train,
partial_y_train,
epochs = 20,
batch_size = 512,
validation_data = (x_val, y_val))
손실과 정확도 그래프
- IMDB 블로그에서 정의한 vis함수로 그래프를 그려줍니다.
vis(history)
- 결과를 살펴보면 아홉 번째 에포크 이후부터 모델의 과적합이 시작되므로 에포크를 9로 하여 모델을 다시 훈련할 필요가 있다.

모델 재훈련
- 모델을 재훈련 시킨다. 테스트 데이터를 이용해 새 모델을 평가한다.
from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
layers.Dense(64, activation='relu'),
layers.Dense(64, activation='relu'),
layers.Dense(46, activation='softmax')
])
model.compile(optimizer="rmsprop",
loss="categorical_crossentropy",
metrics=["accuracy"])
model.fit(x_train,
y_train,
epochs = 9, # 과적합을 피하기 위해 epochs를 9로 하여 모델을 재훈련시킨다.
batch_size = 512)
- 테스트 데이터를 이용해 새 모델을 평가하면 최종적으로 80%에 달하는 정확도를 보임을 알 수 있다.
results = model.evaluate(x_test, y_test) # 테스트 데이터로 모델 평가하고 결과를 results에 할당
results

레이블의 정수 텐서 변환
- 위에서 언급했듯 레이블을 벡터로 변환하는 인코딩 방법에는 두가지가 있다.
- 만약 레이블을 방법 1로 하여 정수 텐서로 변환한다면 다음과 같이 레이블을 변환해 주고,
y_train = np.array(train_labels) # 정수형태로 설정
y_test = np.array(test_labels) # 정수형태로 설정
- 모델 컴파일에서 손실 함수 하나만 바꿔주면 방법 2 대신 방법 1로 모델 학습이 가능하다.
model.compile(optimizer="rmsprop",
loss="sparse_categorical_crossentropy" # 정수 텐서를 입력으로 받아 이를 원-핫 인코딩 해줘야 하므로 설정
metrics=["accuracy"])'DeepLearning' 카테고리의 다른 글
| CNN_강아지 vs 고양이 (0) | 2023.08.30 |
|---|---|
| CNN_MNIST (0) | 2023.08.29 |
| 이진 분류 모델_IMDB데이터 (0) | 2023.08.28 |
| tensorflow를 통한 선형 분류기 구현 (0) | 2023.08.25 |
| MNIST데이터를 활용한 딥러닝 (0) | 2023.08.24 |
