[NLP] 텍스트 전처리: 파이썬에서 띄어쓰기, 문장 분리 라이브러리 사용하기
들어가며
자연어 처리 모델은 입력 데이터의 형태에 굉장히 의존합니다. 동일한 의미를 가진 단어임에도 매번 형태가 달라진다면 모델의 성능을 보장할 수 없습니다. 텍스트를 최대한 규칙적이고 일관된 형태로 변환하기 위해 불필요한 정보들(불용어, 이모티콘, 특수기호, 이메일, 전화번호, 주소 등)를 제거하고, 맞춤법과 띄어쓰기 교정하기, 문장을 분리하기 등 다양한 전처리를 거치는데요,본 포스트에서는 텍스트 전처리 중 띄어쓰기와 문장 분리를 하는 방법들을 알아보겠습니다!
파이썬 ver: 3.8.10
띄어쓰기 적용하기: PyKoSpacing
띄어쓰기가 아예 되어있지 않은 한국어 문장 "아버지가방에들어가신다"는 두 가지 의미로 이해될 수 있습니다. "아버지가 방에 들어가신다"와 "아버지 가방에 들어가신다"로요. 띄어쓰기가 잘 되어있지 않다면 발화자의 의도를 정확하게 이해할 수 없습니다. 사람도 헷갈려하는 문장을 모델은 더 헷갈려하는 것이 당연하죠. 모델이 명확하게 텍스트를 이해하기 위해서 띄어쓰기는 매우 중요한 전처리입니다. 특히나 한국어는 더욱 그렇죠..
띄어쓰기를 위해서 pykospacing 을 설치하여 전처리를 수행해보겠습니다. 아래 코드를 실행하여 라이브러리를 설치합니다.
pip install git+https://github.com/haven-jeon/PyKoSpacing.git
스포츠 기사(출처)에서 기사 두 문장을 가져와 띄어쓰기를 적용해보겠습니다. 띄어쓰기가 잘되는지 확인해보기 위해 먼저 띄어쓰기 없는 문장으로 만들었습니다.
from pykospacing import Spacing
sentence = 'V리그 여자부 흥국생명이 김연경과 옐레나의 쌍포를 앞세워 가장 먼저 10승 고지를 밟았다. 흥국생명은 25일 홈경기에서 도로공사를 상대로 세트 스코어 3대0(27-25 25-20 25-19) 완승을 거뒀다.'
new_sentence = sentence.replace(" ", '') # 띄어쓰기가 없는 문장 임의로 만들기
print(new_sentence)
V리그여자부흥국생명이김연경과옐레나의쌍포를앞세워가장먼저10승고지를밟았다.흥국생명은25일홈경기에서도로공사를상대로세트스코어3대0(27-2525-2025-19)완승을거뒀다.
Spacing 클래스를 불러와 띄어쓰기 없는 문장 new_sentence를 적용해보았습니다. "세트 스코어" 단어와 세트 점수들을 제오하고는 띄어쓰기가 잘 된 것을 확인할 수 있었습니다.
spacing = Spacing()
kospacing_sent = spacing(new_sentence)
print(sentence)
print(kospacing_sent)
V리그 여자부 흥국생명이 김연경과 옐레나의 쌍포를 앞세워 가장 먼저 10승 고지를 밟았다. 흥국생명은 25일 홈경기에서 도로공사를 상대로 세트 스코어 3대0(27-25 25-20 25-19) 완승을 거뒀다.
V리그 여자 부흥국생명이 김연경과 옐레나의 쌍포를 앞세워 가장 먼저 10승 고지를 밟았다. 흥국생명은 25일 홈경기에서 도로공사를 상대로 세트스코어 3대0(27-2525-2025-19) 완승을 거뒀다.
그리고 py-hanspell이라고 하는 라이브러리도 있는데, 현재 기준(23/11/26) 코드 에러가 발생하여 빠른 진행이 어려웠습니다. 다음에 고쳐지면 한번 다시 설치해서 해봐야겠네요..!
문장 분리 라이브러리
자연어 처리 모델에 하나의 문장만을 넣을 것인지, 하나의 문단을 넣을 것인지, 문서 전체를 넣을 것인지도 중요한 의사결정 사항 중 하나입니다. Q&A 처럼 입력값으로 질문이 들어가야 한다는 등 과제의 정의가 명확하다면 고민할 필요가 당연히 없겠지만, 속성 기반 감성분석이나 NER 과 같은 과제는 입력의 단위가 모델의 성능에 영향을 주기도 합니다. 하나의 문장만을 입력으로 넣으면 해당 문장의 뜻을 이해하기는 쉽겠지만 다른 문장과의 연결, 흐름은 이해할 수 없게 됩니다. 여러 문장이 연이어서 제공되면 문장 사이의 관계, 흐름을 이해할 수 있게되지만 그만큼 이해하기 위해 처리 시간이 늘어날 수 있겠죠. 텍스트 전처리 단계에서 문장 분리를 적용하여 어떤 단위를 입력으로 사용해야 모델 성능이 좋은지 실험하는 것도 중요한 단계 중 하나입니다.
kss(Korean sentence segmentation)
kss는 c++로 구현되어 빠른 속도를 자랑하는 문장 분리 라이브러리입니다. 내부 알고리즘을 통해 문장이 구분되지 않은 텍스트를 넣었을 때 이들을 문장 단위로 구분해주는 split_sentences 함수를 제공해주고 있습니다.
여기서는 성능을 획기적으로 개선할 수 있는 다른 방식의 접근이 필요하다. 이에 따라 종결형에 사용되는 음절을 골라내어 이전/이후 음절을 매칭하여 문장을 구분했다. 여기서 골라낸 음절은 [다/요/.!?] 이며, 이전/이후 패턴을 미리 정의해 두고 이후 패턴은 2음절까지 확장해 나가며, 어느 부위에서 정확히 끊어낼지 Sentence Boundary를 지정했다.
출처: https://docs.likejazz.com/kss/
아까 방문했던 스포츠 기사에서 좀 더 연속된 문장을 가져와 문장 분리 함수를 적용해보았습니다. 마침표와 엔터를 모두 제거하고 적용해보니 실제로 4문장인 것을 2문장으로 구분하고 있었습니다.
pip install kss # 설치
from kss import split_sentences
text = """
V리그 여자부 흥국생명이 김연경과 옐레나의 쌍포를 앞세워 가장 먼저 10승 고지를 밟았다 흥국생명은 25일 홈경기에서 도로공사를 상대로 세트 스코어 3대0(27-25 25-20 25-19) 완승을 거뒀다 7연승을 내달린 흥국생명은 10승 1패(승점28)로 1위를 굳게 지켰다 반면, 도로공사는 2연패에 빠지며 3승 8패(승점12)로 6위에 머물렀다
"""
for sent in split_sentences(text):
print(sent)
V리그 여자부 흥국생명이 김연경과 옐레나의 쌍포를 앞세워 가장 먼저 10승 고지를 밟았다
흥국생명은 25일 홈경기에서 도로공사를 상대로 세트 스코어 3대0(27-25 25-20 25-19) 완승을 거뒀다 7연승을 내달린 흥국생명은 10승 1패(승점28)로 1위를 굳게 지켰다 반면, 도로공사는 2연패에 빠지며 3승 8패(승점12)로 6위에 머물렀다
kiwi(Korean Intelligent Word Identifier)
kss의 결과가 조금 아쉬워 다른 라이브러리도 적용해보기로 했습니다. 바로 kiwipiepy 입니다. C++로 작성되었고, 다른 패키지에 의존성도 없다고 하네요. 문장 분리뿐만 아니라 형태소 분석, 사용자 사전 추가 등 다양한 기능을 제공하고 있습니다. 다른 문장 분리 라이브러리들과 비교해보았을 때, 비교적 빠르면서도 성능이 우수하다고 합니다.
pip install kiwipiepy # 설치
from kiwipiepy import Kiwi
kiwi = Kiwi()
kiwi.split_into_sents(text)
[Sentence(text='V리그 여자부 흥국생명이 김연경과 옐레나의 쌍포를 앞세워 가장 먼저 10승 고지를 밟았다', start=1, end=50, tokens=None, subs=[]),
Sentence(text='흥국생명은 25일 홈경기에서 도로공사를 상대로 세트 스코어 3대0(27-25 25-20 25-19) 완승을 거뒀다', start=51, end=114, tokens=None, subs=[]),
Sentence(text='7연승을 내달린 흥국생명은 10승 1패(승점28)로 1위를 굳게 지켰다', start=115, end=154, tokens=None, subs=[]),
Sentence(text='반면, 도로공사는 2연패에 빠지며 3승 8패(승점12)로 6위에 머물렀다', start=155, end=195, tokens=None, subs=[])]
이전의 kss는 4문장을 2문장으로 분리한 반면, kiwi는 4문장으로 잘 분리해주고 있었습니다.
마치며
위 내용은 하나의 텍스트에 대해 실험한 것을 정리한 것에 불과합니다. 텍스트의 내용에 따라, 이전에 어떤 전처리들을 적용했는지에 따라 결과는 달라질 수 있습니다! 어떤 것이 좋다고 단정적으로 얘기할 수 없으니, 여러 라이브러리, 함수의 다양한 파라미터들을 적용해보며 어떤 방식을 사용했을 때 결과가 더 좋은지 직접 실험해봐야 합니다. 함수 적용이 어렵지 않으니, 띄어쓰기, 문장 분리 전처리에 위 라이브러리들을 직접 적용해보고 결과를 비교해보길 바랍니다~
참고
02-10 한국어 전처리 패키지(Text Preprocessing Tools for Korean Text)
유용한 한국어 전처리 패키지를 정리해봅시다. 앞서 소개한 형태소와 문장 토크나이징 도구들인 KoNLPy와 KSS(Korean Sentence Splitter)와 함께 유용하게 사…
wikidocs.net
https://docs.likejazz.com/kss/
한글 문장 분리기 · The Missing Papers
한글 문장 분리기 18 Aug 2019 NLP에서 매우 중요한 작업 중 하나인 문장 분리 기능을 빠른 속도로 처리할 수 모듈을 만든다. 2020년 12월 21일 공지 추가 2019년 8월 18일 초안 작성 공지 작년 즈음에 카
docs.likejazz.com
https://github.com/bab2min/kiwipiepy
GitHub - bab2min/kiwipiepy: Python API for Kiwi
Python API for Kiwi. Contribute to bab2min/kiwipiepy development by creating an account on GitHub.
github.com