미분류

NLP – 자연어 텍스트 처리 (NLTK)

NLP – 자연어 텍스트 처리 (NLTK)

NLTK

NLTK (Natural Language Toolkit): 자연어 처리 및 문서 분석용 패키지

  • 코퍼스(corpus)
  • 토큰 생성
  • 형태소 분석
  • 품사 태깅

NLTK 코퍼스 (nltk.corpus 모듈)

http://www.nltk.org/nltk_data/ (전체목록)

주요 코퍼스

  • gutenberg : 모비딕(Moby Dick), 성서등 구텐베르크 프로젝트 영문 책 텍스트 18개
  • reuters: 10,788 뉴스 문서, 천3백만 단어, 90개 토픽, “training” 과 "test"로 나누어져 있다.
  • brown : 브라운대(1961) 최초 백만단어 코퍼스, 뉴스 학습자료등 카테고리가 나누어져 있다
  • names : 8,000개의 남성과 여성의 이름
  • words : 가장 빈번하게 사용하는 영어 단어 23,5000개
  • stopwords : 14개의 언어의 가장 많이 사용하는 불용어(stop word)
  • cmudict : 카네기멜론대, 13,4000개 단어와 음절(syllables)로 구성. 동음이의어 검색.
import nltk

nltk.download("gutenberg")
nltk.download("reuters")
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('averaged_perceptron_tagger')
nltk.download('wordnet') 
import nltk
fileids = nltk.corpus.gutenberg.fileids()
print(fileids)
  • corpus.fileids() # 코퍼스에 포함된 파일아이디 목록
  • corpus.raw(fileid) # 파일의 원문
  • corpus.sents(fileid) #파일의 문장 목록
  • corpus.words(fileid) # 파일의 단어 목록
from nltk.corpus import gutenberg

for fileid in gutenberg.fileids():
    num_chars = len(gutenberg.raw(fileid)) # 문자수
    num_words = len(gutenberg.words(fileid)) # 단어수
    num_sents = len(gutenberg.sents(fileid)) # 문장수
    num_vocab = len(set(w.lower() for w in gutenberg.words(fileid))) # 어휘수
    print(round(num_chars/num_words), round(num_words/num_sents), round(num_words/num_vocab), fileid)
moby_dick_words = nltk.corpus.gutenberg.words('melville-moby_dick.txt')
len(moby_dick_words)

문서 읽기

import nltk
from nltk.corpus import gutenberg

# 1. read document
moby_dick_text = gutenberg.open('melville-moby_dick.txt').read()
moby_dick_text[:1000]

[Moby Dick by Herman Melville 1851]

ETYMOLOGY.

(Supplied by a Late Consumptive Usher to a Grammar School)

The pale Usher–threadbare in coat, heart, body, and brain; I see him now. He was ever dusting his old lexicons and grammars, with a queer handkerchief, mockingly embellished with all the gay flags of all the known nations of the world. He loved to dust his old grammars; it somehow mildly reminded him of his mortality.

“While you take in hand to school others, and to teach them by what name a whale-fish is to be called in our tongue leaving out, through ignorance, the letter H, which almost alone maketh the signification of the word, you deliver that which is not true.” –HACKLUYT

“WHALE. … Sw. and Dan. HVAL. This animal is named from roundness or rolling; for in Dan. HVALT is arched or vaulted.” –WEBSTER’S DICTIONARY

“WHALE. … It is more immediately from the Dut. and Ger. WALLEN; A.S. WALW-IAN, to roll, to wallow.” –RICHARDSON’S DICTIONARY

Toknize

텍스트를 처리하기 위한 작은 단위(token)으로 나눈다. NLTK는 다음 토큰 생성을 제공

from nltk.tokenize import sent_tokenize # 문장으로 나누기
from nltk.tokenize import word_tokenize # 단어로 나누기
from nltk.tokenize import regexp_tokenize # 정규식으로 나누기
from nltk.tokenize import sent_tokenize

moby_sents = sent_tokenize(moby_dick_text)
moby_sents[100:110]
from nltk.tokenize import word_tokenize

moby_words = word_tokenize(moby_dick_text)
moby_words[100:110]
from nltk import regexp_tokenize

moby_retoks = regexp_tokenize(moby_dick_text.lower(), r"[\w]+")
moby_retoks[100:110]

nltk.Text()

http://www.nltk.org/api/nltk.html#nltk.text.Text

import nltk
moby = nltk.Text(moby_retoks)

print(len(moby.tokens)) # 토큰 개수
print(len(set(moby.tokens))) # 고유한 토큰 개수

빈도 분포

freq_dist = moby.vocab() # Freq Dist (빈도 분포)
print(len(freq_dist))
print(freq_dist.most_common(50)) # 가장 많이 등장하는 50개
moby.plot(50)

count

moby.count('captain')

Dispersion plot

단어가 등장하는 위치를 Word Offset에 따라 배치하여 시각화

모비딕의 주요 등장인물들: ‘ahab’, ‘starbuck’, ‘queequeg’, ‘ishmael’, ‘stubb’, ‘flask’, ‘fedallah’

moby.dispersion_plot(['ahab', 'starbuck', 'queequeg', 'ishmael', 'stubb', 'flask', 'fedallah'])

Concordance

Concordance (색인): 단어가 쓰인 문맥을 모두 찾아준다

moby.concordance('ahab', lines=10)

Similar word

주어진 단어와 비슷한 환경(same context)에서 쓰인(≠비슷한 뜻) 단어들

moby.similar('whale')
moby.similar('ship')
moby.similar('god')

Common_contexts

for two words used in similar contexts

