Word Sense
한글 단어들은 동음이의어가 참 많다.
'차' 를 예로 들어보자.
- 잎이나 뿌리 등을 우려 마시는 것
- 바퀴가 달린 운송수단
- 짐을 실어 그 분량을 세는 단위
- 장기 말 중 '車'
- 빼기의 다른 말
- 몇 주차... 등의 기간을 나타내는 말 etc...
이 때문에 우리는 다의어(Polysemy)와 동형어(Homonym)를 알아야 한다.
- 다의어(Polysemy) : 근본의미 이외에도 다른 뜻으로도 쓰는 단어
- 동형어(Homonym) : 단어의 형태만 같을 뿐 서로 전혀 다른 의미를 지님
이런 경우를 처리하기 위해 필요한 것이 Word Sense Disambiguation(WSD) 이다.
WordNet
- 어휘 분류 사전
- 상위어(Hypernym)나 하위어(Hyponym)에 대한 것이 잘 정리되어 있는 것이 특징
- NLTK Library OR Download(http://wordnetweb.princeton.edu/perl/webwn) - english
- KorLex(korlex.pusan.ac.kr) OR Korean WordNet(wordnet.kaist.ac.kr) - korean
WordNet 은 계층 구조를 가지고 있다. 예를 들어 Person(사람) 이라는 단어의 하위 계층에 Student(학생) 이나 Singer(가수) 등이 있을 것입니다. 이러한 계층 구조를 통해 각 두 단어들의 거리를 계산하여 유사도를 확인할 수 있습니다.
이제 간단한 WordNet 실습을 해보겠습니다.
!pip install nltk==3.2.5
import nltk
nltk.download('wordnet')
from nltk.corpus import wordnet as wn
저의 경우에는 nltk 3.2.5 버전을 설치하였습니다. 그리고 다음과 같이 wordnet을 다운받고 선언하였습니다.
wn.synsets('people')
------------------------------------
[Synset('people.n.01'),
Synset('citizenry.n.01'),
Synset('people.n.03'),
Synset('multitude.n.03'),
Synset('people.v.01'),
Synset('people.v.02')]
예시 단어 'people' 에 대한 동의어 집합을 출력하였습니다.
wn.synsets('people')[0].hypernyms()
-----------------------------------------
[Synset('group.n.01')]
hypernyms( )을 통해 상위 계층을 불러왔습니다. 결국 group > people 이라는 의미입니다.
그렇다면 최상위계층까지 가는 단계들을 한 번에 보기 위해 함수를 만들어 보겠습니다.
def hypernyms(word):
current_pos = wn.synsets(word)[0]
yield current_pos
while 1:
try:
current_pos = current_pos.hypernyms()[0]
yield current_pos
except:
break
for _ in hypernyms('firefighter'):
print(_)
-----------------------------------------------
Synset('fireman.n.04')
Synset('defender.n.01')
Synset('preserver.n.03')
Synset('person.n.01')
Synset('causal_agent.n.01')
Synset('physical_entity.n.01')
Synset('entity.n.01')
hypernyms 라는 함수를 만들어서 단어를 적용시키면 상위 모든 계층들이 나오는 것을 알 수 있었다.
for _ in hypernyms('mailman'):
print(_)
-----------------------------------------
Synset('mailman.n.01')
Synset('deliveryman.n.01')
Synset('employee.n.01')
Synset('worker.n.01')
Synset('person.n.01')
Synset('causal_agent.n.01')
Synset('physical_entity.n.01')
Synset('entity.n.01')
'mailman' 을 적용시켜도 정상적으로 나오는 것을 보였다.
그렇다면 'firefighter' 와 'mailman' 사이의 거리를 측정해 유사도를 판별할 수 있지 않을까?
# 단어 간 거리 측정하기
def distance(word1, word2):
word1_hypernyms = [_ for _ in hypernyms(word1)]
for i, word2_hypernyms in enumerate(hypernyms(word2)):
try:
return i + word1_hypernyms.index(word2_hypernyms)
except:
continue
distance('firefighter', 'mailman')
-----------------------------------
7
hypernyms( ) 함수를 통해서 word1_hypernyms 에 word1 단어의 전 상위 계층을 담는다.
그리고 index 4번째 'person' 에서 firefighter 의 인덱스 3에 있는 'person' 과 만나 7이 측정되었다.
# 유사도 측정
import numpy as np
def similarity(word1, word2):
return -np.log(distance(word1, word2))
print(similarity('firefighter', 'mailman'))
-----------------------------------------------
-1.9459101490553132
이로써 'firefighter' 와 'mailman' 사이의 유사도는 약 -1.946 이 나오게 되었다.
Word Feature Vectors
- 위의 WordNet은 사전에 대한 의존도가 높아 시간이 지날수록 정확도나 활용도가 떨어질 수 있음.
@ TF-IDF
- d 라는 문서 내에서 w 라는 단어가 있을 때, w 는 d 내에서 얼마나 중요한지 나타내는 수치
- 텍스트 마이닝에서 중요하게 사용됨.
- TF(Term Frequency)
- w 가 문서 내에 출현한 횟수
- 하지만, of, the, for 같은 단어도 TF 가 클 것임을 알고 있어야 함. (무시)
- IDF(Inverse Document Frequency)
- w 라는 단어가 몇 개의 문서에 나왔는지에 대한 횟수의 역수
- 이 방법을 통해 of, the, for 과 같은 단어에 대한 영향을 줄여줌
'데이터 분석 > 자연어처리' 카테고리의 다른 글
3. 자연어 처리 - 텍스트 유사도(n-gram, 코사인 유사도) (1) | 2021.01.18 |
---|---|
2. 자연어 처리 - Subword, BPE 알고리즘(OoV, UNK) (0) | 2021.01.17 |
자연어 처리 기초 - 정규표현식 알아보기(정리, 실습편) (0) | 2021.01.16 |
1. 자연어 처리(NLP, NLU, NLG) - 수집, 정제, tokenization (0) | 2021.01.14 |