최근 업무의 일환으로 진행했던 한글 분석 내용을 좀 정리하고자 한다.
나는 이제껏 한글 분석을 할때면 늘 konlpy를 메인으로 사용하고 간간히 kr-wordrank를 섞어 쓰는 방식을 사용했다.
하지만 이번엔 그럴수가 없었는데, 1) 리뷰 데이터이며, 2) 최소한의 관리를 바탕으로 배치가 돌아야 했기 때문이다.
한글 리뷰는 대체 짧다.
그리고 그 와중에 오타나 띄어쓰기는 대체로 안지켜지며, 연령대에 따라 사용되는 단어 무척이나 다르다.
그렇기 때문에 일반적인 방법을 쓰면 늘 관리해야는 이슈가 따라올것 같았다.
그래서 생각한 것이 비지도 학습을 통한 단어 사전을 구축하고 이를 바탕으로 토큰나이징을 하는 것이다.
(사실 이렇게 하는 것이 맞는 지 모르겠다, 다만 생각보다 결과가 잘나와서...)
여기서 사용된 데이터는 https://sosomemo.tistory.com/21 가운데 첫번째 데이터를 사용했다.
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/
여기에서 자세히 알 수 있다.
사실 코드랄것도 없이, 위의 블로그에 추가된 코드에 그냥 내 데이터만 반영한 형태이다.
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/
앞서 kr-wordrank를 바탕으로 어느 정도 단어를 추려냈지만, 결과물을 확인했을 때 부족했다.
위의 데이터와는 다르게 실제 내가 사용한 데이터에서 나온 결과는 손 대야할 것이 많았다.
내가 원하는 것은 긍부정을 구분할 수 있는 단어 추출과 그 빈도수인데, 생각보다 비슷하면서 다른 단어들이 많이 보였다.
그래서 lemmatizer나 postagging과 같은 방식을 통해서 품사에 의해서 단어를 선정해볼까 했는데, 이마저도 생각보다 이쁘지 않았다.
* 참고 : https://lovit.github.io/nlp/2018/06/07/lemmatizer/
그래서, 한번더 토큰나이징을 해서 단어를 뽑는 것을 택했다.
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에 대한 자료가 많이 안나오는데 실제로 사용해보면 꽤나 효과적인 걸 알 수 있다.
'Analysis Tips' 카테고리의 다른 글
데이터 분석가가 되려면 어떤 스킬이 필요할까? (0) | 2023.07.08 |
---|---|
주저리 적어보는 데이터 분석 (0) | 2023.07.07 |
[API] 주택 구입 부담 지수 API 연결 (2) | 2021.08.28 |
[공공데이터] 수집한 데이터 flask로 표현해보기 (0) | 2021.07.31 |
[공공데이터] DB에 저장하고 Flask와 연결해보기 (0) | 2021.01.10 |
댓글