입력된 텍스트로부터 Ngram 생성
In [31]:
import nltk
import sklearn
from nltk import ngrams
sentence = 'this is a foo bar sentences and i want to ngramize it'
n = 3 # you can give 4, 5, 1 or any number less than sentences length
ngramsres = ngrams(sentence.split(), n)
for grams in ngramsres:
print (grams)
가장 많이 출현한 바이그램 출력하기
In [25]:
from nltk.collocations import *
bigram_measures = nltk.collocations.BigramAssocMeasures()
trigram_measures = nltk.collocations.TrigramAssocMeasures()
finder = BigramCollocationFinder.from_words(
nltk.corpus.genesis.words('english-web.txt'))
finder.nbest(bigram_measures.pmi, 10)
Out[25]:
입력된 텍스트로부터 바이그램 생성
In [24]:
from nltk import bigrams
text = "I do not like green eggs and ham, I do not like them Sam I am!"
tokens = nltk.wordpunct_tokenize(text)
finder = BigramCollocationFinder.from_words(tokens)
scored = finder.score_ngrams(bigram_measures.raw_freq)
sorted(bigram for bigram, score in scored)
Out[24]:
바이그램의 빈도수 세기
In [32]:
sorted(finder.nbest(trigram_measures.raw_freq, 2))
sorted(finder.ngram_fd.items(), key=lambda t: (-t[1], t[0]))[:10]
Out[32]:
CountVectorizer는 다음과 같은 세가지 작업을 수행한다.
텍스트를 입력하고 단어가방(BOW)에 넣기
단어 수만큼 벡터를 만들고, 각 단어를 벡터에 abc 순으로 넣기
ex) and는 0번가방에, document는 1번가방에 들어감
In [34]:
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'This is the first document.',
'This is the second second document.',
'And the third one.',
'Is this the first document?',
'The last document?',
]
vect = CountVectorizer()
vect.fit(corpus)
vect.vocabulary_
Out[34]:
가방에 들어간 단어들을 출력하고, 각 문장에서 그 단어가 출현한 빈도수 세기
In [41]:
print(vectorizer.get_feature_names())
vect.transform(corpus).toarray()
Out[41]:
Stop Words 는 문서에서 단어장을 생성할 때 무시할 수 있는 단어를 말한다. 보통 영어의 관사나 접속사, 한국어의 조사 등이 여기에 해당한다. stop_words 인수로 조절할 수 있다.
In [44]:
vect = CountVectorizer(stop_words=["and", "is", "the", "this"]).fit(corpus)
vect.vocabulary_
Out[44]:
Stop Words(불용어)를 제외하고, 벡터를 다시 생성하기
In [50]:
vect.transform(corpus).toarray()
Out[50]:
TF-IDF(Term Frequency – Inverse Document Frequency) 인코딩은 단어를 갯수 그대로 카운트하지 않고 모든 문서에 공통적으로 들어있는 단어의 경우 문서 구별 능력이 떨어진다고 보아 가중치를 축소하는 방법이다.
구제적으로는 문서 $d$(document)와 단어 $t$ 에 대해 다음과 같이 계산한다.
$$ \text{tf-idf}(d, t) = \text{tf}(d, t) \cdot \text{idf}(t) $$여기에서
$\text{idf}(t)$ : inverse document frequency. 특정한 단어가 들어 있는 문서의 수에 반비례하는 수
$$ \text{idf}(d, t) = \log \dfrac{n}{1 + \text{df}(t)} $$
$n$ : 전체 문서의 수
In [51]:
from sklearn.feature_extraction.text import TfidfVectorizer
In [52]:
tfidv = TfidfVectorizer().fit(corpus)
tfidv.transform(corpus).toarray()
Out[52]:
다음은 Scikit-Learn의 문자열 분석기를 사용하여 웹사이트에 특정한 단어가 어느 정도 사용되었는지 빈도수를 알아보는 코드이다.
In [92]:
from urllib.request import urlopen
import json
import string
from konlpy.utils import pprint
from konlpy.tag import Hannanum
hannanum = Hannanum()
#f = urlopen("https://www.datascienceschool.net/download-notebook/708e711429a646818b9dcbb581e0c10a/")
f = urlopen("https://github.com/ahhn/oss/raw/master/resources/Ngram_BOW_TF-IDF.ipynb")
json = json.loads(f.read())
cell = ["\n".join(c["source"]) for c in json["cells"] if c["cell_type"] == "markdown"]
docs = [w for w in hannanum.nouns(" ".join(cell)) if ((not w[0].isnumeric()) and (w[0] not in string.punctuation))]
여기에서는 하나의 문서가 하나의 단어로만 이루어져 있다. 따라서 CountVectorizer로 이 문서 집합을 처리하면 각 문서는 하나의 원소만 1이고 나머지 원소는 0인 벡터가 된다. 이 벡터의 합으로 빈도를 알아보았다.
In [90]:
import numpy as np
import matplotlib.pyplot as plt
vect = CountVectorizer().fit(docs)
count = vect.transform(docs).toarray().sum(axis=0)
idx = np.argsort(-count)
count = count[idx]
feature_name = np.array(vect.get_feature_names())[idx]
plt.bar(range(len(count)), count)
plt.show()
In [91]:
pprint(list(zip(feature_name, count))[:10])
In [ ]: