우선 각 단어를 word2vec으로 벡터화 해야하는데 word2vec은 단어로 표현된 리스트를 입력값으로 넣어야 하기 때문에 전처리한 넘파이 배열을 사용하지 않는다. 따라서 전처리된 텍스트 데이터를 불러온 후 각 단어들의 리스트로 나눠야 한다.
import re
import pandas as pd
import numpy as np
import json
import os
DATA_IN_PATH='./data_in/'
TRAIN_CLEAN_DATA='train_clean.csv'
train_data=pd.read_csv(DATA_IN_PATH + TRAIN_CLEAN_DATA)
reviews=list(train_data['review'])
sentiments=list(train_data['sentiment'])
sentences=[]
for review in reviews:
sentences.append(review.split())
전처리한 데이터는 경우 문자열로 이뤄져있는데, 단어로 구분된 리스트로 만들어야하기에 전체 리뷰를 단어 리스트로 바꿨다. 각 리뷰를 spit함수로 구분한 후 리스트에 하나씩 추가해서 입력 값을 만든다.
word2vec 모델 학습을 진행하기 전에 word2vec 모델의 하이퍼파라미터를 설정한다.
# 학습 시 필요한 하이퍼 파라미터
# 워드 벡터 특징값 수
num_features=300
# 단어에 대한 최소 빈도 수
min_word_count=40
# 프로세스 개수
num_workers=4
# 컨텍스트 윈도우 크기
context=10
# 다운 샘플링 비율
downsampling=1e-3
학습에는 gensim 라이브러리를 사용( 없다면 설치)
그 전에 진행 상황을 확인하기 위한 logging을 알아보면
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
로그 수준을 INFO에 맞추면 작성한 양식에 맞춰 INFO 수준으로 보여준다.
word2vec 모듈에 있는 Word2vec 객체를 생성해서 실행하고 이렇게 학습하고 생성된 객체는 model 변수에 할당한다. 이때 학습을 위한 인자는 입력할 데이터와 하이퍼파라미터를 순서대로 입력해야 원하는 하이퍼파라미터를 사용해 학습할 수 있다.
from gensim.models import word2vec
print("Training model...")
model=word2vec.Word2Vec(sentences,
workers=num_workers,
size=num_features,
min_count=min_word_count,
window=context,
sample=downsampling)
학습이 진행되며 로그 메시지가 나타나고 학습이 완료된다. 그 후 word2vec으로 학습시킨 모델의 경의 모델을 따로 저장하여 이후에 다시 사용하도록 한다.
# 모델의 하이퍼파라미터를 설정한 내용을 모델 이름에 담는다면 나중에 참고하기 좋음
# 모델을 저장하면 Word2Vec.load()로 모델을 다시 사용 가능
model_name="300features_40minwords_10context"
model.save(model_name)
이제 만들어진 word2vec 모델을 활용해 선형 회귀 모델을 학습한다. 우선 학습을 하기 위해서 하나의 리뷰를 같은 형태의 입력값으로 만들어야 한다. 지금은 word2vec 모델에서 각 단어가 벡터로 표현돼 있다. 그리고 리뷰마다 단어의 개수가 모두 다르기에 입력값을 하나의 형태로 만들어야 한다. 가장 단순한 방법으로는 문장에 있는 모든 단어의 벡터값에 대해 평균을 내서 리뷰 하나당 하나의 벡터로 만드는 방법이 있다. 하나의 리뷰에 전체 단어의 평균값을 계산하는 함수를 구현하면,
def get_features(words, model, num_features):
# 출력 벡터 초기화
feature_vector=np.zeros((num_features), dtype=np.float32)
num_words=0
# 어휘사전 준비
index2word_set=set(model.wv.index2word)
for w in words:
if w in index2word_set:
num_words+=1
# 사전에 해당하는 단어에 대해 단어 벡터를 더함
feature_vector=np.add(feature_vector, model[w])
# 문장의 단어 수만큼 나누어 단어 벡터의 평균값을 문장 벡터로 함
feature_vector=np.divide(feature_vector, num_words)
return feature_vector
하나의 벡터를 만드는 속도를 빠르게 하기 위해 np.zeros로 미리 모두 0의 값을 가지는 벡터를 만들고, 문장의 단어가 해당 모델 단어사전에 속하는지 보기 위해 model.wv.index2word를 set 객체로 생성해서 index2word_set 변수에 할당한다. 그리고 반복문으로 리뷰를 구성하는 단어에 대해 임베딩된 벡터가 있는 단어 벡터의 합을 구한다. 마지막으로 사용한 단어의 전체 개수로 나눠 평균 벡터의 값을 구함.
이제 정의한 함수를 사용해 전체 리뷰에 대해 각 리뷰의 평균 벡터를 구하는 함수를 정의,
def get_dataset(reviews, model, num_features):
dataset=list()
for s in reviews:
dataset.append(get_features(s, model, num_features))
reviewFeatureVecs=np.stack(dataset)
return reviewFeatureVecs
속도 향상을 위해 전체 리뷰에 대한 평균 벡터를 담을 0으로 채워진 넘파이 배열을 미리 만든다. 배열은 2차원으로 만드는데 행에는 각 문장에 대한 길이를, 열에는 평균 벡터의 차원 수(크기)를 입력한다. 그리고 각 리뷰에 대해 반복문으로 특징 값을 만든다.
그리고 전체 리뷰 데이터를 실제 학습에 쓸 입력값으로 만든다.
test_data_vecs=get_dataset(sentences, model, num_features)
만든 데이터로 학습 데이터와 검증 데이터로 나눈다. 앞서 TF-IDF에서 진행한 방식과 같다.
from sklearn.model_selection import train_test_split
X=test_data_vecs
y=np.array(sentiments)
RANDOM_SEED=42
TEST_SPLIT=0.2
X_train, X_eval, y_train, y_eval=train_test_split(X, y, test_size=TEST_SPLIT, random_state=RANDOM_SEED)
모델은 TF-IDF 벡터를 사용했을 때와 동일하게 로지스틱 모델을 사용한다. 비교하면 입력값을 어떤 특징으로 뽑았는지만 다르고 모두 같다.
from sklearn.linear_model import LogisticRegression
lgs=LogisticRegression(class_weight='balanced')
lgs.fit(X_train, y_train)
이전과 똑같이 진행한다.
# 검증 데이터로 성능 측정
print("Accuracy: %f" % lgs.score(X_eval, y_eval))
캐글에 제출할 데이터를 만든다.
TEST_CLEAN_DATA='test_clean.csv'
test_data=pd.read_csv(DATA_IN_PATH+TEST_CLEAN_DATA)
test_review=list(test_data['review'])
평가 데이터 역시 학습 데이터와 마찬가지로 각 리뷰가 하나의 문자열로 되어 있으므로 평가 데이터도 각 단어의 리스트로 만들어야 함.
test_sentences=[]
for review in test_data:
test_sentences.append(review.split())
평가 데이터도 단어 리스트로 만든 후 word2vec으로 임베딩된 벡터값을 갖게 해야한다. 평가 데이터에 대해 새롭게 word2vec 모델을 학습시키는 것이 아니라 이전에 학습시킨 모델을 사용해 각 단어들의 벡터로 만들어 각 리뷰에 대한 특징값을 만든다.
test_data_vecs=get_dataset(test_sentences, model, num_features)
이렇게 리뷰를 특징 벡터로 만들었다면 이제 학습시킨 로지스틱 모델에 적용해 결과를 확인한다. 해당 데이터의 평가 데이터는 라벨이 없으므로 예측한 값을 따로 저장해서 제출하여 성능 측정
DATA_OUT_PATH='./data_out/'
test_predicted=lgs.predict(test_data_vecs)
if not os.path.exists(DATA_OUT_PATH):
os.makedirs(DATA_OUT_PATH)
ids=list(test_data['id'])
answer_dataset=pd.DataFrame({'id':ids, 'sentiment':test_predicted})
answer_dataset.to_csv(DATA_OUT_PATH+'lgs_answer.csv',index=False)
에서 되야하는데 음..... 오류가 나네..(수정 예정)
[ NLP ] 영어 텍스트 분류 (6) (0) | 2020.12.30 |
---|---|
[ NLP ] 영어 텍스트 분류 (5) (0) | 2020.12.22 |
[ NLP ] 영어 텍스트 분류 (3) (0) | 2020.12.10 |
[ NLP ] 영어 텍스트 분류 (2) (0) | 2020.12.09 |
[ NLP ] 영어 텍스트 분류 (1) (0) | 2020.12.08 |