moby.common_contexts(['monstrous', 'true'])

Collocations

연어(連語, collocation): 함께 위치하는 단어들 (co + location), 어휘의 조합 또는 짝을 이루는 단어

moby.collocations()

PoS Tagging

NLTK 에서는 Penn Treebank Tagset 을 이용

https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html

예를 들어,

  • NN: 일반명사 단수
  • NNS: 일반명사 복수
  • NNP: 대명사 단수
  • NNPS: 대명사 복수
nltk.pos_tag(['The', 'earth', 'is', 'a', 'beautiful', 'planet'])
  • DT: 한정사
  • NN: 명사, 단수형
  • VBZ: 동사, 현재형 시제, 3인칭 단수
  • JJ: 형용사
# 허먼 멜빌, "모비딕" 첫 단락
# 나를 이스마엘로 불러라. 몇 년 전, 정확히 얼마나 오래 동안 그랬는지는 모르겠지만,
# 내 지갑에 돈 한 푼 없는 빈털터리 신세에 육상에선 특별히 흥미를 끄는 어떤 것도 없던 그런 시절,
# 나는 잠시 동안이나마 배를 타고 세계의 바다를 보고 싶다는 생각을 했다.
# 그것이 우울하고 의기소침한 감정, 그 반복되는 악순환의 고리를 끊어버리는 한 방법이었다.

moby_dick_first_para_text = '''
Call me Ishmael.  Some years ago -- never mind how long
precisely--having little or no money in my purse, and nothing
particular to interest me on shore, I thought I would sail about a
little and see the watery part of the world.
It is a way I have of driving off the spleen, and regulating the circulation.
'''

import nltk
from nltk.tokenize import word_tokenize

moby_words = word_tokenize(moby_dick_first_para_text)
tasg = nltk.pos_tag(moby_words)
tasg[:20]

Noun phrase chunking

text = 'The earth is a beautiful planet.'

tokens = text.split()
tags = nltk.pos_tag(tokens)
parser = nltk.RegexpParser("NP: {<DT>?<JJ>?<NN.*>*}")
tree = parser.parse(tags)
tree

Stemming (어간 추출), lemmatizing (표제어 추출)

NLTK 지원

  • Stemmer: Porter(보수적), Lancaster(적극적)
  • Lemmatizer: WordNetLemmatizer (WordNet 이 계산한 형태소를 참조, 인터넷 연결 필요)

Stemmer vs Lemmatizer

  • stemming은 단어만 본다 (결과 stem이 사전에 없을 수도 있다)
  • Lemmatizer는 더 느리고 더 보수적
p_stmr = nltk.PorterStemmer()
p_stmr.stem("wonderful"), p_stmr.stem("flying"), p_stmr.stem("flies")
l_stmr = nltk.LancasterStemmer()
l_stmr.stem("wonderful"), l_stmr.stem("flying"), l_stmr.stem("flies")
lmtz = nltk.WordNetLemmatizer()
lmtz.lemmatize("wonderful"), lmtz.lemmatize("flying"), lmtz.lemmatize("flies")
# POS: # n=명사, v=동사, a=형용사, r=부사
print(lmtz.lemmatize("cats"))
print(lmtz.lemmatize("better", pos="a"))
print(lmtz.lemmatize("is", pos="v"))
print(lmtz.lemmatize("led"))
print(lmtz.lemmatize("led",'v'))

Summary

  • NLTK 코퍼스
  • Concordance (색인)
  • Similar Word: Similar context 단어들 (≠비슷한 뜻)
  • common_contexts
  • Collocations (연어)
  • PoS Tagging
  • chunking
  • Stemming (어간 추출), lemmatizing (표제어 추출)

실습 노트북

zerg96

Recent Posts

코스피 낙폭 7%로 확대, 외국인 1.7조 순매도: 10월 15일 오전 10시 시황

오전 시황 글에 이어 장중 후속 정리입니다. 코스피는 개장 직후 5%대였던 낙폭이 오전 10시 전후에…

3시간 ago

코스피 5.59% 급락 출발, 개장 7분 만에 매도 사이드카: 10월 15일 오전 시황

10월 15일 목요일 아침, 코스피가 전날 종가보다 5.59% 낮은 5,673.01로 출발했습니다. 장 시작 7분 만에…

3시간 ago

삼성 갤럭시 AI, 솔직히 기대 이하였다 — 실망스러운 이유 TOP 5

삼성 갤럭시 AI, 써보니 실망스러웠다. 온디바이스 한계, 지역 제한, 낮은 일상 활용도 등 현실적인 문제점…

4시간 ago

주 52시간제 뒤 제조업·중소기업만 흔들렸다? KDI 미공개 연구가 말한 것과 안 밝힌 것

주 52시간 상한이 기업 성과에 어떤 영향을 줬는지를 다룬 KDI(한국개발연구원) 연구 내용이 10월 14일 국회를…

5시간 ago

나스닥 1.88% 급락, 9월 미국 CPI 3.7%에 금리 인상 확률 한때 51%…오늘 코스피 개장 전 체크 4가지

어제 코스피는 장 초반 6,062선까지 올랐다가 결국 6,000선 턱걸이로 마감했습니다. 다들 미국 소비자물가지수(CPI) 발표만 쳐다보던…

5시간 ago

재택근무 종말이 온다? AI 감시 소프트웨어가 사무실을 부활시키는 진짜 이유

AI 감시 소프트웨어가 재택근무 시대를 끝내고 있다. 직원의 키스트로크·화면·표정까지 추적하는 기술의 실체와, 한국 직장인이 알아야…

23시간 ago