다운로드
작성자: admin 작성일시: 2016-06-14 23:10:13 조회수: 7066 다운로드: 244
카테고리: Python 태그목록:

NLTK 자연어 처리 패키지

NLTK(Natural Language Toolkit) 패키지는 교육용으로 개발된 자연어 처리 및 문서 분석용 파이썬 패키지다. 다양한 기능 및 예제를 가지고 있으며 실무 및 연구에서도 많이 사용된다.

NLTK 패키지가 제공하는 주요 기능은 다음과 같다.

  • 말뭉치
  • 토큰 생성
  • 형태소 분석
  • 품사 태깅

말뭉치

말뭉치(corpus)는 자연어 분석 작업을 위해 만든 샘플 문서 집합을 말한다. 단순히 소설, 신문 등의 문서를 모아놓은 것도 있지만 품사. 형태소, 등의 보조적 의미를 추가하고 쉬운 분석을 위해 구조적인 형태로 정리해 놓은 것을 포함한다. NLTK 패키지의 corpus 서브패키지에서는 다양한 연구용 말뭉치를 제공한다. 이 목록은 전체 corpus의 일부일 뿐이다. 말뭉치 자료는 설치시에 제공되지 않고 download 명령으로 사용자가 다운로드 받아야 한다.

In:
import nltk

nltk.download('averaged_perceptron_tagger')
nltk.download("gutenberg")
nltk.download('punkt')
nltk.download('reuters')
nltk.download("stopwords")
nltk.download("webtext")
nltk.download("wordnet")
[nltk_data] Downloading package averaged_perceptron_tagger to
[nltk_data]     /home/dockeruser/nltk_data...
[nltk_data]   Package averaged_perceptron_tagger is already up-to-
[nltk_data]       date!
[nltk_data] Downloading package gutenberg to
[nltk_data]     /home/dockeruser/nltk_data...
[nltk_data]   Package gutenberg is already up-to-date!
[nltk_data] Downloading package punkt to /home/dockeruser/nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package reuters to
[nltk_data]     /home/dockeruser/nltk_data...
[nltk_data]   Package reuters is already up-to-date!
[nltk_data] Downloading package stopwords to
[nltk_data]     /home/dockeruser/nltk_data...
[nltk_data]   Package stopwords is already up-to-date!
[nltk_data] Downloading package webtext to
[nltk_data]     /home/dockeruser/nltk_data...
[nltk_data]   Package webtext is already up-to-date!
[nltk_data] Downloading package wordnet to
[nltk_data]     /home/dockeruser/nltk_data...
[nltk_data]   Package wordnet is already up-to-date!
Out:
True

예를 들어 저작권이 말소된 문학작품을 포함하는 gutenberg 말뭉치에는 다음과 같은 작품이 샘플로 포함되어 있다.

In:
nltk.corpus.gutenberg.fileids()
Out:
['austen-emma.txt',
 'austen-persuasion.txt',
 'austen-sense.txt',
 'bible-kjv.txt',
 'blake-poems.txt',
 'bryant-stories.txt',
 'burgess-busterbrown.txt',
 'carroll-alice.txt',
 'chesterton-ball.txt',
 'chesterton-brown.txt',
 'chesterton-thursday.txt',
 'edgeworth-parents.txt',
 'melville-moby_dick.txt',
 'milton-paradise.txt',
 'shakespeare-caesar.txt',
 'shakespeare-hamlet.txt',
 'shakespeare-macbeth.txt',
 'whitman-leaves.txt']

이 중 제인 오스틴의 엠마 문서를 살펴보면 다음과 같이 원문 형태 그대로를 포함하고 있다.

In:
emma_raw = nltk.corpus.gutenberg.raw("austen-emma.txt")
print(emma_raw[:1302])
[Emma by Jane Austen 1816]

VOLUME I

CHAPTER I


Emma Woodhouse, handsome, clever, and rich, with a comfortable home
and happy disposition, seemed to unite some of the best blessings
of existence; and had lived nearly twenty-one years in the world
with very little to distress or vex her.

She was the youngest of the two daughters of a most affectionate,
indulgent father; and had, in consequence of her sister's marriage,
been mistress of his house from a very early period.  Her mother
had died too long ago for her to have more than an indistinct
remembrance of her caresses; and her place had been supplied
by an excellent woman as governess, who had fallen little short
of a mother in affection.

Sixteen years had Miss Taylor been in Mr. Woodhouse's family,
less as a governess than a friend, very fond of both daughters,
but particularly of Emma.  Between _them_ it was more the intimacy
of sisters.  Even before Miss Taylor had ceased to hold the nominal
office of governess, the mildness of her temper had hardly allowed
her to impose any restraint; and the shadow of authority being
now long passed away, they had been living together as friend and
friend very mutually attached, and Emma doing just what she liked;
highly esteeming Miss Taylor's judgment, but directed chiefly by
her own.

토큰 생성

자연어 문서를 분석하기 위해서는 우선 긴 문자열을 분석을 위한 작은 단위로 나누어야 한다. 이 문자열 단위를 토큰(token)이라고 하고 이렇게 문자열을 토큰으로 나누는 작업을 토큰 생성(tokenizing)이라고 한다. 영문의 경우에는 문장, 단어 등을 토큰으로 사용하거나 정규 표현식을 쓸 수 있다.

