본문 바로가기
Analysis Tips

[한글 분석] kr-wordrank와 soynlp를 활용한 한글 분석

by dovah. 2022. 1. 15.
반응형

최근 업무의 일환으로 진행했던 한글 분석 내용을 좀 정리하고자 한다.

 

 

나는 이제껏 한글 분석을 할때면 늘 konlpy를 메인으로 사용하고 간간히 kr-wordrank를 섞어 쓰는 방식을 사용했다.

하지만 이번엔 그럴수가 없었는데, 1) 리뷰 데이터이며, 2) 최소한의 관리를 바탕으로 배치가 돌아야 했기 때문이다.

 

한글 리뷰는 대체 짧다.

그리고 그 와중에 오타나 띄어쓰기는 대체로 안지켜지며, 연령대에 따라 사용되는 단어 무척이나 다르다.

그렇기 때문에 일반적인 방법을 쓰면 늘 관리해야는 이슈가 따라올것 같았다.

 

그래서 생각한 것이 비지도 학습을 통한 단어 사전을 구축하고 이를 바탕으로 토큰나이징을 하는 것이다.

(사실 이렇게 하는 것이 맞는 지 모르겠다, 다만 생각보다 결과가 잘나와서...)

 

 

여기서 사용된 데이터는  https://sosomemo.tistory.com/21 가운데 첫번째 데이터를 사용했다.

 

한국어 dataset 모음

한국어를 가지고 실험을 해보기 위해 구글링을 해보았지만 생각보다 한국어 데이터가 많지 않았다. 공개되어 있는 한국어 dataset 을 링크로 남겨두고, 새로 추가 될 때 마다 갱신할 예정이다. ※

sosomemo.tistory.com

 

 

1. text normalizing

데이터 정규화 과정으로 한글을 목적이기 때문에, 완전한 단어만을 골랐다.

*'ㅋㅋㅋㅋ', 'ㅎㅎㅎㅎ' 과 같이 자음으로만 된 경우나, 영어/숫자/특수문자의 경우 제거했다.

import re
from krwordrank.hangle import normalize
temp_data['normalize_doc'] = temp_data['document'].apply(lambda x: ' '.join(re.findall(r'[가-힣]+', str(x))))

temp_text = temp_data['normalize_doc'].to_list()
texts = [normalize(t, english=False, number=False) for t in temp_text]
temp_data['normalize_doc'] = texts

1차적으로 정규표현식에 의한 단어 처리 이후에, wordrank에서 제공하는 과정을 추가했다.

*사실 두 과정이 서로 겹치는 과정으로 보인다. 정규표현식 처리만 진행도 될듯.

 

 

 

2. kr-wordrank

kr-wordrank에 대한 설명은

https://lovit.github.io/nlp/2018/04/16/krwordrank/

 

KR-WordRank, 토크나이저를 이용하지 않는 한국어 키워드 추출기

PageRank 나 HITS 같은 graph ranking 알고리즘은 natural language processing 에서 이용되기도 합니다. WordRank 는 일본어와 중국어의 unsupervised word segmentation 을 위하여 제안된 방법입니다. 하지만 이 알고리즘

lovit.github.io

여기에서 자세히 알 수 있다.

 

사실 코드랄것도 없이, 위의 블로그에 추가된 코드에 그냥 내 데이터만 반영한 형태이다.

from krwordrank.word import KRWordRank
wordrank_extractor = KRWordRank(min_count=20, max_length=20, verbose=True)
beta = 0.9
max_iter = 100
keywords, rank, graph = wordrank_extractor.extract(texts, beta, max_iter)

 

여기서 중요한 것은 'keywords'인데, 해당 결과는 dict형태로 '단어':점수로 구성되어있다.

 

 

3. L-tonkenizer

해당 토큰나이저에 대한 설명은 아래에 되어있다.

https://lovit.github.io/nlp/2018/04/09/cohesion_ltokenizer/

 

Cohesion score + L-Tokenizer. 띄어쓰기가 잘 되어있는 한국어 문서를 위한 unsupervised tokenizer

다양한 언어에서 미등록 단어를 데이터 기반으로 추출하려는 시도가 있었습니다. 단어는 연속으로 등장한 글자이며, 그 글자들은 서로 연관성이 높습니다. Characters 간의 co-occurrence 정보를 이용

lovit.github.io

 

앞서 kr-wordrank를 바탕으로 어느 정도 단어를 추려냈지만, 결과물을 확인했을 때 부족했다.

위의 데이터와는 다르게 실제 내가 사용한 데이터에서 나온 결과는 손 대야할 것이 많았다.

내가 원하는 것은 긍부정을 구분할 수 있는 단어 추출과 그 빈도수인데, 생각보다 비슷하면서 다른 단어들이 많이 보였다.

 

그래서 lemmatizer나 postagging과 같은 방식을 통해서 품사에 의해서 단어를 선정해볼까 했는데, 이마저도 생각보다 이쁘지 않았다.

* 참고 : https://lovit.github.io/nlp/2018/06/07/lemmatizer/

 

한국어 용언의 원형 복원 (Korean lemmatization)

한국어의 단어는 9 품사로 이뤄져 있습니다. 그 중 용언에 해당하는 형용사와 동사는 활용 (conjugation) 이 됩니다. 용언은 어간 (stem) 과 어미 (ending) 로 구성되어 있으며, 용언의 원형은 어간의 원

lovit.github.io

 

그래서, 한번더 토큰나이징을 해서 단어를 뽑는 것을 택했다.

soynlp에서 제공하는 몇가지 토큰나이저 중에서 내가 쓰는 데이터와 가장 잘 맞는 토큰나이저는 ltokenizer였다.

 

 

from soynlp.tokenizer import LTokenizer

ltokenizer = LTokenizer(scores = keywords)
temp_data['ltokenizer'] = temp_data['normalize_doc'].apply(lambda x: ltokenizer.tokenize(x))

앞서 단어별 점수로 구성된 keywords를 토큰나이저의 사전으로 사용했다.

이후, 각 문서별로 해당 토큰나이저를 반영했다.

 

 토큰나이저까지 반영된 결과물이다.

일단 숫자를 뺀 것이 해석을 더 어렵게 하는 것 같다.

원본 문서와 비교했을 때, 생각보다 잘된 것 같다. 특히 '재밌게'가 '재밌' + '게'로 , '재밌다'가 '재밌' + '다'로구분된 것이 인상적이다.

이렇게 됨으로써 '재밌게' 와 '재밌다' 는 같은 뜻을 가진 다른 단어이지만 실제 빈도수 에서는 '재밌'으로 통합해서 볼 수 있다.

 

 

 

 

텍스트 마이닝은 전처리가 가장 중요하다.

일반적인 데이터와는 다르게 어떤 결과물을 원하는지 따라 처리해야하는 방법이 다르고, 노력한만큼 잘 되지 않는 경우가 대다수이다. 특히, 한글 데이터의 경우 무분별한 신조어나 제대로 지켜지지 않은 맞춤법 때문에 더 힘들다.

 

위에서 사용한 방법들은 정답이 아니다. 어쩌면 konlpy를 사용해서 단어 사전을 구축하는 것이 더 맞을 수도 있다.

하지만 지금 당장 내가 바로 결과를 내볼 수 있는 방법이 위의 방법들이었다.

 

한글 분석 특히, soynlp에 대한 자료가 많이 안나오는데 실제로 사용해보면 꽤나 효과적인 걸 알 수 있다.

 

반응형

댓글