[ NLP ] 텍스트 유사도 (3)
앞서 전처리한 데이터를 사용해 유사도 측정을 위한 모델을 만든다.
처음은 XG 부스트 모델이다.
XG 부스트 텍스트 유사도 분석 모델
해당 모델로 데이터의 주어진 두 진물 문장 사이 유사도를 측정해 두 질문이 중복인지 아닌지 판단한다.
모델 소개
'eXtream Gradient Boosting'의 약자로 앙상블의 한 방법인 Boosting 기법을 이용한다.
Boosting 기법에 대해 알아보면 머신러닝 혹은 통계학에서 앙상블 기법이란 여러 개의 학습 알고리즘을 사용해 더 좋은 성능을 얻는 방법을 의미하는데 앙상블 기법에는 bagging과 boosting이라는 방법이 있다.
bagging은 여러 개의 학습 알고리즘과 모델을 통해 각각 결과를 예측하고 모든 결과를 동등하게 보고 취합해 결과를 얻는 것이다.
boosting은 결과를 다 동일하게 취합하는 bagging과는 다르게 각 결과를 순차적으로 취합하는데, 단순히 하나씩 취합하는 방법이 아니라 이전 알고리즘과 모델이 학습 후 잘못 예측한 부분에 가중치를 줘서 다시 모델로 가서 학습한다.
XG 부스트는 부스팅 기법 중 트리 부스팅 기법을 활용한 모델이다. 랜덤 포레스트 모델은 배깅에 해당하지만 트리 부스팅은 여러 개의 의사결정 트리를 사용하지만 단순히 결과의 평균을 내는 것이 아니라 오답에 가중치를 부여한다. 그리고 가중치가 적용된 오답에 대해 관심을 가지고 정답이 될 수 있도록 결과를 만들고 해당 결과에 대한 다른 오답을 찾아 다시 똑같은 작업을 반복적으로 진행하는 것.
결국 XG 부스트란 이러한 트리 부스팅 방식에 경사 하강법을 통해 최적화 하는 방법이고 연산량을 줄이기 위해 의사결정 트리를 구성할 때 병렬 처리를 사용해 빠른시간에 학습 가능하다.
모델 구현
여기선 XG 부스트 모델만을 위한 라이브러리를 쓸 예정이다. 우선 전처리한 데이터를 가져온다.
import numpy as np
DATA_IN_PATH='./data_in2/'
TRAIN_Q1_DATA_FILE='train_q1.npy'
TRAIN_Q2_DATA_FILE='train_q2.npy'
TRAIN_LABEL_DATA_FILE='train_label.npy'
#훈련 데이터를 가져온다.
train_q1_data=np.load(open(DATA_IN_PATH+TRAIN_Q1_DATA_FILE,'rb'))
train_q2_data=np.load(open(DATA_IN_PATH+TRAIN_Q2_DATA_FILE,'rb'))
train_labels=np.load(open(DATA_IN_PATH+TRAIN_LABEL_DATA_FILE,'rb'))
데이터는 각 데이터에 대해 두 개의 질문이 주어져 있는 형태다. 현재는 두 질문이 따로 구성되어 있지만 이를 하나씩 묶어 하나의 질문 쌍으로 만들어야 한다.
train_input=np.stack((train_q1_data, train_q2_data), axis=1)
넘파이의 stack함수로 두 질문을 하나의 쌍으로 만들었다. 이 데이터 형태를 출력해보면
print(train_input.shape)
전체 29만 개 정도의 데이터에 대해 두 질문이 각각 31개의 질문 길이를 가지고 있음을 확인할 수 있고 두 질문 쌍이 하나로 묶여있다.
이제 학습 데이터의 일부를 검증 데이터로 만든다.
from sklearn.model_selection import train_test_split
train_input, eval_input, train_label, eval_label=train_test_split(train_input, train_labels, test_size=0.2, random_state=4242)
전체 데이터의 20%를 검증 데이터로 만들었다. 이제 학습 데이터를 활용해 XG 부스트 모델을 학습시키고 검증 데이터로 모델의 성능을 측정한다. 모델을 구현하기 위해 'xgboost' 라이브러리를 활용한다. 없으면 설치한다.
import xgboost as xgb
train_data=xgb.DMatrix(train_input.sum(axis=1),label=train_label)
eval_data=xgb.DMatrix(eval_input.sum(axis=1),label=eval_label)
data_list=[(train_data, 'train'), (eval_data, 'valid')]
XG 부스트 모델을 사용하려면 입력값을 xgb라이브러리의 데이터 형식인 DMatrix 형태로 만들어야한다.
적용과정에서 sum을 이용하는데 이는 각 데이터의 두 질문을 하나의 값으로 만들기 위함이다. 그리고 두 데이터를 묶어서 하나의 리스트로 만든다. 이때 데이터는 각 상태의 문자열과 함께 튜플 형태로 구성한다.
이제 모델을 생성하고 학습과정을 진행한다.
params={}
params['objective']='binary:logistic'
params['eval_metric']='rmse'
bst=xgb.train(params, train_data, num_boost_round=1000, evals=data_list, early_stopping_rounds=10)
우선 모델을 만들고 학습하기 위해 몇 가지 선택해야 하는 옵션은 딕셔더리에 넣으면 된다. 이때 딕셔너리에는 모델의 목적함수와 평가 지표를 정해서 넣어야 하는데 여기서는 우선 목적 함수의 경우 이진 로지스틱 함수를 이용한다. 평가 지표의 경우 rmse를 사용한다. 이렇게 만든 인자와 학습 데이터, 데이터를 반복하는 횟수인 num_boost_round, 모델 검증 시 사용할 전체 데이터 쌍, 그리고 조기 멈춤(early stopping)을 위한 횟수를 지정한다.
데이터를 반복하는 횟수, 즉 에폭을 의미하는 값으로는 1000을 설정했는데 전체 데이터를 만번 반복해야 끝나도록 설정한 것이다. 그리고 조기 멈춤을 위한 횟수값으로 10을 설정했는데 이건 만약 10 에폭 동안 에러값이 별로 줄어들지 않을 때 조기 멈춤하는 것이다.
진행하면 각 스텝마다 학습 에러와 검증 에러를 계속 보여주며 조기 종료했는데 이는 더 이상 에러가 떨어지지 않아 조기 멈춤한 것이다.
이제 캐글을 제출하도록 만든다. 우선 전처리한 평가 데이터를 불러온다.
TEST_Q1_DATA_FILE='test_q1.npy'
TEST_Q2_DATA_FILE='test_q2.npy'
TEST_ID_DATA_FILE='test_id.npy'
test_q1_data=np.load(open(DATA_IN_PATH+TEST_Q1_DATA_FILE,'rb'),allow_pickle=True)
test_q2_data=np.load(open(DATA_IN_PATH+TEST_Q2_DATA_FILE,'rb'),allow_pickle=True)
test_id_data=np.load(open(DATA_IN_PATH+TEST_ID_DATA_FILE,'rb'),allow_pickle=True)
불러온 평가 데이터를 앞의 학습 데이터와 마찬가지로 XG 부스트 모델에 적용할 수 있게 형식에 맞춰 만든 후 모델의 predict 함수에 적용한다.
test_input=np.stack((test_q1_data, test_q2_data), axis=1)
test_data=xgb.DMatrix(test_input.sum(axis=1))
test_predict=bst.predict(test_data)
이제 평가 데이터의 id값과 예측값을 하나의 데이터프레임으로 만들고 csv파일로 저장한다.
그리고 만들어진 파일을 캐글에 제출한다
만약 성능을 더 올리고 싶다면 TF-IDF나 word2vec으로 데이터의 입력값의 형태를 바꾸는걸 추천한다고 한다.
[ 출처 : 책 ( 텐서플로와 머신러닝으로 시작하는 자연어 처리) ]