문자열을 토큰으로 분리하는 함수를 토큰 생성 함수(tokenizer)라고 한다. 토큰 생성 함수는 문자열을 입력받아 토큰 문자열의 리스트를 출력한다.

In:
from nltk.tokenize import sent_tokenize
print(sent_tokenize(emma_raw[:1000])[3])
Sixteen years had Miss Taylor been in Mr. Woodhouse's family,
less as a governess than a friend, very fond of both daughters,
but particularly of Emma.
In:
from nltk.tokenize import word_tokenize
word_tokenize(emma_raw[50:100])
Out:
['Emma',
 'Woodhouse',
 ',',
 'handsome',
 ',',
 'clever',
 ',',
 'and',
 'rich',
 ',',
 'with',
 'a']
In:
from nltk.tokenize import RegexpTokenizer
t = RegexpTokenizer("[\w]+")
t.tokenize(emma_raw[50:100])
Out:
['Emma', 'Woodhouse', 'handsome', 'clever', 'and', 'rich', 'with', 'a']

형태소 분석

형태소(morpheme)는 언어학에서 일정한 의미가 있는 가장 작은 말의 단위를 뜻한다. 보통 자연어 처리에서는 토큰으로 형태소를 이용한다. 형태소 분석(morphological analysis)이란 단어로부터 어근, 접두사, 접미사, 품사 등 다양한 언어적 속성을 파악하고 이를 이용하여 형태소를 찾아내거나 처리하는 작업이다. 형태소 분석의 예로는 다음과 같은 작업이 있다.

  • 어간 추출(stemming)
  • 원형 복원(lemmatizing)
  • 품사 부착(Part-Of-Speech tagging)

어간 추출과 원형 복원

어간 추출(stemming)은 여러가지 이유로 변화된 단어의 접미사나 어미를 제거하여 같은 의미를 가지는 형태소의 실제 형태를 동일하게 만드는 방법이다. NLTK는 PorterStemmer LancasterStemmer 등을 제공한다. 자세한 어간 추출 알고리즘은 다음 웹사이트를 참고한다.

In:
words = ['lives', 'dies', 'flies', 'died']
In:
from nltk.stem import PorterStemmer
st = PorterStemmer()
[st.stem(w) for w in words]
Out:
['live', 'die', 'fli', 'die']
In:
from nltk.stem import LancasterStemmer
st = LancasterStemmer()
[st.stem(w) for w in words]
Out:
['liv', 'die', 'fli', 'died']

어간 추출은 원형 복원(lemmatizing)의 일종이다. 원형 복원은 같은 의미를 가지는 여러 단어를 가장 근본적인 형태 즉 사전형으로 통일하는 작업이다.

In:
from nltk.stem import WordNetLemmatizer
lm = WordNetLemmatizer()
[lm.lemmatize(w) for w in words]
Out:
['life', 'dy', 'fly', 'died']
In:
lm.lemmatize("died", pos="v")
Out:
'die'

POS tagging

품사(POS, part-of-speech)는 낱말을 문법적인 기능이나 형태, 뜻에 따라 구분한 것이다. 품사의 구분은 언어마다 그리고 학자마다 다르다. 예를 들어 NLTK에서는 펜 트리뱅크 태그세트(Penn Treebank Tagset)라는 것을 이용한다. 다음은 펜 트리뱅크 태그세트에서 사용하는 품사의 예이다.

  • NN 명사(단수형 혹은 집합형)
  • PRP 인칭대명사
  • CD 서수
  • DT 관형사
  • VBP 동사 현재형

국내 태그세트로는 "21세기 세종계획 품사 태그세트"를 비롯하여 다양한 품사 태그세트가 있다. 세종계획 품사 태그세트의 자세한 내용은 "(21세기 세종계획)국어 기초자료 구축" 보고서의 "어절 분석 표지 표준안"을 참조한다.

In:
from nltk.tag import pos_tag
x = ["volume", "I", "chapter", "1", "I", "am", "a", "boy", "."]
tagged_list = pos_tag(x)
tagged_list
Out:
[('volume', 'NN'),
 ('I', 'PRP'),
 ('chapter', 'VBP'),
 ('1', 'CD'),
 ('I', 'PRP'),
 ('am', 'VBP'),
 ('a', 'DT'),
 ('boy', 'NN'),
 ('.', '.')]
In:
from nltk.tag import untag
untag(tagged_list)
Out:
['volume', 'I', 'chapter', '1', 'I', 'am', 'a', 'boy', '.']

Scikit-Learn 등에서 자연어 분석을 할 때는 같은 토큰이라도 품사가 다르면 다른 토큰으로 처리해야 하는 경우가 많은데 이 때는 원래의 토큰과 품사를 붙여서 새로운 토큰을 만들어 사용한다.

In:
def tokenizer(doc):
    return ["/".join(p) for p in pos_tag(doc)]
In:
tokenizer(x)
Out:
['volume/NN',
 'I/PRP',
 'chapter/VBP',
 '1/CD',
 'I/PRP',
 'am/VBP',
 'a/DT',
 'boy/NN',
 './.']

질문/덧글

아직 질문이나 덧글이 없습니다. 첫번째 글을 남겨주세요!