Gensim-LDA 토픽 모델 생성
이 장은 Gensim에서 LDA (Latent Dirichlet assignment) 토픽 모델을 만드는 방법을 배우는 데 도움이됩니다.
NLP (자연어 처리)의 주요 응용 프로그램 중 하나에서 대량 텍스트에서 주제에 대한 정보를 자동으로 추출합니다. 많은 양의 텍스트는 호텔 리뷰, 트윗, Facebook 게시물, 다른 소셜 미디어 채널의 피드, 영화 리뷰, 뉴스 기사, 사용자 피드백, 이메일 등의 피드가 될 수 있습니다.
이 디지털 시대에 사람 / 고객이 무엇에 대해 이야기하고 있는지, 그들의 의견과 문제를 이해하는 것은 기업, 정치 캠페인 및 관리자에게 매우 가치가있을 수 있습니다. 그러나 그렇게 많은 양의 텍스트를 수동으로 읽은 다음 주제에서 정보를 추출 할 수 있습니까?
아니, 그렇지 않습니다. 이처럼 방대한 양의 텍스트 문서를 읽고 여기에서 논의 된 필수 정보 / 주제를 자동으로 추출 할 수있는 자동 알고리즘이 필요합니다.
LDA의 역할
주제 모델링에 대한 LDA의 접근 방식은 문서의 텍스트를 특정 주제로 분류하는 것입니다. Dirichlet 분포로 모델링 된 LDA는-
- 문서 모델 별 주제 및
- 주제 모델 당 단어
LDA 토픽 모델 알고리즘을 제공 한 후 토픽-키워드 배포의 좋은 구성을 얻기 위해 다시 정렬합니다.
- 문서 내의 주제 분포 및
- 주제 내 키워드 분포
처리하는 동안 LDA의 일부 가정은 다음과 같습니다.
- 모든 문서는 주제의 다중 명목 분포로 모델링됩니다.
- 모든 주제는 단어의 다중 명목 분포로 모델링됩니다.
- LDA는 각 텍스트 청크에 관련 단어가 포함되어 있다고 가정하기 때문에 올바른 데이터 코퍼스를 선택해야합니다.
- LDA는 또한 문서가 주제의 혼합으로 생성되었다고 가정합니다.
Gensim으로 구현
여기서는 LDA (Latent Dirichlet Allocation)를 사용하여 데이터 세트에서 자연스럽게 논의되는 주제를 추출합니다.
데이터 세트로드
우리가 사용할 데이터 셋은 ’20 Newsgroups’뉴스 보고서의 다양한 섹션에서 수천 개의 뉴스 기사가 있습니다. 아래에서 사용할 수 있습니다.Sklearn데이터 세트. 다음 Python 스크립트의 도움으로 쉽게 다운로드 할 수 있습니다.
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
다음 스크립트의 도움으로 샘플 뉴스를 살펴 보겠습니다.
newsgroups_train.data[:4]
["From: [email protected] (where's my thing)\nSubject:
WHAT car is this!?\nNntp-Posting-Host: rac3.wam.umd.edu\nOrganization:
University of Maryland, College Park\nLines:
15\n\n I was wondering if anyone out there could enlighten me on this car
I saw\nthe other day. It was a 2-door sports car, looked to be from the
late 60s/\nearly 70s. It was called a Bricklin. The doors were really small.
In addition,\nthe front bumper was separate from the rest of the body.
This is \nall I know. If anyone can tellme a model name,
engine specs, years\nof production, where this car is made, history, or
whatever info you\nhave on this funky looking car, please e-mail.\n\nThanks,
\n- IL\n ---- brought to you by your neighborhood Lerxst ----\n\n\n\n\n",
"From: [email protected] (Guy Kuo)\nSubject: SI Clock Poll - Final
Call\nSummary: Final call for SI clock reports\nKeywords:
SI,acceleration,clock,upgrade\nArticle-I.D.: shelley.1qvfo9INNc3s\nOrganization:
University of Washington\nLines: 11\nNNTP-Posting-Host: carson.u.washington.edu\n\nA
fair number of brave souls who upgraded their SI clock oscillator have\nshared their
experiences for this poll. Please send a brief message detailing\nyour experiences with
the procedure. Top speed attained, CPU rated speed,\nadd on cards and adapters, heat
sinks, hour of usage per day, floppy disk\nfunctionality with 800 and 1.4 m floppies
are especially requested.\n\nI will be summarizing in the next two days, so please add
to the network\nknowledge base if you have done the clock upgrade and haven't answered
this\npoll. Thanks.\n\nGuy Kuo <;[email protected]>\n",
'From: [email protected] (Thomas E Willis)\nSubject:
PB questions...\nOrganization: Purdue University Engineering
Computer Network\nDistribution: usa\nLines: 36\n\nwell folks,
my mac plus finally gave up the ghost this weekend after\nstarting
life as a 512k way back in 1985. sooo, i\'m in the market for
a\nnew machine a bit sooner than i intended to be...\n\ni\'m looking
into picking up a powerbook 160 or maybe 180 and have a bunch\nof
questions that (hopefully) somebody can answer:\n\n* does anybody
know any dirt on when the next round of powerbook\nintroductions
are expected? i\'d heard the 185c was supposed to make an\nappearence
"this summer" but haven\'t heard anymore on it - and since i\ndon\'t
have access to macleak, i was wondering if anybody out there had\nmore
info...\n\n* has anybody heard rumors about price drops to the powerbook
line like the\nones the duo\'s just went through recently?\n\n* what\'s
the impression of the display on the 180? i could probably swing\na 180
if i got the 80Mb disk rather than the 120, but i don\'t really have\na
feel for how much "better" the display is (yea, it looks great in the\nstore,
but is that all "wow" or is it really that good?). could i solicit\nsome
opinions of people who use the 160 and 180 day-to-day on if its
worth\ntaking the disk size and money hit to get the active display?
(i realize\nthis is a real subjective question, but i\'ve only played around
with the\nmachines in a computer store breifly and figured the opinions
of somebody\nwho actually uses the machine daily might prove helpful).\n\n*
how well does hellcats perform? ;)\n\nthanks a bunch in advance for any info -
if you could email, i\'ll post a\nsummary (news reading time is at a premium
with finals just around the\ncorner... :
( )\n--\nTom Willis \\ [email protected] \\ Purdue Electrical
Engineering\n---------------------------------------------------------------------------\
n"Convictions are more dangerous enemies of truth than lies." - F. W.\nNietzsche\n',
'From: jgreen@amber (Joe Green)\nSubject: Re: Weitek P9000 ?\nOrganization:
Harris Computer Systems Division\nLines: 14\nDistribution: world\nNNTP-Posting-Host:
amber.ssd.csd.harris.com\nX-Newsreader: TIN [version 1.1 PL9]\n\nRobert
J.C. Kyanko ([email protected]) wrote:\n >[email protected] writes in article
<[email protected] >:\n> > Anyone know about the
Weitek P9000 graphics chip?\n > As far as the low-level stuff goes, it looks
pretty nice. It\'s got this\n> quadrilateral fill command that requires just
the four points.\n\nDo you have Weitek\'s address/phone number? I\'d like to get
some information\nabout this chip.\n\n--\nJoe Green\t\t\t\tHarris
Corporation\[email protected]\t\t\tComputer Systems Division\n"The only
thing that really scares me is a person with no sense of humor.
"\n\t\t\t\t\t\t-- Jonathan Winters\n']
전제 조건
NLTK의 불용어와 Scapy의 영어 모델이 필요합니다. 둘 다 다음과 같이 다운로드 할 수 있습니다-
import nltk;
nltk.download('stopwords')
nlp = spacy.load('en_core_web_md', disable=['parser', 'ner'])
필요한 패키지 가져 오기
LDA 모델을 구축하려면 다음과 같은 패키지를 가져와야합니다.
import re
import numpy as np
import pandas as pd
from pprint import pprint
import gensim
import gensim.corpora as corpora
from gensim.utils import simple_preprocess
from gensim.models import CoherenceModel
import spacy
import pyLDAvis
import pyLDAvis.gensim
import matplotlib.pyplot as plt
불용어 준비
이제 불용어를 가져 와서 사용해야합니다.
from nltk.corpus import stopwords
stop_words = stopwords.words('english')
stop_words.extend(['from', 'subject', 're', 'edu', 'use'])
텍스트 정리
이제 Gensim의 도움으로 simple_preprocess()각 문장을 단어 목록으로 토큰 화해야합니다. 구두점과 불필요한 문자도 제거해야합니다. 이를 위해 다음과 같은 이름의 함수를 생성합니다.sent_to_words() −
def sent_to_words(sentences):
for sentence in sentences:
yield(gensim.utils.simple_preprocess(str(sentence), deacc=True))
data_words = list(sent_to_words(data))
Bigram 및 Trigram 모델 구축
아시다시피, bigram은 문서에서 자주 발생하는 두 단어이고 trigram은 문서에서 자주 발생하는 세 단어입니다. Gensim의 도움으로Phrases 모델, 우리는 이것을 할 수 있습니다-
bigram = gensim.models.Phrases(data_words, min_count=5, threshold=100)
trigram = gensim.models.Phrases(bigram[data_words], threshold=100)
bigram_mod = gensim.models.phrases.Phraser(bigram)
trigram_mod = gensim.models.phrases.Phraser(trigram)
불용어 필터링
다음으로 불용어를 필터링해야합니다. 이와 함께, 우리는 또한 bigrams, trigrams 및 lemmatisation을위한 함수를 만들 것입니다.
def remove_stopwords(texts):
return [[word for word in simple_preprocess(str(doc))
if word not in stop_words] for doc in texts]
def make_bigrams(texts):
return [bigram_mod[doc] for doc in texts]
def make_trigrams(texts):
return [trigram_mod[bigram_mod[doc]] for doc in texts]
def lemmatization(texts, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV']):
texts_out = []
for sent in texts:
doc = nlp(" ".join(sent))
texts_out.append([token.lemma_ for token in doc if token.pos_ in allowed_postags])
return texts_out
주제 모델을위한 사전 및 코퍼스 구축
이제 사전과 말뭉치를 구축해야합니다. 이전 예제에서도 수행했습니다.
id2word = corpora.Dictionary(data_lemmatized)
texts = data_lemmatized
corpus = [id2word.doc2bow(text) for text in texts]
LDA 주제 모델 구축
우리는 이미 LDA 모델을 훈련하는 데 필요한 모든 것을 구현했습니다. 이제 LDA 토픽 모델을 구축 할 때입니다. 구현 예의 경우 다음 코드 줄을 사용하여 수행 할 수 있습니다.
lda_model = gensim.models.ldamodel.LdaModel(
corpus=corpus, id2word=id2word, num_topics=20, random_state=100,
update_every=1, chunksize=100, passes=10, alpha='auto', per_word_topics=True
)
구현 예
LDA 토픽 모델을 구축하기위한 전체 구현 예제를 보겠습니다.
import re
import numpy as np
import pandas as pd
from pprint import pprint
import gensim
import gensim.corpora as corpora
from gensim.utils import simple_preprocess
from gensim.models import CoherenceModel
import spacy
import pyLDAvis
import pyLDAvis.gensim
import matplotlib.pyplot as plt
from nltk.corpus import stopwords
stop_words = stopwords.words('english')
stop_words.extend(['from', 'subject', 're', 'edu', 'use'])
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
data = newsgroups_train.data
data = [re.sub('\S*@\S*\s?', '', sent) for sent in data]
data = [re.sub('\s+', ' ', sent) for sent in data]
data = [re.sub("\'", "", sent) for sent in data]
print(data_words[:4]) #it will print the data after prepared for stopwords
bigram = gensim.models.Phrases(data_words, min_count=5, threshold=100)
trigram = gensim.models.Phrases(bigram[data_words], threshold=100)
bigram_mod = gensim.models.phrases.Phraser(bigram)
trigram_mod = gensim.models.phrases.Phraser(trigram)
def remove_stopwords(texts):
return [[word for word in simple_preprocess(str(doc))
if word not in stop_words] for doc in texts]
def make_bigrams(texts):
return [bigram_mod[doc] for doc in texts]
def make_trigrams(texts):
[trigram_mod[bigram_mod[doc]] for doc in texts]
def lemmatization(texts, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV']):
texts_out = []
for sent in texts:
doc = nlp(" ".join(sent))
texts_out.append([token.lemma_ for token in doc if token.pos_ in allowed_postags])
return texts_out
data_words_nostops = remove_stopwords(data_words)
data_words_bigrams = make_bigrams(data_words_nostops)
nlp = spacy.load('en_core_web_md', disable=['parser', 'ner'])
data_lemmatized = lemmatization(data_words_bigrams, allowed_postags=[
'NOUN', 'ADJ', 'VERB', 'ADV'
])
print(data_lemmatized[:4]) #it will print the lemmatized data.
id2word = corpora.Dictionary(data_lemmatized)
texts = data_lemmatized
corpus = [id2word.doc2bow(text) for text in texts]
print(corpus[:4]) #it will print the corpus we created above.
[[(id2word[id], freq) for id, freq in cp] for cp in corpus[:4]]
#it will print the words with their frequencies.
lda_model = gensim.models.ldamodel.LdaModel(
corpus=corpus, id2word=id2word, num_topics=20, random_state=100,
update_every=1, chunksize=100, passes=10, alpha='auto', per_word_topics=True
)
이제 위에서 만든 LDA 모델을 사용하여 주제를 가져오고 Model Perplexity를 계산할 수 있습니다.