機械学習・自然言語処理の勉強メモ

学んだことのメモやまとめ

gensimでLDA

LDA(Latent Dirichlet Allocation)



1つの文書が複数のトピックから成ることを仮定した言語モデルの一種。
各文書には潜在トピックがあると仮定し、統計的に共起しやすい単語の集合が生成される要因を、この潜在トピックという観測できない確率変数で定式化する。

LDAに関しては下記書籍を参考とした。
トピックモデルによる統計的潜在意味解析

gensim



実際にやってみた。
(gensimを利用するととても簡単にできる。)

import cPickle
from gensim import corpora, matutils
from gensim import models
from gensim.models import LdaModel
import numpy as np


def main():
    dataset, vocab = cPickle.load(open("mr.p", "rb"))
    revs = [row['text'].split(' ') for row in dataset]
    labels = [row['y'] for row in dataset]
    dic = corpora.Dictionary(revs)
    dic.filter_extremes(no_below=20, no_above=0.7)
    bow_corpus = [dic.doc2bow(rv) for rv in revs]
    lda_model = LdaModel(bow_corpus, id2word=dic, num_topics=20)
    print lda_model[bow_corpus[0]]


if __name__ == '__main__':
    main()

と書くだけで、文書中のトピックの割合が取得できる。

[(1, 0.22445983304291817), (17, 0.55363776888969674), (19, 0.14462966979334729)]

その他のメソッドも試してみた。

get_topics()

「トピック数×語彙数」の行列を返す。

lda_model.get_topics()
[[  1.40446616e-05   1.40446615e-05   1.40446616e-05 ...,   9.82555128e-05
    1.40446618e-05   4.90368539e-05]
 [  1.20256228e-05   1.20256229e-05   1.20256229e-05 ...,   1.55216513e-04
    3.11760227e-04   1.20256228e-05]
 [  1.55919044e-05   1.55919045e-05   1.55919044e-05 ...,   1.55919046e-05
    1.55919047e-05   1.55919045e-05]
 ..., 
 [  1.19235269e-05   1.19235269e-05   1.21649655e-04 ...,   3.65494502e-04
    1.61219783e-03   1.19235270e-05]
 [  1.41439113e-05   1.41439113e-05   1.41439112e-05 ...,   1.41439113e-05
    1.41439115e-05   1.41439113e-05]
 [  1.02977463e-02   1.62936741e-04   1.09163449e-05 ...,   1.57830283e-05
    4.47850511e-04   1.09163453e-05]]
get_topic_terms(topicid)

指定したトピックID内の関連単語のIDを返す。

lda_model.get_topic_terms(0)
[(674, 0.099598859213123059), (613, 0.055008575703275893), (1026, 0.040194958370204814), (586, 0.023299022204587051), (409, 0.020764761216239783), (217, 0.019417292755655135),…]
get_term_topics(word_id)

指定した単語IDが最も所属してそうなトピックIDを返す。

lda_model.get_term_topics(0)
[(19, 0.010189890165199727)]
get_document_topics(bow)

与えらえたBoWのトピック分布を返す。

lda_model.get_document_topics(bow_corpus[0])
[(13, 0.69405250751360936), (14, 0.22412930939946971)]

per_word_topics=Trueとすると、

  • 文書全体のトピック分布
  • 文書内の単語ID毎のトピックID
  • 単語ID毎のトピック分布

が返される。

lda_model.get_document_topics(bow_corpus[0], per_word_topics=True)
([(9, 0.43971687652113278), (10, 0.19073529930448427), (11, 0.091512148784717667), (12, 0.11118590105453396), (17, 0.10915746580796076)], [(39, [10, 9, 12, 17]), (43, [9, 10, 12]), (151, [9, 10, 12, 17, 11]), (412, [9, 10, 12, 17, 11]), (562, [9, 10, 17, 12, 11]), (760, [12, 10]), (882, [9, 10, 12]), (961, [9]), (1553, [11]), (1642, [17]), (2193, [10])], [(39, [(9, 0.35812025010416354), (10, 0.39548224502999885), (12, 0.16138260507795527), (17, 0.085014897325994529)]), (43, [(9, 0.90591614106435558), (10, 0.070274114320047626), (12, 0.023809743265930976)]), (151, [(9, 0.40908844296361441), (10, 0.32224450806838406), (11, 0.046493798207396117), (12, 0.13963577171766678), (17, 0.082537477552365041)]), (412, [(9, 0.53988495897246425), (10, 0.21588508541351215), (11, 0.0393998855008671), (12, 0.1140384251004949), (17, 0.09079164322614694)]), (562, [(9, 1.5016800952657685), (10, 0.2394395900154252), (11, 0.058161520114690037), (12, 0.087480131990062951), (17, 0.11323866017325207)]), (760, [(10, 0.15331773702114965), (12, 0.84668226255330858)]), (882, [(9, 0.95660045501581226), (10, 0.022120129187718884), (12, 0.021279414875852359)]), (961, [(9, 0.99998296320671409)]), (1553, [(11, 0.99553355887725581)]), (1642, [(17, 0.99726244519637808)]), (2193, [(10, 0.9999999990873405)])])