프로그래밍/NLP

[ NLP ] 한글 텍스트 분류 (2)

Yanoo 2021. 1. 13. 23:21
728x90
반응형

데이터 전처리

앞서 분석한 데이터 기반으로 전처리를 진행한다. 라이브러리를 부르면

import numpy as np
import pandas as pd
import re
import json
from konlpy.tag import Okt
from tensorflow.python.keras.preprocessing.sequence import pad_sequences
from tensorflow.python.keras.preprocessing.text import Tokenizer


DATA_IN_PATH='./data_in/'

train_data=pd.read_csv(DATA_IN_PATH+'ratings_train.txt', header=0, delimiter='\t', quoting=3)

불러온 라이브러리는 대부분 영어 전처리와 같고 다른점은 한글 토그나이징 도구인 KoNLPy를 사용한다는 점이다.

 

train_data['document'][:5]

보면 영어와 다르게 HTML 태그가 없어서 Beautiful Soup은 안쓴다. 하지만 특수문자나 숫자는 지워야 하는데 먼저 첫 번째 리뷰를 전처리 해보면, (정규 표현식을 이용해 제거한다.)

review_text=re.sub("[^가-힣ㄱ-ㅎㅏ-ㅣ\\s]","",train_data['document'][0])
print(review_text)

특수문자가 제거됐고 이제 불용어를 제거하기 위해 문장 단어로 나눠야한다. okt를 이용한다. 그리고 형태소 분석기를 사용할 때 어간 추출을 사용해 어간이 추출된 단어로 나눈다.

okt=Okt()
review_text=okt.morphs(review_text,stem=True)
print(review_text)

결과를 보면 문장이 각 단어로 나눠져 있다. 불용어를 제거해야하는데 한글 불용어는 파이썬 라이브러리가 없어 직접 불용어 사전을 만들어 제거해야한다.

stop_words=set(['은','는','이','가','하','아','것','들','의','있','되','수','보','주','등','한'])
clean_review=[token for token in review_text if not token in stop_words]

print(clean_review)

 

 

이제 전체 데이터에 적용하기 위해 하나의 함수로 만든다.

def preprocessing(review, okt, remove_stopwords = False, stop_words = []):
    # 함수의 인자는 다음과 같다.
    # review : 전처리할 텍스트
    # okt : okt 객체를 반복적으로 생성하지 않고 미리 생성후 인자로 받는다.
    # remove_stopword : 불용어를 제거할지 선택 기본값은 False
    # stop_word : 불용어 사전은 사용자가 직접 입력해야함 기본값은 비어있는 리스트
    
    # 1. 한글 및 공백을 제외한 문자 모두 제거.
    review_text = re.sub("[^가-힣ㄱ-ㅎㅏ-ㅣ\\s]", "", review)
    
    # 2. okt 객체를 활용해서 형태소 단위로 나눈다.
    word_review = okt.morphs(review_text, stem=True)
    
    if remove_stopwords:
        
        # 불용어 제거(선택적)
        word_review = [token for token in word_review if not token in stop_words]
        
   
    return word_review

 

전처리 과정을 함수로 정의했으니 학습 데이터에 대한 전처리를 진행한다.

stop_words=set(['은','는','이','가','하','아','것','들','의','있','되','수','보','주','등','한'])
okt=Okt()
clean_train_review=[]

for review in train_data['document']:
    # 비어있는 데이터에서 멈추지 않도록 문자열인 경우에만 진행
    if type(review)==str:
        clean_train_review.append(preprocessing(review, okt, remove_stopwords=True, stop_words=stop_words))
    else:
        # string이 아니면 비어있는 값 추가
        clean_train_review.append([])

clean_train_review[:4]

 

이제 해당 리뷰를 인덱스 벡터로 변환하면 되는데, 평가 데이터도 동일하게 진행하기에 평가 데이터도 앞 과정을 똑같이 수행한다.

test_data=pd.read_csv(DATA_IN_PATH+'ratings_test.txt', header=0, delimiter='\t', quoting=3)

clean_test_review=[]

for review in test_data['document']:
    # 빈 데이터에서 멈추지 않도록 문자열인 경우에만 진행
    if type(review)==str:
        clean_test_review.append(preprocessing(review, okt, remove_stopwords=True, stop_words=stop_words))
    else:
        # stirng이 아니면 비어있는 값 추가
        clean_test_review.append([])

 

이제 학습 데이터와 평가 데이터에 대해 인덱스 벡터로 바꾼 후 패딩 처리만 하면 모든 전처리가 끝난다. 텐서플로의 전처리 모듈을 사용하는데, 토크나이징 객체를 만든 후 학습 데이터에 대해서만 적용하고 해당 객체를 사용해 두 데이터를 인덱스 벡터로 만든다. 마지막으로 데이터들을 패딩처리하면 된다.

tokenizer=Tokenizer()
tokenizer.fit_on_texts(clean_train_review)
train_sequences=tokenizer.texts_to_sequences(clean_train_review)
test_sequences=tokenizer.texts_to_sequences(clean_test_review)

# 단어 사전 형태
word_vocab=tokenizer.word_index

# 문장 최대 길이
MAX_SEQUENCE_LENGTH=8

# 학습 데이터를 벡터화
train_inputs=pad_sequences(train_sequences, maxlen=MAX_SEQUENCE_LENGTH, padding='post')
# 학습 데이터의 라벨
train_labels=np.array([train_data['label']])

# 평가 데이터를 벡터화
test_inputs=pad_sequences(test_sequences, maxlen=MAX_SEQUENCE_LENGTH, padding='post')
# 평가 데이터의 라벨
test_labels=np.array(test_data['label'])

패딩 처리할 때 최대 길이를 8로 했는데 이유는 데이터 분석 과정에서 단어 평균 개수가 약 8개였기때문.

 

학습, 평가 데이터에 대해 입력값과 라벨값을 만든 후에 모델링에서 사용하도록 저장한다.

TRAIN_INPUT_DATA='nsmc_train_input.npy'
TRAIN_LABEL_DATA='nsmc_train_label.npy'
TEST_INPUT_DATA='nsmc_test_input.npy'
TEST_LABEL_DATA='nsmc_test_label.npy'
DATA_CONFIGS='data_configs.json'

data_configs={}

data_configs['vocab']=word_vocab

# vocab size 추가
data_configs['vocab_size']=len(word_vocab)+1

import os
# 저장하는 디렉터리가 존재하지 않으면 생성
if not os.path.exists(DATA_IN_PATH):
    os.makedirs(DATA_IN_PATH)

# 전처리된 학습 데이터를 넘파이 형태로 저장
np.save(open(DATA_IN_PATH+TRAIN_INPUT_DATA,'wb'),train_inputs)
np.save(open(DATA_IN_PATH+TRAIN_LABEL_DATA,'wb'),train_labels)
# 전처리된 평가 데이터를 넘파이 형태로 저장
np.save(open(DATA_IN_PATH+TEST_INPUT_DATA,'wb'),test_inputs)
np.save(open(DATA_IN_PATH+TEST_LABEL_DATA,'wb'),test_labels)

# 데이터 사전을 json 형태로 저장
json.dump(data_configs, open(DATA_IN_PATH+DATA_CONFIGS,'w'), ensure_ascii=False)

 

전처리는 끝냈고, 다음은 모델을 만든다.

 

 

 

[ 출처 : 책 ( 텐서플로와 머신러닝으로 시작하는 자연어 처리) ]

728x90
반응형