KoNLPy
한국어의 자연어 처리를 위해서 사용하는 패키지다.
Okt, Mecab, Komoran, Kkma 등 형태소 분석기를 제공한다.
KSS
한국어의 문장 토큰화를 위한 도구를 제공하는 패키지다.
PyKoSpacing
띄어쓰기가 되어 있지 않는 문장을 띄어쓰기 한 문장으로 변환하는 패키지다.
from pykospacing import Spacing
sent = '김철수는 극중 두 인격의 사나이 이광수 역을 맡았다. 철수는 한국 유일의 태권도 전승자를 가리는 결전의 날을 앞두고 10년간 함께 훈련한 사형인 유연재(김광수 분)를 찾으러 속세로 내려온 인물이다.'
spacing = Spacing()
kospacing_sent = spacing(sent)
print(kospacing_sent)
'''
김철수는 극중 두 인격의 사나이 이광수 역을 맡았다. 철수는 한국 유일의 태권도 전승자를 가리는 결전의 날을 앞두고 10년간 함께 훈련한 사형인 유연재(김광수 분)를 찾으러 속세로 내려온 인물이다.
'''
굉장히 띄어쓰기를 잘 하는 걸 확인할 수 있다.
원래 띄어쓰기가 되어 있는 문장과 다름이 없다.
Py-Hanspell
네이버 한글 맞춤법 검사기를 바탕으로 만들어진 패키지나 현재 작동하지 않는다.
SOYNLP
soynlp는 품사 태깅, 단어 토큰화 등을 지원하는 단어 토크나이저다.
비지도 학습으로 단어 토큰화를 하며, 데이터에 자주 등장하는 단어들을 분석한다.
내부적으로 단어 점수표로 동작하며, 이 점수는 응집 확률과 브랜칭 엔트로피를 활용한다.
이 용어에 대해서는 아래에서 설명하겠다.
기존의 형태소 분석기는 신조어나 형태소 분석기에 등록되지 않은 단어에 대해 제대로 구분하지 못한다.
예를 들어 별다줄 같이 문자열이 자주 연결되어 등장한다면 한 단어라고 판단하는 것이다.
또, 별다줄이라는 단어 앞 뒤에 독립된 다른 단어들이 계속해서 등장한다면 별다줄을 한 단어로 파악하는 것이다.
이것을 구현한 토크나이저가 soynlp다.
soynlp는 기존 KoNLPy와는 달리 학습 기반의 단어 토크나이저이므로 학습 과정을 거쳐야 한다.
이는 전체 코퍼스로부터 응집 확률과 브랜칭 엔트로피 단어 점수표를 만드는 과정이다.
WordExtractor.train() 함수로 코퍼스에 대한 학습을 하고,
WordExtractor.extract() 함수를 통해 단어 점수표를 계산한다.
응집 확률 (cohesion probability)
응집 확률은 내부 문자열이 얼마나 응집하여 자주 등장하는지를 판단하는 척도다.
문자열을 만드는 과정에서 왼쪽에서 순서대로 문자를 추가하면서 각 문자열이 주어졌을 때 그 다음 문자가 나올 확률을 계산하여 누적곱을 한 값이다. 이 값이 높을수록 전체 코퍼스에서 이 문자열 시퀀스는 하나의 단어로 등장할 가능성이 높다.
쉽게 말하면 해당 문자 다음에 나올 문자에 대한 확률을 계산한 값으로
특정 문자열이 얼마나 같이 등장하는지를 판단한 것이다.
교재의 예제에 따르면 '반포한강공원에' 라는 문자 시퀀스에 대해 다음과 같은 응집확률이 계산된다고 한다.
print(word_score_table["반포한"].cohesion_forward)
print(word_score_table["반포한강공원"].cohesion_forward)
print(word_score_table["반포한강공원에"].cohesion_forward)
'''
0.08838002913645132
0.37891487632839754
0.33492963377557666
'''
'반포항' 보다는 '반포한강공원'이 응집 확률이 높지만, '반포한강공원에'는 응집 확률이 낮은 걸 볼 수 있다.
따라서 하나의 단어로 판단하기 적합한 문자열은 '반포한강공원'이다.
브랜칭 엔트로피 (branching entropy)
브랜칭 엔트로피는 확률 분포의 엔트로피 값을 사용한다.
주어진 문자열에서 얼마나 다음 문자가 등장할 수 있는지를 판단하는 척도다.
사자성어 퀴즈에서 앞 두단어를 보여줬을 때 뒤 단어를 맞추는 느낌과 비슷하다.
단어의 앞 부분 일부 뒤에 나올 수 있는 문자들의 다양성을 의미한다.
브랜칭 엔트로피를 문자 시퀀스에서 다음 문자 예측을 위해 헷갈리는 정도라고 비유할 수 있다.
브랜칭 엔트로피 값은 하나의 단어에 가까워질수록 점점 줄어든다.
print(word_score_table["디스"].right_branching_entropy)
print(word_score_table["디스플"].right_branching_entropy)
'''
1.6371694761537934
-0.0
'''
교재의 예제에서 사용한 코퍼스에서 '디스' 부분만으로는 다양한 뒷글자를 예측할 수 있다.
그러나 '디스플'까지 주어진 경우 다음 글자가 '레'로 확실하므로 0.0이라는 값을 출력한다.
print(word_score_table["디스플레이"].right_branching_entropy)
# 3.1400392861792916
'디스플레이'를 넣으면 갑자기 엔트로피 값이 확 오른다.
이 이유는 디스플레이 뒤에 다양한 조사가 올 수 있기 때문이다.
이를 이용해 하나의 단어를 판단할 수 있다.
L tokenizer
한국어의 어절 토큰은 주로 L토큰 + R토큰의 형식을 가진다.
L 토크나이저는 L토큰 + R토큰으로 나누되, 분리 기준을 점수가 가장 높은 L토큰을 찾아내는 원리다.
- L토큰: 어절의 앞 부분을 의미한다. 주로 의미를 가지는 실질적인 어간이다.
- R토큰: 어절의 뒷 부분을 의미한다. 주로 문법적 요소인 접사다.
이 점수를 결정하는 기준은 다양하다.
빈도 기반으로 점수를 결정하기도 하고, 언어 모델이나 통계적 모델 기반 점수를 사용하기도 한다.
MaxXcoreTokenizer
최대 점수 토크나이저는 띄어쓰기가 되어 있지 않은 문장에서 점수가 높은 글자 시퀀스를 찾아내는 것이다.
normalizer
채팅 같은 경우 ㅋㅋㅋㅋ, ㅎㅎㅎㅎ, ㅋㅋㅋㅋㅋㅋ 와 같은 이모티콘을 다 다르게 분류하는 것은 불필요하다.
이런 부분을 정규화 하기 위해 emoticon_normalisze() 함수를 사용한다.
from soynlp.normalizer import *
print(emoticon_normalize('앜ㅋㅋㅋㅋ이영화존잼쓰ㅠㅠㅠㅠㅠ', num_repeats=2))
print(emoticon_normalize('앜ㅋㅋㅋㅋㅋㅋㅋㅋㅋ이영화존잼쓰ㅠㅠㅠㅠ', num_repeats=2))
print(emoticon_normalize('앜ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ이영화존잼쓰ㅠㅠㅠㅠㅠㅠ', num_repeats=2))
print(emoticon_normalize('앜ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ이영화존잼쓰ㅠㅠㅠㅠㅠㅠㅠㅠ', num_repeats=2))
'''
아ㅋㅋ영화존잼쓰ㅠㅠ
아ㅋㅋ영화존잼쓰ㅠㅠ
아ㅋㅋ영화존잼쓰ㅠㅠ
아ㅋㅋ영화존잼쓰ㅠㅠ
'''
num_repeats 인자를 통해 몇 글자로 줄여서 나타낼 건지 정할 수 있다.
이모티콘에 한정되지 않고 repeat_normalize() 함수를 이용해 글자도 줄일 수 있다.
print(repeat_normalize('와하하하하하하하하하핫', num_repeats=2))
print(repeat_normalize('와하하하하하하핫', num_repeats=2))
print(repeat_normalize('와하하하하핫', num_repeats=2))
'''
와하하핫
와하하핫
와하하핫
'''
Customized KoNLPy
한국어는 띄어쓰기만으로 단어들을 잘 분리할 수 없다.
사람 이름 같은 경우 형태소 분석기에 사용자 사전을 추가하는 등 별도의 처리를 해야한다.
customized_konlpy에서 제공하는 형태소 분석기 Twitter를 사용하면 쉽게 추가할 수 있다.
add_dictionary('단어', '품사') 함수를 이용하여 사전을 추가할 수 있다.
from ckonlpy.tag import Twitter
twitter = Twitter()
twitter.add_dictionary('은경이', 'Noun')
twitter.morphs('은경이는 사무실로 갔습니다.')
'''
['은경이', '는', '사무실', '로', '갔습니다', '.']
'''
형태소 분석기에 사전을 추가하면 '은경이'를 제대로 분리하는 것을 볼 수 있다.
add_dictionary() 함수로 '은경이'를 추가하지 않는다면 '은', '경이'로 분리된다.
'AI > NLP' 카테고리의 다른 글
[Wiki] 카운트 기반 단어 표현 (1) | 2024.06.03 |
---|---|
[Wiki] 언어 모델 (1) | 2024.06.02 |
[Wiki] 원-핫 인코딩 (0) | 2024.06.02 |
[Wiki] 패딩 (0) | 2024.06.01 |
[Wiki] 정수 인코딩 (0) | 2024.06.01 |