Distribución de temas: ¿Cómo vemos qué documento pertenece a qué tema después de hacer LDA en python?
nltk gensim (3)
Soy capaz de ejecutar el código LDA de gensim y obtuve los 10 temas principales con sus respectivas palabras clave.
Ahora me gustaría ir un paso más allá para ver qué tan preciso es el LDA algo al ver qué documento se agrupan en cada tema. ¿Es esto posible en gensim LDA?
Básicamente me gustaría hacer algo como esto, pero en python y usando gensim.
LDA con modelos de temas, ¿cómo puedo ver a qué temas pertenecen diferentes documentos?
Si quieres usar el truco de
cluster1 = [j for i,j in zip(lda_corpus,documents) if i[0][1] > threshold]
cluster2 = [j for i,j in zip(lda_corpus,documents) if i[1][1] > threshold]
cluster3 = [j for i,j in zip(lda_corpus,documents) if i[2][1] > threshold]
en la respuesta anterior de alvas, asegúrese de establecer minimum_probability = 0 en LdaModel
gensim.models.ldamodel.LdaModel(corpus,
num_topics=num_topics, id2word = dictionary,
passes=2, minimum_probability=0)
De lo contrario, es posible que la dimensión de lda_corpus y los documentos no concuerden, ya que gensim suprimirá cualquier corpus con una probabilidad menor que la probabilidad mínima.
Una forma alternativa de agrupar documentos en temas es asignar temas de acuerdo con la probabilidad máxima
lda_corpus = [max(prob,key=lambda y:y[1])
for prob in lda[mm] ]
playlists = [[] for i in xrange(topic_num])]
for i, x in enumerate(lda_corpus):
playlists[x[0]].append(documents[i])
Nota lda[mm]
es, en términos generales, una lista de listas, o matriz 2D. El número de filas es el número de documentos y el número de columnas es el número de temas. Cada elemento de la matriz es una tupla de la forma (3,0.82)
por ejemplo. Aquí 3 se refiere al índice de temas y 0.82 la probabilidad correspondiente de ser de ese tema. De forma predeterminada, la minimum_probability=0.01
probabilidad minimum_probability=0.01
y cualquier tupla con probabilidad menor a 0.01 se omite en lda[mm]
. Puede configurarlo para que sea 1 / # temas si utiliza el método de agrupación con la máxima probabilidad.
Usando las probabilidades de los temas, puede intentar establecer un umbral y usarlo como una línea de base de agrupación en clústeres, pero estoy seguro de que hay mejores maneras de hacer agrupaciones en clústeres que este método "pirateado".
from gensim import corpora, models, similarities
from itertools import chain
""" DEMO """
documents = ["Human machine interface for lab abc computer applications",
"A survey of user opinion of computer system response time",
"The EPS user interface management system",
"System and human system engineering testing of EPS",
"Relation of user perceived response time to error measurement",
"The generation of random binary unordered trees",
"The intersection graph of paths in trees",
"Graph minors IV Widths of trees and well quasi ordering",
"Graph minors A survey"]
# remove common words and tokenize
stoplist = set(''for a of the and to in''.split())
texts = [[word for word in document.lower().split() if word not in stoplist]
for document in documents]
# remove words that appear only once
all_tokens = sum(texts, [])
tokens_once = set(word for word in set(all_tokens) if all_tokens.count(word) == 1)
texts = [[word for word in text if word not in tokens_once] for text in texts]
# Create Dictionary.
id2word = corpora.Dictionary(texts)
# Creates the Bag of Word corpus.
mm = [id2word.doc2bow(text) for text in texts]
# Trains the LDA models.
lda = models.ldamodel.LdaModel(corpus=mm, id2word=id2word, num_topics=3, /
update_every=1, chunksize=10000, passes=1)
# Prints the topics.
for top in lda.print_topics():
print top
print
# Assigns the topics to the documents in corpus
lda_corpus = lda[mm]
# Find the threshold, let''s set the threshold to be 1/#clusters,
# To prove that the threshold is sane, we average the sum of all probabilities:
scores = list(chain(*[[score for topic_id,score in topic] /
for topic in [doc for doc in lda_corpus]]))
threshold = sum(scores)/len(scores)
print threshold
print
cluster1 = [j for i,j in zip(lda_corpus,documents) if i[0][1] > threshold]
cluster2 = [j for i,j in zip(lda_corpus,documents) if i[1][1] > threshold]
cluster3 = [j for i,j in zip(lda_corpus,documents) if i[2][1] > threshold]
print cluster1
print cluster2
print cluster3
[out]
:
0.131*trees + 0.121*graph + 0.119*system + 0.115*user + 0.098*survey + 0.082*interface + 0.080*eps + 0.064*minors + 0.056*response + 0.056*computer
0.171*time + 0.171*user + 0.170*response + 0.082*survey + 0.080*computer + 0.079*system + 0.050*trees + 0.042*graph + 0.040*minors + 0.040*human
0.155*system + 0.150*human + 0.110*graph + 0.107*minors + 0.094*trees + 0.090*eps + 0.088*computer + 0.087*interface + 0.040*survey + 0.028*user
0.333333333333
[''The EPS user interface management system'', ''The generation of random binary unordered trees'', ''The intersection graph of paths in trees'', ''Graph minors A survey'']
[''A survey of user opinion of computer system response time'', ''Relation of user perceived response time to error measurement'']
[''Human machine interface for lab abc computer applications'', ''System and human system engineering testing of EPS'', ''Graph minors IV Widths of trees and well quasi ordering'']
Solo para que quede más claro:
# Find the threshold, let''s set the threshold to be 1/#clusters,
# To prove that the threshold is sane, we average the sum of all probabilities:
scores = []
for doc in lda_corpus
for topic in doc:
for topic_id, score in topic:
scores.append(score)
threshold = sum(scores)/len(scores)
El código anterior es la suma de la puntuación de todas las palabras y en todos los temas para todos los documentos. Luego normaliza la suma por el número de puntuaciones.
lda_corpus [i] [j] tiene la forma [(0, t1), (0, t2) ..., (0, t10), .... (n, t10)] donde el primer término denota el documento índice y el segundo término denota la probabilidad del tema en ese documento en particular.