한국어 텍스트 전처리 활용 (filtering)

4 분 소요

Introduction

  • 이전 포스팅에서 텍스트 전처리 라이브러리 사용법을 익혔다.
  • 이번 포스팅에서는 라이브러리 기능보다는, nlp 모델 성능을 높이기 위해 필요한 텍스트 전처리(필터링) 방법들에 대해 서술한다.
  • 이전 포스팅과 일부 겹치는 내용이 있을 수 있고, 부실하게 정리된 내용이 있을 수 있으나 계속 다듬을 예정.

Pre-question

  • 모델 성능을 높이기 위해 nlp 데이터 전처리 관점에서 어떤 것을 해야할까?

1. 맞춤법 정리

  • hanspell을 사용해 맞춤법이 틀린 문장들을 교정한다.
!pip install git+https://github.com/ssut/py-hanspell.git

from hanspell import spell_checker
 
sent = "무엇이 않뒈는지 체크를해줘"
spelled_sent = spell_checker.check(sent)
print(spelled_sent)
checked_sent = spelled_sent.checked 
print(checked_sent)

>>> Checked(result=True, original='무엇이 않뒈는지 체크를해줘', checked='무엇이 않데는 지 체크를 해줘', errors=2, words=OrderedDict([('무엇이', 0), ('않데는', 4), ('지', 4), ('체크를', 2), ('해줘', 2)]), time=0.7035374641418457)
>>> 무엇이 않데는  체크를 해줘

2. 문제를 일으킬 수 있는 문자들을 제거.

  • 여기 제시된 문자들은 성능 문제 이외에도, 모델 코드에 따라 런타임 에러를 발생시킬수도 있다.
    • “\u200b”, “…”, “\ufeff”와 같은 문자들을 제거한다.
    • text = re.sub(r”[+á?\xc3\xa1]”, “”, text)를 사용한다.

3. 의미가 없는 기호 제거, 변환

  • 문장 내에서 의미가 없는 기호를 제거한다. 이런 기호들은 크롤링 과정에서 부산물로도 발생할 수 있다.
    • 수학(,) -> 수학

4. 중구난방으로 표현된 수식 등 통일

  • 수식을 표현하는 방법이 다양한데, 그대로 두면 같은 의미를 가진 수식도 다른 토큰으로 치환될 수 있다.
punct_mapping = {"‘": "'", "₹": "e", "´": "'", "°": "", "€": "e", "™": "tm", "√": " sqrt ", "×": "x", "²": "2", "—": "-", "–": "-", "’": "'", "_": "-", "`": "'", '“': '"', '”': '"', '“': '"', "£": "e", '∞': 'infinity', 'θ': 'theta', '÷': '/', 'α': 'alpha', '•': '.', 'à': 'a', '−': '-', 'β': 'beta', '∅': '', '³': '3', 'π': 'pi', }
for p in punct_mapping:
    text = text.replace(p, punct_mapping[p])

5. 중복 제거

  • 중복으로 쓰인 띄어쓰기를 제거한다.
text = "하늘이    매우  맑다."
text = re.sub(r"\s+", " ", text).strip()
>>> 하늘이 매우 맑다.
  • 문장도 제거할 수 있음.
  • from collections import OrderedDict
    texts = list(OrderedDict.fromkeys(texts))
    

6. 띄어쓰기 보정

  • pykospacing은 띄어쓰기가 잘못된 문장을 보정한다.
  • 띄어쓰기가 잘못 추가된 걸 보정하지는 못하는 듯하다.
!pip install git+https://github.com/haven-jeon/PyKoSpacing.git

from pykospacing import Spacing

text = "나는밥을맛있게 먹 고싶다"
spacing = Spacing()
text = spacing(text)
print(text)

>>> 나는 밥을 맛있게   싶다

7. 품사에 따른 문장 필터링

  • koNLpy를 이용해 문장 내 품사를 분석하고, 명사(NN), 동사(V), 형용사(J) 포함 여부에 따라 문장을 필터링 할 수 있다.
  • 특히 mecab 토크나이저는 다른 토크나이저와 비교할 때, 처리속도 뿐 아니라 다양한 품사를 다루기 때문에 주로 사용된다.
!bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh)

from konlpy.tag import Mecab

NN_TAGS = ["NNG", "NNP", "NNB", "NP"]
V_TAGS = ["VV", "VA", "VX", "VCP", "VCN", "XSN", "XSA", "XSV"]
J_TAGS = ["JKS", "J", "JO", "JK", "JKC", "JKG", "JKB", "JKV", "JKQ", "JX", "JC", "JKI", "JKO", "JKM", "ETM"]
    
mecab = Mecab()
answer = []

text = "어머니가 장을 보고 오신다."
morphs = mecab.pos(text, join=False)
nn_flag, v_flag, j_flag = False, False, False
for morph in morphs:
    pos_tags = morph[1].split("+")
    for pos_tag in pos_tags:
        if not nn_flag and pos_tag in NN_TAGS:
            nn_flag = True
        if not v_flag and pos_tag in V_TAGS:
            v_flag = True
        if not j_flag and pos_tag in J_TAGS:
            j_flag = True
    if nn_flag and v_flag and j_flag:
        answer.append(text)
        break

8. 불용어 필터링

9. 최대/최소 길이 필터링

Reference

  • 네이버 AI 부트캠프 (* 강의 자료 바탕으로 재구성)