LDA
Latent Dirichlet
Dirichlet Distribution & Dirichlet Process: 狄利克雷分布于狄利克雷过程
作者:肉很多链接:
首先先看
现在问题来了。
Q:我们如何知道这枚硬币抛出字的概率?我们知道,如果可以一直抛下去,最后
举个例子,比如:
那我们如果有个什么工具能描述一下这个
到这里,其实很自然地会想到把
我们现在用更正规的语言重新整理一下思路。现在有个硬币得到
现在我们来看看
在这里
带着以上这个结论,我们再来看这个抛硬币问题:
连续抛
现在在来看
更有意思的是,当我们每多抛一次硬币,出现字时,我们只需要
其实之所以计算会变得这么简单,是因为被
ok。讲到这你应该明白,对于有两个结果的重复
结论
from scipy.stats import dirichlet, poisson
from numpy.random import choice
from collections import defaultdict
num_documents = 5
num_topics = 2
topic_dirichlet_parameter = 1 # beta
term_dirichlet_parameter = 1 # alpha
vocabulary = ["see", "spot", "run"]
num_terms = len(vocabulary)
length_param = 10 # xi
term_distribution_by_topic = {} # Phi
topic_distribution_by_document = {} # Theta
document_length = {}
topic_index = defaultdict(list)
word_index = defaultdict(list)
term_distribution = dirichlet(num_terms - [term_dirichlet_parameter])
topic_distribution = dirichlet(num_topics - [topic_dirichlet_parameter])
# 遍历每个主题
for topic in range(num_topics):
# 采样得出每个主题对应的词分布
term_distribution_by_topic[topic] = term_distribution.rvs()[0]
# 遍历所有的文档
for document in range(num_documents):
# 采样出该文档对应的主题分布
topic_distribution_by_document[document] = topic_distribution.rvs()[0]
topic_distribution_param = topic_distribution_by_document[document]
# 从泊松分布中采样出文档长度
document_length[document] = poisson(length_param).rvs()
# 遍历整个文档中的所有词
for word in range(document_length[document]):
topics = range(num_topics)
# 采样出某个生成主题
topic = choice(topics, p=topic_distribution_param)
topic_index[document].append(topic)
# 采样出某个生成词
term_distribution_param = term_distribution_by_topic[topic]
word_index[document].append(choice(vocabulary, p=term_distribution_param))
如果还有困惑的同学可以参考如下
def perplexity(self, docs=None):
if docs == None: docs = self.docs
# 单词在主题上的分布矩阵
phi = self.worddist()
log_per = 0
N = 0
Kalpha = self.K * self.alpha
//遍历语料集中的所有文档
for m, doc in enumerate(docs):
// n_m_z 为每个文档中每个主题的单词数,theta 即是每个单词出现的频次占比
theta = self.n_m_z[m] / (len(self.docs[m]) + Kalpha)
for w in doc:
// numpy.inner(phi[:,w], theta) 即是某个出现的概率统计值
log_per -= numpy.log(numpy.inner(phi[:,w], theta))
N += len(doc)
return numpy.exp(log_per / N)
Introduction
LDA has been widely used in textual analysis,

