anobiidae's blog

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

LDAの実装その2

    def inference(self):
        """イテレーション1回分の推論を行う"""
        for m, doc in enumerate(self.docs):
            z_n = self.z_m_n[m]
            for n, t in enumerate(doc):
                # n 番目の単語 t (トピック z)についてカウンタを減算
                z = z_n[n]
                self.n_m_z[m, z] -= 1
                self.n_z_t[z, t] -= 1
                self.n_z[z] -= 1

                # トピックの事後分布からサンプリング
                p_z = self.n_z_t[:, t] * self.n_m_z[m] / self.n_z
                new_z = numpy.random.multinomial(1, p_z / p_z.sum()).argmax()

                # サンプリングされた新トピックを設定&カウンタを増加
                z_n[n] = new_z
                self.n_m_z[m, new_z] += 1
                self.n_z_t[new_z, t] += 1
                self.n_z[new_z] += 1                
                

inferenceの意味は演繹、ね。

 

foreach(self.docs as $m => $doc){

z_n = z_m_n[m];

foreach(doc in $n => $t){

z = z_n[n];

n_m_z[m, z] --; n_z_t[z,t] --; n_z[z] --;  # n番目の単語を無所属に。

new_z = ... は後でやるとして

z_n[n] = new_z

n_m_z[m, new_z] ++;

n_z_t[new_z, t] ++;

n_z[new_z] ++; # n番目の単語をnew_z所属に変更

 

という感じかー。 z_m_n[m][n] はm番目の文章のn番目のキーワードはどこのtopicですか?が入っていると。

 

                # トピックの事後分布からサンプリング
                p_z = self.n_z_t[:, t] * self.n_m_z[m] / self.n_z
                new_z = numpy.random.multinomial(1, p_z / p_z.sum()).argmax()

 

 

で、ここはGibbs samplingの更新式だろうなー

p_z_sum = 0;

for(i=0;i<K;i++){ p_z[i] = n_z_t[i, t] * self.n_m_z[m,i] / self.n_z[i]; p_z_sum += p_z[i]; }

的な感じだろう、多分。

multinomial() はDraw samples from a multinomial distribution.。

で、p_z[i]/p_z_sumの確率で選んで最大になるものを選びます……

 

Cで組むのめんどくさい(;ω;)

Fast LDAの論文からすると

P[k] ← P[k -1] + ... としておいて u ← uniform[0..1], u<P[k]/P[K]で探索と。