머신러닝 이진분류 예제 - meosinleoning ijinbunlyu yeje

3장 신경망 시작하기

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

IMDB 데이터셋 (Internet Movie Database)

인터넷 영화 데이터베이스로부터 가져온 양극단의 리뷰 5만 개로 이루어짐.

훈련 데이터 2만 5,000개와 테스트 데이터 2만 5,5000개로 나뉘어 있고

각각 50%는 부정, 50%는 긍정 리뷰로 구성

각 리뷰(단어 시퀀스)가 숫자 시퀀스로 변환되어 있음.

1. 데이터셋 로드

from keras.datasets import imdb #data load, rottnsms 1만 개로 제한 (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

train_data, test_data : 리뷰의 목록, 각 리뷰는 단어 인덱스의 리스트

train_labels, test_labels : 부정을 나타내는 0과 긍정을 나타내는 1의 리스트

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): # 크기가 (len(sequences), dimension))이고 모든 원소가 0인 행렬을 만듦. results = np.zeros((len(sequences), dimension)) for i, sequence in enumerate(sequences): results[i, sequence] = 1. # results[i]에서 특정 인덱스의 위치를 1로 만듦. return results # 훈련 데이터를 벡터로 변환 x_train = vectorize_sequences(train_data) # 테스트 데이터를 벡터로 변환 x_test = vectorize_sequences(test_data)# 레이블을 벡터로 변환 y_train = np.asarray(train_labels).astype('float32') y_test = np.asarray(test_labels).astype('float32')

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연산을 적용

출처 : //aidev.co.kr/deeplearning/6893

Dense층을 쌓을 때 두 가지 중요한 구조상의 결정이 필요

  • 얼마나 많은 층을 사용할 것인가?
    => 16개의 은닉 유닛을 가진 2개의 은닉 층
  • 각 층에 얼마나 많은 은닉 유닛을 둘 것인가?
    => 현재 리뷰의 감정을 스칼라 값의 예측으로 출력하는 세 번째 층
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'))
출처 : 케라스 창시자에게 배우는 딥러닝 도서의 그림

4. 신경망 모델 만들기 - 모델 컴파일하기

model.compile(optimizer='rmsprop', #옵티마이저 선택 loss='binary_crossentropy', #손실 함수 선택 metrics=['accuracy']) # 측정 지표 선택

손실 함수에서 이진 분류 문제이고 신경망의 출력이 확률이므로 binary_crossentropy 또는 mean_squared_error가 적합

(확률 출력 모델은 크로스엔트로피(Crossentropy)가 적합)

크로스엔트로피(Crossentropy) : 정보 이론 분야에서 온 개념으로 확률 분포 간의 차이를 측정

5. 훈련 검증

훈련하는 동안 처음 본 데이터에 대한 모델의 정확도를 측정하기 위해 원본 훈련 데이터에서 10,000개의 샘플을 준비

x_val = x_train[:10000] partial_x_train = x_train[10000:] y_val = y_train[:10000] partial_y_train = y_train[10000:]

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 acc = history.history['acc'] val_acc = history.history['val_acc'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs = range(1, len(acc) + 1) # ‘bo’는 파란색 점을 의미합니다 plt.plot(epochs, loss, 'bo', label='Training loss') # ‘b’는 파란색 실선을 의미합니다 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_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('Training and validation accuracy') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.show()
결과

4번째 에포크 이후부터 훈련 데이터에 과도하게 최적화된 과대 적합(overfitting)인 걸 확인할 수 있음.

따라서, 에포크를 4번으로 줄이고 다시 훈련하기

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) results = model.evaluate(x_test, y_test)

최종 결과 : 87%의 정확도

>>> results [0.3231545869159698, 0.87348]

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

>>> model.predict(x_test) array([[0.1402615 ], [0.9997029 ], [0.29552558], ..., [0.07234979], [0.04342841], [0.48153415]], dtype=float32)

Toplist

최신 우편물

태그