NLTK
# 03
3장에서는 lemmatization, stemming, POS tagging, Parsing, SEntece breaking, Word segmentation을 배웠다.
lemmatization은 그 단어가 문장에서 어떻게 쓰였는지 알아내는 것이다.
HTML에서 코퍼스를 구축할 때,
html=urlopen(url).read()
raw=nltk.clean_html(html)
을 하면 ASCII로 바뀌고, 이걸 text로 바꾸기 위해서
tokens=nltk.wordpunct_tokenize(Raw)
text=nltk.Text(token)
를 하면 Text로 바꿀 수 있다.
url으로 string을 다운받으려면
from urllibk import *
response=request.urlopen(url)
raw=response.read()decode('utf8')
을 하면 된다.
string 클래스가 되었으니까 find, rfind 함수를 쓸 수 있고
url 전체를 가져왔으니 header와 footer을 떼어야 한다.
html 태그를 제거하기 위해서 raw=BeautifulSoup(html, 'html.parser').get_text()
from bs4 import BeautifulSoup을 해줘야한다.
BeautifulSoup은 unicode와 utf-8로 바꿀 때 쓰는 모듈이다.
tokenization을 하기위해서는
tokens=nltk.word_tokenize(raw)
을 쓰면되는데, list로 리턴한다.
token을 text로 변환하기 위해서는
text=nltk.Text(tokens)를 쓰면 된다.
따라서 nltk.의 Text함수의 인자로는 list가 들어가야 한다.
리턴값은 nltk.text.Text 클래스가 생성된다.
nltk.text.Text 클래스에서는 여러가지 메소드를 사용할 수 있는데,
concordance, collocation 등을 사용할 수 있다.
(RSS Feeds, feedparser)...?
os 패키지에는 getcwd()메소드와 listdir(경로), chdir(경로) 등이 있다.
스트링 중간에 끊어서 작성하는 방법은
\하고 그냥 넘어가거나
(괄호로
묶어서 하거나)
"""로 묶을 수 있다.
local encoding 을 하려면 맨 처음에 #-*- coding: utf-8 -*-으로 하면 된다.
문법에 관한 참스키 계층은
이렇게 되는데, 정규표현식에 대해서는 내용이 너무 많으므로 간략하게 설명하려고 한다.
^ : 이 패턴으로 시작
$ 이 패턴으로 종료
[] : 이 중에 하나
[^] : 피해야할 문자들 집합
| : 두 패턴 중 하나이어야 함
? : 0개거나 1개
+ : 하나 이상
* : 0개 이상
패턴{n} : n 번 반복
{n, m} : n번이상 최대 m 번 이하
\d : 숫자0-9
\w : 문자
\s : 화이트 스페이스 [\t\n\r\f]
. : wildcard. \n을 제외한 모든 문자
전화번호 4653으로 만들 수 있는 영어단어를 코딩해보면,
import re
wordlist=[w for w in nltk.corpus.words.words('en') if w.islower()]
[w for w in wordlist if re.search('^[ghi][mno][jlk][def]$', w)]
re모듈의 메소드에는
search : string 전체를 검색해 일치하는 첫번째 문자열을 찾는다.
match : string의 첫 문자열만을 비교하여 확인한다. 처음부터 일치하여야 함.
findall : 가장 많이 쓰이는 메소드로, 일치하는 것을 모두 찾아서 list로 반환한다.
sub : string 전체에서 일치하는 모든 것을 replace로 교체하고 str으로 반환한다.
split : 주어진 스트링을 패턴으로 분리시킨다. re.split()을 사용해서 정규 표현식을 이용할 수 있다.
compile : 해당 정규 표현식을 re.RegexObject 객체로 저장할 수 있어 다시 쓰는 번거로움을 피할 수 있다.
*와 +는 greedy이므로 가장 긴 것을 가져온다.
가져올 때 non-greedy로 하려면 뒤에 ?를 붙이면 된다.
findall메소드에서 3번째 인자를 줄 수도 있는데 MULTILINE이 이에 해당된다.
GNI 논문의 이메일 주소를 출력해주는 코드를 써보면,
GNI=PlaintextCorpusReader("경로", ".*\.txt", encoding='utf-8')
giRaw=GNI.raw('파일이름.txt')
re.findall(r'[\w._%+=]+@[\w.-]+\.[a-zA-Z]{2,4}',giRaw)
이렇게 된다.
(?!pattern) : Positive Lookahead, a(?=b)이면 a나 abc를 찾는다. consuming은 아님.
(?:pattern) : Negative Lookahead, a(?!b)은 a나 acc를 찾는다.
(?=pattern) : Non-Capturing Group, 캡처를 하지 않는다.
nltk에서 제공하는 findall의 정규표현식은 다르게 생겼다. 토큰 바운더리(<.>)로 표현한다.
lower()메서드를 통해서 텍스트를 normalized할 수 있다.
nltk의 stemmers에는 Porter와 Lancaster 가 있다.
[nltk.PorterStemmers().stem(t) for t in tokens] 등으로 할 수 있는데, 둘의 규칙이 다르다.
nltk의 lemmatizer는 affixes를 제거해서 사전에 있는 것만 반환한다.
from nltk.stem.wordnet import WordNetLemmatizer
[nltk.WordNetLemmatizer().lemmatize(t) for t in tokens]으로 쓸 수 있다.
(알아두기!)
lemmatisation은 사전을 기반으로, stemming이랑 구별. stem은 context안 보므로, lemmatisation이 더 정확도가 높음.
in a 들을 제외하려면, [x for x in words if not (x in stopwords.words('english'))]하기
의미있는 단어들만을 통계에 넣기 위해서 평범한 단어를 제거하려면
from nltk.corpus import stopwords
words=[리스트]
[x for x in words if not(x in stopwords.words('english'))]
를 하기.
그래서 각 GNI 논문 별로 빈도수 많은 단어를 평범한 단어 제거후에 출력하는 코드는
GenomInfoCorpus=PaintextCorpusReader(corpus_root, '.*\.txt', encoding='utf-8')
giRaw=GenomInfoCorpus.raw()
giWords=GenomInfoCorpus.words()
from nltk. corpus import stopwords wnl=nltk.WordNetLemmatizer()
giRaws={}
for fileid in GenomInfoCorpus.fileids():
giRaws[fileid]=GenomInfoCorpus.raw(fileid)
giRaws[fileid]=re.sub(r'[\n\r.,()]', '', giRaws[fileid])
words=nltk.word_tokenize(giRaws[fileid])
words=[x for x in words if not (x.lower() in stopwords.words('english'))]
fd=nltk.FreqDist(words)
fd=sorted([(freq, word) for (word, freq) in fd.items()], revers=True)
이렇게 된다.
nltk.regexp_tokenize()도 따로 있는데, 기본 tokenize보다 못하다. custom할 수 있다 정도만 알아두기.
nltk.sent_tokenize(text) 메서드는 punctuation기준으로 sent를 나누기 때문에 문장 단위로 나누는 것이지만 정확도가 매우 떨어진다.
giWords=GNI.words('파일명')
giWord2=re.split(r'[\n\t]+', giRaw)
와 차이가 나는 이유는 첫번쨰 words는 ,나 :, ;들이 포함되기 때문이다.
string을 format 처리하면
'{} flies like an {}'.format('Time', 'arrow')
라고 하면 'Time flies like and arrow'로 나온다.
'{1} flies like an {0}'.format('Time', 'arrow')
은 'arrow flies like an Time'
'{:10} flies'.format('Time')
은 'Time flies'가 된다.
'{:<10} flies'.format('Time')도 똑같음.
'{:>10} flies'.format('Time')은
' Time flies'로 나온다.
import math
'{:4f}'.format(math.pi)은 3.141593으로 나오고,
'{:.4f}'.format(math.pi)은 3.1416으로 나온다.
'etc > NLTK' 카테고리의 다른 글
[ANN] #01 (0) | 2019.05.05 |
---|---|
[NLTK] #02 (0) | 2019.04.09 |
[NLTK] #01 (0) | 2019.04.08 |