Mathematics
Beta 分布:Dirichlet 分布的基础
$$
f(x) =
\left {
\begin{aligned}
\frac{1}{B(\alpha,\beta)}x^{\alpha-1}(1-x)^{\beta-1}, x \in (0,1) \
其中
$$ \Gamma(x) = \int_0^{\infty}t^{x-1}e^{-t}dt \Rightarrow \Gamma(n) = (n-1)! \Rightarrow B(\alpha,\beta)=\frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)} $$
Dirichlet 分布: 多项分布的共轭分布
$$ \alpha = \alpha_1 , \beta = \alpha_2 , x = x_1 , x - 1 = x_2 $$
$$
f(\vec{p} | \vec{\alpha}) = \left {
\begin{aligned}
\frac{1}{\Delta(\vec{\alpha})} \prod_{k=1}^{K} p_k^{\alpha_k - 1} ,p_k \in (0,1) \
可以简记为:
$$ Dir(\vec{p} | \vec{\alpha}) = \frac{1}{\Delta(\vec{\alpha})} \prod_{k=1}^{K} p_k^{\alpha_k - 1} $$
其中
$$ \Delta(\vec{\alpha}) = \frac{ \prod_{k=1}^K \Gamma(\alpha_k)}{ \Gamma(\sum_{k=1}^{K}\alpha_k)} $$
该部分在给定的
Symmetric Dirichlet Distribution( 对称Dirichlet 分布)
一旦采取了对称的
$$ Dir(\vec{p} | \alpha,K) = \frac{1}{\Delta_K(\alpha)} \prod_{k=1}^{K} p_k^{\alpha - 1} \ \Delta_K(\vec{\alpha}) = \Gamma^K(\alpha){ \Gamma(K * \alpha)} $$
而不同的
在实际的应用中,一般会选用
模型解释

Terminology
-
字典中共有
$V$ 个不可重复的term ,如果这些term 出现在了具体的文章中,就是word 。在具体的某文章中的word 当然是可能重复的。 -
语料库
(Corpus) 中共有$m$ 篇文档,分别是$d_1,d_2,\dots,d_m$ ,每篇文章长度为$N_m$ ,即由$N_i$ 个word 组成。每篇文章都有各自的主题分布,主题分布服从多项式分布,该多项式分布的参数服从Dirichlet 分布,该Dirichlet 分布的参数为$\vec{ \alpha }$ 。注意,多项分布的共轭先验分布为Dirichlet 分布。怎么来看待所谓的文章主题服从多项分布呢。你每一个文章等于多一次实验,
$m$ 篇文档就等于做了$m$ 次实验。而每次实验中有$K$ 个结果,每个结果以一定概率出现。 -
一共涉及到
$K$( 值给定) 个主题,$T_1,T_2,\dots,T_k$。每个主题都有各自的词分布,词分布为多项式分布,该多项式分布的参数服从Dirichlet 分布,该Diriclet 分布的参数为$\vec{\beta}$ 。注意,一个词可能从属于多个主题。
模型过程
参数学习
给定一个文档集合,
似然概率
一个词
$$ p(w_{m,n}=t | \vec{\theta_m},\Phi) = \sum_{k=1}^K p(w_{m,n}=t | \vec{\phi_k})p(z_{m,n}=k|\vec{\theta}_m) $$
上式即给定某个主题的情况下能够看到某个词的概率的总和。每个文档中出现主题
$$ p(W | \Theta,\Phi) = \prod_{m=1}^{M}p(\vec{w_m} | \vec{\theta_m},\Phi) = \prod_{m=1}^M \prod_{n=1}^{N_m}p(w_{m,n}|\vec{\theta_m},\Phi) $$
Gibbs Sampling
首先通俗理解一下,在某篇文档中存在着
$N_m$ 个词,依次根据其他的词推算某个词来自于某个主题的概率,从而达到收敛。最开始的时候,某个词属于某个主题是随机分配的。Gibbs Sampling 的核心在于找出某个词到底属于哪个主题。
$$ p(\vec{w},\vec{z} | \vec{\alpha},\vec{\beta}) = p(\vec{w} | \vec{z},\vec{\beta})p(\vec{z} | \vec{\alpha}) $$
第一项因子是给定主题采样词的过程。后面的因此计算,
$$ p(\vec{w} | ,\vec{z},\vec{\beta}) = \int p(\vec{w} | \vec{z},\vec{\Phi})p(\Phi | \vec{\beta})d \Phi \ = \int \prod_{z=1}^{K} \frac{1}{\Delta(\vec{\beta})}\prod_{t=1}^V \phi_{z,t}^{n_z^{(t)} + \beta_t - 1}d\vec{\phi_z} \ = \prod_{z=1}^{K}\frac{\Delta(\vec{n_z} + \vec{\beta})}{\Delta(\vec{ \beta })} , \vec{n_z} = { n_z^{(t)} }_{t=1}^V $$
$$ p(\vec{z} | \vec{\alpha}) \ = \int p(\vec{z} | \Theta) p(\Theta|\vec{\alpha}) d\Theta \ = \int \prod_{m=1}^{M} \frac{1}{\Delta(\vec\alpha)} \prod_{k=1}^K\theta_{m,k}^{ n_m^{(k)} + \alpha_k - 1 }d\vec{\theta_m} \ = \prod_{m=1}^M \frac{ \Delta(\vec{n_m} + \vec\alpha) }{ \Delta(\vec\alpha) }, \vec{n_m}={ n_m^{(k)} }_{k=1}^K $$
Gibbs Updating Rule
词分布和主题分布总结
经过上面的
$$ \phi_{k,t} = \frac{ n_k^{(t)} + \beta_t }{ \sum^V_{t=1}n_k^{(t)} + \beta_t } \ \theta_{m,k} = \frac{ n_m^{(k)} + \alpha_k }{ \sum^K_{k=1}n_m^{(k)} + \alpha_k } \ $$
$$ p(\vec{\theta_m} | \vec{z_m}, \vec{\alpha} ) = \frac{1}{Z_{\theta_m}} \prod_{n=1}^{N_m} p(z_{m,n} | \vec{\theta_m} * p(\vec{\theta_m} | \vec{alpha} )) = Dir(\vec{\theta_m} | \vec{n_m} + \vec{\alpha}) \ p(\vec{\phi_k} | \vec{z}, \vec{w}, \vec{\beta} ) = \frac{1}{Z_{\phi_k}} \prod_{i:z_i=k} p(w_i | \vec{\phi_k}) * p(\vec{\phi_k} | \vec{\beta}) = Dir(\vec{\phi_k} | \vec{n_k} + \vec{\beta}) $$
代码实现
代码的输入有文档数目
超参数的确定
- 交叉验证
$\alpha$ 表达了不同文档间主题是否鲜明,$\beta$ 度量了有多少近义词能够属于同一个类别。- 给定主题数目
$K$ ,可以使用:
$$ \alpha = 50 / K \ \beta = 0.01 $$