문장 자동완성 프로젝트

머신 러닝 공부를 하기위해 사용 가능한 프로그램이면서, 이미 나와있어 구체적인 기능을 알 수 있는 프로젝트로

문장 자동완성 프로젝트를 해봅니다.


프로젝트 개발 순서

1. 학습에 필요한 데이터 얻기

2. 데이터 가공하기(전처리)

3. 모델 설계하기(학습)

4. 학습 후 평가

 

데이터 얻기

이번 프로젝트에서는, 국립국어원의 말뭉치 "위험한 실험 : 교육개혁의 정치학(1999)"를 사용하겠습니다.

링크 : https://ithub.korean.go.kr/user/total/database/corpusView.do

다운로드 받아 파이썬 파일과 같은 디렉토리에 위치시킵니다.

 

데이터 가공하기(전처리)

다운로드 받은 데이터에는 html태그 및 특수문자와 같은 학습과정에 방해가 되는 것들이 있습니다.

이를 학습전에 먼저 제거하고, 학습에 필요한 형식으로 만드는 과정을 진행합니다.

 

다운로드 받은 말뭉치에 쓰여진 HTML 태그 및 특수문자는 정규표현식을 이용해 해당 내용을 지워줍니다.

또한, 박상길님이 개발한 KSS(Korean Sentence Splitter)를 이용해 문단을 문장 단위로 나눠 준 후

sentence_list에 넣습니다.

import re
import kss
f = open('4BH00005.txt', encoding="utf8")
i=0
sentence_list = []
while True:
    line = f.readline()
    if not line: break
    if line != '\n':
        i=i+1
        line = re.sub('<.+?>', '', line, 0, re.S)
        line = re.sub('\(.+?\)', '', line, 0, re.S)
        line = re.sub('\[.+?\]', '', line, 0, re.S)
        line = re.sub('\{.+?\}', '', line, 0, re.S)
        line = re.sub('《.+?》', '', line, 0, re.S)
        line = re.sub('[-=+,#/\?:^$.@*\"※~&%ㆍ!『』\‘|\(\)\[\]\<\>`\'…《》\{\}_「」±√]', '', line,0,re.S)
        line = line.lower()
        if len(line) >10:
            sentence_list+= kss.split_sentences(line)
f.close()
print(len(sentence_list)) #출력결과 : 2264
#2264개의 문장이 sentence_list에 들어갔습니다.

케라스의 토크나이져를 이용해 토큰화를 진행합니다.

vocab_size를 총 단어의 갯수보다 1 크게 해줍니다.

그 이유는 단어 100개를 토큰화 및 원핫 인코딩을 진행하면, 크기가 101인 배열로 인코딩되기 때문입니다. 

from tensorflow.keras.preprocessing.text import Tokenizer
t = Tokenizer()
t.fit_on_texts(sentence_list)
vocab_size = len(t.word_index) + 1
print('단어 집합의 크기 : %d' % vocab_size) #출력결과 : 13809

이제 정수인코딩 및 하나의 문장을 여러 단계적으로 분리합니다.

sequences = list()

for line in sentence_list:
    encoded = t.texts_to_sequences([line])[0] # 각 샘플에 대한 정수 인코딩
    for i in range(1, len(encoded)):
        sequence = encoded[:i+1]
        sequences.append(sequence)

sequences[:11] # 11개의 샘플 출력

샘플출력 결과는 다음과 같습니다.

[[4919, 232],
 [4919, 232, 25],
 [4919, 232, 25, 2797],
 [4919, 232, 25, 2797, 4920],
 [8, 609],
 [8, 609, 610],
 [8, 609, 610, 611],
 [8, 609, 610, 611, 215],
 [8, 609, 610, 611, 215, 1169],
 [8, 609, 610, 611, 215, 1169, 232],
 [8, 609, 610, 611, 215, 1169, 232, 1170]]

정수 인코딩 된 정수를 이용해 단어를 얻기 위해 정수를 key, 단어를 value로 하는 index_to_word 딕셔너리를 만듭니다.

index_to_word={}
for key, value in t.word_index.items(): # 인덱스를 단어로 바꾸기 위해 index_to_word를 생성
    index_to_word[value] = key

단계적으로 분리된 각 줄들을 레이블로 분리하기 전에, 같은 크기로 만들기 위해 가장 긴 문장으로 패딩 작업을 수행합니다.

패딩 작업을 한 뒤에는 문장들의 가장 마지막 단어를 y 레이블로 분리합니다.

분리된 y레이블에 대해 원-핫 인코딩을 수행합니다.

max_len=max(len(l) for l in sequences)
from tensorflow.keras.preprocessing.sequence import pad_sequences
sequences = pad_sequences(sequences, maxlen=max_len, padding='pre')
import numpy as np
sequences = np.array(sequences)
X = sequences[:,:-1] # 가장 마지막을 제외하고
y = sequences[:,-1] # 가장 마지막만
from tensorflow.keras.utils import to_categorical
y = to_categorical(y, num_classes=vocab_size)

이제 모델을 설계합니다.

 

모델 설계하기(학습)

전처리 된 데이터를 모델에 학습시킵니다.

이번 프로젝트는 RNN의 변형인 GRU 모델을 이용하여 학습하겠습니다.

GRU 모델 설명 : https://wikidocs.net/22889

 

학습 후 평가

테스트를 통해 학습이 의도한대로 되었는지 확인합니다.

테스트 데이터를 이용해 정확도와 희소문제가 발생하였는지 등을 확인하고 보완합니다.

 

 


이번 프로젝트는 다음을 참고하여 진행됩니다.

딥 러닝을 이용한 자연어 처리 입문(Won Joon Yoo) : https://wikidocs.net/book/2155