Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python NLTK WordNet으로 동의어·반의어 추출하기

WordNet은 Python의 자연어 처리 라이브러리인 NLTK(Natural Language Toolkit)에 포함된 대규모 영어 단어 데이터베이스입니다. 명사, 형용사, 부사, 동사 등 방대한 양의 영어 단어를 담고 있으며, 의미가 서로 같거나 비슷한 단어들을 시논셋(synset)이라 불리는 인지 동의어 집합으로 묶어 관리합니다.

NLTK와 WordNet 설치하기

WordNet을 사용하려면 먼저 NLTK 모듈을 설치하고, 이후 WordNet 패키지를 다운로드해야 합니다.

$ sudo pip3 install nltk
$ python3
>>> import nltk
>>> nltk.download('wordnet')

WordNet에는 의미가 같은 단어들이 여러 그룹으로 묶여 있습니다. 첫 번째 예제에서는 특정 단어의 의미와 관련 세부 정보를 어떻게 가져오는지 살펴보겠습니다. 해당 단어에 사용 예문이 존재한다면 예문까지 함께 반환됩니다.

예제 1: 단어 정보 조회

from nltk.corpus import wordnet   # NLTK에서 wordnet 임포트
synset = wordnet.synsets("Travel")
print('Word and Type : ' + synset[0].name())
print('Synonym of Travel is: ' + synset[0].lemmas()[0].name())
print('The meaning of the word : ' + synset[0].definition())
print('Example of Travel : ' + str(synset[0].examples()))

실행 결과

$ python3 322a.word_info.py
Word and Type : travel.n.01
Synonym of Travel is: travel
The meaning of the word : the act of going from one place to another
Example of Travel : ['he enjoyed selling but he hated the travel']
$

위 예제처럼 synsets() 함수를 호출하면 단어 이름과 품사 타입(예: travel.n.01은 명사임을 의미), 대표 동의어, 사전적 정의, 사용 예문 등을 한꺼번에 확인할 수 있습니다.

예제 2: 동의어와 반의어 추출

이번에는 주어진 단어의 동의어(synonym)와 반의어(antonym)를 한 번에 추출하는 방법을 알아보겠습니다. 각 시논셋에 포함된 lemma를 순회하면서 동의어 목록에는 모든 이름을 추가하고, 반의어가 존재하는 경우에만 반의어 목록에 추가합니다.

import nltk
from nltk.corpus import wordnet   # NLTK에서 wordnet 임포트
syn = list()
ant = list()
for synset in wordnet.synsets("Worse"):
   for lemma in synset.lemmas():
      syn.append(lemma.name())    # 동의어 추가
      if lemma.antonyms():        # 반의어가 존재할 때만 목록에 추가
         ant.append(lemma.antonyms()[0].name())
print('Synonyms: ' + str(syn))
print('Antonyms: ' + str(ant))

실행 결과

$ python3 322b.syn_ant.py
Synonyms: ['worse', 'worse', 'worse', 'worsened', 'bad', 'bad', 'big', 'bad', 'tough', 'bad', 'spoiled', 'spoilt', 'regretful', 'sorry', 'bad', 'bad', 'uncollectible', 'bad', 'bad', 'bad', 'risky', 'high-risk', 'speculative', 'bad', 'unfit', 'unsound', 'bad', 'bad', 'bad', 'forged', 'bad', 'defective', 'worse']
Antonyms: ['better', 'better', 'good', 'unregretful']
$

출력 결과에서 볼 수 있듯이 하나의 단어라도 여러 시논셋에 걸쳐 다양한 의미로 등장하기 때문에 동의어 목록에 중복 항목이 많이 나타날 수 있습니다. 실무에서는 set()을 활용해 중복을 제거하면 더 깔끔한 결과를 얻을 수 있습니다.

예제 3: 두 단어 간 유사도 비교

NLTK WordNet에는 또 하나 강력한 기능이 있습니다. 바로 두 단어가 얼마나 비슷한지를 수치로 판단하는 기능입니다. wup_similarity() 메서드를 사용하면 두 단어 쌍에 대한 유사도(similarity ratio)를 0부터 1 사이의 값으로 반환받을 수 있습니다.

import nltk
from nltk.corpus import wordnet     # NLTK에서 wordnet 임포트
first_word = wordnet.synset("Travel.v.01")
second_word = wordnet.synset("Walk.v.01")
print('Similarity: ' + str(first_word.wup_similarity(second_word)))
first_word = wordnet.synset("Good.n.01")
second_word = wordnet.synset("zebra.n.01")
print('Similarity: ' + str(first_word.wup_similarity(second_word)))

실행 결과

$ python3 322c.compare.py
Similarity: 0.6666666666666666
Similarity: 0.09090909090909091
$

'Travel'과 'Walk'는 모두 이동과 관련된 동작이라는 공통점이 있어 약 0.67의 높은 유사도를 보인 반면, 'Good'과 'zebra'는 의미적으로 거리가 멀어 약 0.09의 낮은 유사도가 산출되었습니다. 이러한 유사도 측정 기능은 검색어 확장, 중복 문서 판별, 추천 시스템 등 다양한 자연어 처리 작업에 활용할 수 있습니다.