본문 바로가기
Data Science/머신러닝

LSTM으로 IMDB 리뷰 감성 분류하기

by 코딩은 잼있어 2020. 7. 2.
728x90

LSTM으로 IMDB 리뷰 감성 분류하기

  • 이번에는 데이터를 분류하기 위해 케라스를 활용해 보겠다.
  • 머신 러닝의 연습을 위해 케라스에서는 영화 사이트 IMDB의 리뷰데이터를 제공해주는데, 해당 데이터와 LSTM을 활용하여 감성에 따라 분류하는 알고리즘을 구현을 연습해보겠다.
from keras.datasets import imdb
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense, LSTM, Embedding
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.models import load_model

# 과정 1. 훈련데이터와 테스트데이터를 불러온다
# 훈련용 영화 리뷰는 X_train에, 훈련용 리뷰의 감성 정보는 y_train에 저장된다.
# 테스트용 영화 리뷰는 X_test에, 테스트용 리뷰의 감성 정보는 y_test에 저장된다.
# 감성정보는 0(부정) or 1(긍정)임
# load_data의 파라미터인 num_words를 사용하여 사용빈도수위가 높은 리뷰 5000개만 갖고옴
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words = 5000)

# 과정 2. 불러온 데이터를 내가 원하는 데이터에 맞게 가공한다.
# pad_sequences란??
# pad_sequences는 문장의 길이가 maxlen을 넘어가면 초과분을 삭제하고 부족하면 0으로 채운다
# 결과적으로 모든 문장의 길이를 max_len으로 만듬
max_len = 500
# X_train과 X_test의 모든 문장의 길이를 500으로 제한
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = pad_sequences(X_test, maxlen=max_len)

# 과정 3. 모델링을 진행 
# Sequential() : 케라스에서는 층을 구성하기 위해 Sequential()을 사용함
# model.add() 라는 코드를 통해 층을 단계적으로 추가할수 있다.
model = Sequential()
# Embedding() : Embedding()을 통해 임베딩 층을 생성
# Embedding(단어집합의 크기, 벡터크기)
model.add(Embedding(5000, 120))

model.add(LSTM(120))
# Dense() : 진결합층(fully-conntected layer)을 의미함 
# Dense(출력 뉴런의수, input_dim = 입력 뉴런의 수, activation = 활성화 함수)
model.add(Dense(1, activation='sigmoid'))

# 과정 4. 데이터를 훈련시키기전에 훈련 조건들을 설정한다.
# EarlyStopping 속성 ==> 학습을 조기중단
# monitor='val_loss' : loss를 monitor에 저장
# mode='min : performance measure를 최소화시킴(max와 min이 존재)
# verbose=1 : verbose를 1로 하면, 언제 keras에서 training을 머췄는지 화면에 출력
# patience=4 : 검증 데이터의 loss가 4번증가하면 학습을 조기중단
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=4)

# ModelCheckpoint 속성 ==> 일정 간격으로 모델의 체크포인트를 저장
# save_best_only=True : 검증데이터의 정확도가 이전보다 더 좋아질 경우에만 'best_model.h5'이름으로 모델을 저장
mc = ModelCheckpoint('best_model.h5', monitor='val_acc', mode='max', verbose=1, save_best_only=True)


# 과정 5. 훈련을 진행한다.
# loss(손실함수) : 이진 판별값이 출력이 되기 때문에, 손실 함수는 binary_crossentropy
# optimizer(최적화함수)
# metrics=['acc'] : 정확도를구하기 위해 accuracy 추가
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc'])

# epochs : 몇번 훈련시킬것인가 ??
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=1, batch_size=64, callbacks=[es, mc])

# 과정 6. 훈련결과를 바탕으로 textdata를 넣어 결과값의 정확도를 측정하자 
# 훈련과정에서 검증 데이터가 가장 높았던 'best_model.h5' 을 로드
loaded_model = load_model('best_model.h5')
print("\n 테스트 정확도: %.4f" % (loaded_model.evaluate(X_test, y_test)[1]))

노트북의 성능이 좋지 않기때문에 예제에서는 10번진행했던 훈련을 1번만 진행했는데,, 이것마저 제대로 돌아가지않는다..

아래와 같이 경고가 발생하면서 훈련을 위한 25000개의 데이터가 가아닌 391개의 데이터를 이용하여 훈련을 진행한다. 케라스를 돌릴수 있는 gpu가 없고, 25000개를 돌리기 위한 cpu의 성능에 미달되어 데이터의 갯수가 작아진것이라고 추정된다....ㅠ..

(돈벌면 바로 엔디비아 gpu 있는 노트북부터 사야겠다.)

img

출력값만 확대

img

  • 1번의 391개의 데이터를 이용한 훈련결과 loss: 0.4803, acc: 0.7602이 나온다.
  • loss 를 더 낮추기 위해 훈련을 더 진행해야하지만, 노트북의 한계로 여기까지 ㅠ.. 진행하겠다..
  • 마지막으로 test data를 이용하여 정확도를 출력해낸다.
728x90