anobiidae's blog

個人的に自然言語処理とかに関して、調べ物したもののメモとかを残す場所。

しーかたがないのでCGBのコードを解読解読

http://d.hatena.ne.jp/n_shuyo/20110214/lda さんのコードを眺めつつ、CGBを実装するか…

class LDA: """LDA : collapsed Gibbs で推論""" def __init__(self, K, alpha, beta): self.K = K self.alpha = alpha # parameter of topics prior self.beta = beta # parameter of words prior

これは初期化部分。coppapsed Gibbs samplingの場合、α、βはvectorではなくvariableと。

 

 def set_corpus(self, corpus, stopwords): """コーパスの読み込みとカウンタの初期化""" voca = vocabulary.Vocabulary(stopwords==0) self.docs = [voca.doc_to_ids(doc) for doc in corpus] M = len(self.docs) self.V = voca.size() self.z_m_n =  # topics of words of documents self.n_m_z = numpy.zeros((M, self.K)) + self.alpha # word count of each document and topic self.n_z_t = numpy.zeros((self.K, self.V)) + self.beta # word count of each topic and vocabulary self.n_z = numpy.zeros(self.K) + self.V * self.beta # word count of each topic 
        

 

vocaはvocabraryファイルを読み込みます、かな?

self.docsは、えーっと、vocaのdoc_to_ids(doc) ただし、docはcurpus内の物を順繰りに使うと。idsは頻度……かな?

 

Mは文書数、Vは全語彙数(つまりvocabularyに含まれるwordの種別数)

self_z_m_n は一次元配列(ただしまだ空)

self.n_m_z はarray(M×K)で、初期値α、これは確か高速化でこうやってると。

self.n_z_tはarray(K×V)で、初期値β

self.n_z はarray(K)で、初期値 V × β

 

 self.N = 0 for m, doc in enumerate(self.docs): self.N += len(doc) z_n = numpy.random.randint(0, self.K, len(doc)) self.z_m_n.append(z_n) for t, z in zip(doc, z_n): self.n_m_z[m, z] += 1 self.n_z_t[z, t] += 1 self.n_z[z] += 1 return voca

Nは0で初期化したけど、docのlenで加算しますよ…… len(doc)が「この文章の単語出現数」で、Nは「このcorpusの単語出現数」か。

 

for m, doc in enumerate(self.docs) は……?

http://d.hatena.ne.jp/meganii/20111121/1321884656

をみるとつまり、 foreach(self.docs as $m => $doc)と(謎記載)

enumerate()は「この引数にindex付ける」という意味です、と。

 

z_n は0~Kの間の、len(doc)=この文章の単語数の乱数。

self.z_m_nに追加する、とあるけど要するにz_m_n[m] = z_n ですと。

で、for t,z in zip(doc,z_n) ???

docの各要素をkeyに、z_nの各要素をvalueにした配列を作って、t,zでそれぞれ回す、かな?

t in doc には単語、z in z_nには乱数で適当に決めたトピック、で「単語に適当にtopic割り振り」かな?

self.n_m_z[m,z] は「ある文章mのtopic zの出現数」

self.n_z_t[z,t] は「あるtopic zの単語 tの出現数」

self.n_z[z] は「あるtopic zの出現数」

と。