Gensim - Erstellen eines LDA-Themenmodells
In diesem Kapitel erfahren Sie, wie Sie ein LDA-Themenmodell (Latent Dirichlet Allocation) in Gensim erstellen.
Automatisches Extrahieren von Informationen zu Themen aus einer großen Anzahl von Texten in einer der Hauptanwendungen von NLP (Natural Language Processing). Eine große Menge an Texten kann Feeds aus Hotelbewertungen, Tweets, Facebook-Posts, Feeds aus anderen Social-Media-Kanälen, Filmkritiken, Nachrichten, Benutzer-Feedbacks, E-Mails usw. sein.
In diesem digitalen Zeitalter kann es für Unternehmen, politische Kampagnen und Administratoren von großem Wert sein, zu wissen, worüber Menschen / Kunden sprechen, ihre Meinungen und Probleme zu verstehen. Aber ist es möglich, so große Textmengen manuell durchzulesen und dann die Informationen aus Themen zu extrahieren?
Nein, ist es nicht. Es erfordert einen automatischen Algorithmus, der diese große Menge an Textdokumenten lesen und automatisch die erforderlichen Informationen / Themen daraus extrahieren kann.
Rolle der LDA
Der Ansatz von LDA zur Themenmodellierung besteht darin, Text in einem Dokument einem bestimmten Thema zuzuordnen. Als Dirichlet-Distribution modelliert, baut LDA -
- Ein Thema pro Dokumentmodell und
- Wörter pro Themenmodell
Nachdem der LDA-Themenmodellalgorithmus bereitgestellt wurde, ordnet er Folgendes neu an, um eine gute Zusammensetzung der Verteilung der Themenschlüsselwörter zu erhalten.
- Die Themenverteilungen innerhalb des Dokuments und
- Schlüsselwortverteilung innerhalb der Themen
Während der Verarbeitung sind einige der von LDA getroffenen Annahmen:
- Jedes Dokument wird als Multi-Nominal-Verteilung von Themen modelliert.
- Jedes Thema wird als multinominale Wortverteilung modelliert.
- Wir sollten den richtigen Datenbestand auswählen müssen, da LDA davon ausgeht, dass jeder Textabschnitt die zugehörigen Wörter enthält.
- LDA geht auch davon aus, dass die Dokumente aus einer Mischung von Themen erstellt werden.
Implementierung mit Gensim
Hier werden wir LDA (Latent Dirichlet Allocation) verwenden, um die natürlich diskutierten Themen aus dem Datensatz zu extrahieren.
Datensatz wird geladen
Der Datensatz, den wir verwenden werden, ist der Datensatz von ’20 Newsgroups’mit Tausenden von Nachrichtenartikeln aus verschiedenen Abschnitten eines Nachrichtenberichts. Es ist verfügbar unterSklearnDatensätze. Wir können einfach mit Hilfe des folgenden Python-Skripts herunterladen -
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
Schauen wir uns einige der Beispielnachrichten mit Hilfe des folgenden Skripts an:
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']
Voraussetzung
Wir brauchen Stoppwörter von NLTK und ein englisches Modell von Scapy. Beide können wie folgt heruntergeladen werden:
import nltk;
nltk.download('stopwords')
nlp = spacy.load('en_core_web_md', disable=['parser', 'ner'])
Notwendige Pakete importieren
Um ein LDA-Modell zu erstellen, müssen wir das folgende erforderliche Paket importieren:
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
Stoppwörter vorbereiten
Jetzt müssen wir die Stoppwörter importieren und verwenden -
from nltk.corpus import stopwords
stop_words = stopwords.words('english')
stop_words.extend(['from', 'subject', 're', 'edu', 'use'])
Bereinigen Sie den Text
Nun, mit Hilfe von Gensim simple_preprocess()Wir müssen jeden Satz in eine Liste von Wörtern umwandeln. Wir sollten auch die Interpunktionen und unnötigen Zeichen entfernen. Zu diesem Zweck erstellen wir eine Funktion mit dem Namensent_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))
Erstellen von Bigram- und Trigram-Modellen
Wie wir wissen, sind Bigramme zwei Wörter, die im Dokument häufig zusammen vorkommen, und Trigramm sind drei Wörter, die im Dokument häufig zusammen vorkommen. Mit Hilfe von GensimPhrases Modell können wir das tun -
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)
Stoppwörter herausfiltern
Als nächstes müssen wir die Stoppwörter herausfiltern. Daneben werden wir auch Funktionen zur Herstellung von Bigrams, Trigrammen und zur Lemmatisierung erstellen -
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
Erstellen von Wörterbuch und Korpus für das Themenmodell
Wir müssen jetzt das Wörterbuch und den Korpus erstellen. Wir haben es auch in den vorherigen Beispielen gemacht -
id2word = corpora.Dictionary(data_lemmatized)
texts = data_lemmatized
corpus = [id2word.doc2bow(text) for text in texts]
Erstellen eines LDA-Themenmodells
Wir haben bereits alles implementiert, was zum Trainieren des LDA-Modells erforderlich ist. Jetzt ist es an der Zeit, das LDA-Themenmodell zu erstellen. Für unser Implementierungsbeispiel kann dies mithilfe der folgenden Codezeile erfolgen:
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
)
Implementierungsbeispiel
Sehen wir uns das vollständige Implementierungsbeispiel zum Erstellen eines LDA-Themenmodells an.
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
)
Wir können jetzt das oben erstellte LDA-Modell verwenden, um die Themen abzurufen und die Modell-Ratlosigkeit zu berechnen.