elevne's Study Note
NLP 공부 (3: 감성분석) 본문
Github에 공개되어 있는 네이버 영화 평점 데이터를 사용하여 감성분석을 진행해보았다. 해당 데이터는 총 20만 개의 영화리뷰 데이터로 이루어져 있고, 20만 개의 리뷰는 각각 긍정/부정으로(각각 1,0)으로 레이블링이 되어있다. 아래 링크에서 데이터를 다운로드 받을 수 있다.
데이터링크: https://github.com/e9t/nsmc
import pandas as pd
train_data = pd.read_csv("ratings_train.txt", header=0, delimiter="\t")
train_data.head()
위에서는 데이터가 tab으로 구분되어 있어 delimiter=”\t”을 인자로 넣어서 파일을 읽어주었다.
그 후, 전체 트레이닝 데이터셋의 특징을 알아보기 위한 과정을 몇 가지 거쳤다. WordCloud를 만들어서 단순히 확인해보기도 하고, 전체 리뷰 데이터 길이의 분포를 알아보기도 하였다.
from wordcloud import WordCloud
import matplotlib.pyplot as plt
#어휘분석은 문자열에 대해서만 가능하기에 다른 형식은 제외하고 list 만들기
train_data_list = [i for i in train_data["document"] if type(i) is str]
wordcloud = WordCloud(font_path="BMHANNAPro.ttf").generate(" ".join(train_data_list))
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()
import numpy as np
#단어개수 분포 확인해보기
word_count = train_data["document"].astype(str).apply(lambda x:len(x.split(" ")))
간단하게 데이터셋 특성을 여러 방면으로 확인해본 후, 이제는 모델링을 위한 데이터전처리를 거쳐야할 차례였다. 이전 시간에 알아보았던 KoNLPy와 Keras의 Tokenizer을 사용하여 Input data에 대한 전처리를 진행하였다.
from konlpy.tag import Okt
import re
#전처리된 리뷰들을 넣을 리스트
train_data_preprocess = list()
#형태소분석시 제외할 불용어들
stopwords = ["은", "는", "이", "가", "하", "아", "것", "들", "이", "있", "되", "수",
"보", "주", "등", "한"]
okt = Okt()
for i in train_data["document"]:
if type(i) is str:
i = re.sub("[^가-힣ㄱ-ㅎㅏ-ㅣ\\s]","",i)
hts_list = okt.morphs(i, stem=True)
hts_list = [hts for hts in hts_list if not hts in stopwords]
train_data_preprocess.append(hts_list)
else:
train_data_preprocess.append([])
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer()
tokenizer.fit_on_texts(train_data_preprocess)
train_seqs = tokenizer.texts_to_sequences(train_data_preprocess)
test_seqs = tokenizer.texts_to_sequences(test_data_preprocess)
#단어사전
vocab = tokenizer.word_index
#학습데이터/라벨
train_input = pad_sequences(train_seqs, maxlen=10, padding="post")
train_label = np.array(train_data["label"])
#테스트데이터/라벨
test_input = pad_sequences(test_seqs, maxlen=10, padding="post")
test_label = np.array(test_data["label"])
Re 라이브러리의 sub함수를 통해서 한글을 제외한 문자들을 우선적으로 제거해줄 수 있도록 했고, 그 이후에 Okt 형태소분석기를 통해 형태소분석을 진행하였다. 이전 글에 작성했었던 Keras의 texts_to_sequences 함수를 사용해서 텍스트들을 One-Hot Encoding 형태의 시퀀스 형태로 변경을 해줬다. 그 후, 최대 길이를 10으로 지정해주며 pad_sequence 함수를 통해 모든 시퀀스들을 동일한 길이로 맞춰주었다. 이제 모델을 학습시키기 위한 데이터전처리 단계는 끝이났고, 학습시킬 모델을 아래와 같이 작성해주었다.
from keras.models import Sequential
from keras.layers import Dense, Activation, LSTM, Dropout, Embedding
from keras.constraints import MaxNorm
from keras.losses import BinaryCrossentropy
model = Sequential()
model.add(Embedding(input_dim=len(vocab)+1, output_dim=128))
model.add(LSTM(128, return_sequences=True))
model.add(LSTM(128))
model.add(Dropout(0.3))
model.add(Dense(128, activation="relu"))
model.add(Dense(1, activation="sigmoid", kernel_constraint=MaxNorm(max_value=3.)))
model.compile(optimizer="adam", loss=BinaryCrossentropy(), metrics=["accuracy"])
LSTM 레이어를 두 개 쌓아보았다. 첫 번째 LSTM 레이어에 인자로 넣은 return_sequences는 시퀀스 출력 여부를 결정하는 부분인데, LSTM 레이어는 이 인자에 따라서 마지막 시퀀스에서 한 번만 출력을 할 수도 있고 각 시퀀스에서 출력할 수도 있다고 한다. Many-to-Many 문제를 풀거나 위와 같이 LSTM 레이어를 여러 개로 쌓을 때는 이 인자가 필요하다고 한다.
모델도 컴파일 해주었으니 학습을 진행해주었다.
from keras.callbacks import EarlyStopping, ModelCheckpoint
earlystop_callback = EarlyStopping(monitor="val_accuracy", min_delta=0.0001, patience=5)
cp_callback = ModelCheckpoint("./", monitor="val_accuracy", verbose=1, save_best_only=True)
model.fit(train_input, train_label, batch_size=512, epochs=30, validation_split=0.1, callbacks=[earlystop_callback, cp_callback])
Train set에 대해서는 꽤나 높은 성능을 보여주는 것으로 나타났지만, validation accuray가 80프로 초반에서 발전하지 않아서 epoch 7에서 금방 멈춰버린 것을 볼 수 있다. 이러한 문제를 해결하기 위해 Dropout을 추가한다던지 LSTM 레이어를 하나 줄인다던지 여러가지 시도를 해볼 수 있을 것 같다. 마지막으로 아래 코드에서 model predict 함수를 통해 간단한 테스트를 해보며 마무리하였다.
출처:
'Machine Learning > NLP' 카테고리의 다른 글
NLP 공부 (5-1: Transformer) (0) | 2022.10.23 |
---|---|
NLP 공부 (4-2: Seq2Seq with Attention) (0) | 2022.10.22 |
NLP 공부 (4-1: Seq2Seq with Attention) (0) | 2022.10.21 |
NLP 공부 (2: Embedding(Word2Vec)) (0) | 2022.10.16 |
NLP 공부 (1: Vectorizer, 형태소분석기, re) (0) | 2022.10.15 |