web-dev-qa-db-ja.com

トピックの配布:python

GensimからLDAコードを実行して、それぞれのキーワードで上位10トピックを取得できます。

ここで、LDAアルゴが各トピックにクラスター化されているドキュメントを確認することで、LDAアルゴがどれほど正確であるかを確認するために、さらに一歩進みたいと思います。これはgensim LDAで可能ですか?

基本的に私はこのようなことをしたいと思いますが、pythonおよびgensimを使用します。

topicmodelsを使用したLDA、どのドキュメントがどのトピックに属しているかを確認するにはどうすればよいですか?

22
jxn

トピックの確率を使用して、いくつかのしきい値を設定し、それをクラスタリングのベースラインとして使用することができますが、この「ハッキー」な方法よりもクラスタリングを行うより良い方法があると確信しています。

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']

明確にするために:

# 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)

上記のコードは、すべてのドキュメントのすべての単語とすべてのトピックのスコアの合計です。次に、スコアの数で合計を正規化します。

28
alvas

のトリックを使用したい場合

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]

alvasによる以前の回答では、LdaModelでminimum_probability = 0を設定してください

gensim.models.ldamodel.LdaModel(corpus,
            num_topics=num_topics, id2Word = dictionary,
            passes=2, minimum_probability=0)

それ以外の場合、gensimはすべてのコーパスをminimum_probabilityよりも低い確率で抑制するため、lda_corpusとドキュメントの次元が一致しない場合があります。

ドキュメントをトピックにグループ化する別の方法は、最大確率に従ってトピックを割り当てることです

    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])

lda[mm]は、おおまかに言ってリストのリスト、つまり2Dマトリックスです。行の数はドキュメントの数であり、列の数はトピックの数です。各マトリックス要素は、たとえば(3,0.82)という形式のタプルです。ここで3はトピックインデックスを指し、0.82はそのトピックの対応する確率を指します。デフォルトでは、minimum_probability=0.01および0.01未満の確率のタプルはlda[mm]で省略されています。最大の確率でグループ化メソッドを使用する場合は、1 /#topicsに設定できます。

9
nos

lda_corpus [i] [j]の形式は[(0、t1)、(0、t2)...、(0、t10)、....(n、t10)]で、最初の項はドキュメントを示しますインデックスと第2項は、その特定のドキュメントのトピックの確率を示します。

2
ayushi