如何从PyMC3中的Dirichlet过程中提取无监督的聚类?

时间:2017-01-09 17:55:40

标签: python machine-learning bayesian pymc3 unsupervised-learning

我刚刚通过Bayesian Analysis in Python完成了Osvaldo Martin本书(了解贝叶斯概念和一些花哨的numpy索引的好书)。

我真的想将我的理解扩展到贝叶斯混合模型,用于无监督的样本聚类。我的所有谷歌搜索都引导我Austin Rochford's tutorial,这真的是提供了丰富的信息。我理解发生了什么,但我不清楚如何适应群集(特别是使用群集分配的多个属性,但这是一个不同的主题)。

我了解如何为Dirichlet distribution分配先验,但我无法弄清楚如何在PyMC3中获取群集。看起来mus的大多数会聚到质心(即我从中采样的分布均值),但它们仍然是分开的components。我考虑过为weights(模型中的w)设置一个截止点,但这似乎并没有像我想象的那样工作,因为多个components的平均参数略有不同{ {1}}正在融合。

如何从此mus模型中提取聚类(质心)?我为其提供了最多PyMC3个组件,我想收集到{{1} }。 15似乎位于正确的位置,但是权重被搞砸了b / c它们正在其他群集之间分配,因此我无法使用权​​重阈值(除非我合并它们但我不会# 39;不要认为这是通常的做法。

3

enter image description here

mus

enter image description here

以下类似问题

https://stats.stackexchange.com/questions/120209/pymc3-dirichlet-distribution用于回归而非群集

关于DP过程的

https://stats.stackexchange.com/questions/108251/image-clustering-and-dirichlet-process理论

https://stats.stackexchange.com/questions/116311/draw-a-multinomial-distribution-from-a-dirichlet-distribution解释了DP

Dirichlet process in PyMC 3指导我上面的Austin Rochford教程

1 个答案:

答案 0 :(得分:7)

使用pymc3添加一些新功能将有助于明确这一点。我想我在添加后更新了Dirichlet Process示例,但在文档清理期间似乎已经恢复到旧版本;我很快就会解决这个问题。

其中一个困难是,您生成的数据比组件均可容纳的先验更加分散;如果您将数据标准化,样本应该更快地混合。

第二个是pymc3现在支持混合物分布,其中指标变量component被边缘化了。这些边际混合物分布将有助于加速混合,并允许您使用NUTS(使用ADVI初始化)。

最后,对于无限模型的这些截断版本,当遇到计算问题时,增加潜在组件的数量通常很有用。我发现K = 30对于此模型的效果优于K = 15

以下代码实现了这些更改,并显示了" active"可以提取组件均值。

from matplotlib import pyplot as plt
import numpy as np
import pymc3 as pm
import seaborn as sns
from theano import tensor as T

blue = sns.color_palette()[0]

np.random.seed(462233) # from random.org

N = 150

CENTROIDS = np.array([0, 10, 50])
WEIGHTS = np.array([0.4, 0.4, 0.2])

x = np.random.normal(CENTROIDS[np.random.choice(3, size=N, p=WEIGHTS)], size=N)
x_std = (x - x.mean()) / x.std()

fig, ax = plt.subplots(figsize=(8, 6))

ax.hist(x_std, bins=30);

Standardized data

K = 30

with pm.Model() as model:
    alpha = pm.Gamma('alpha', 1., 1.)
    beta = pm.Beta('beta', 1., alpha, shape=K)
    w = pm.Deterministic('w', beta * T.concatenate([[1], T.extra_ops.cumprod(1 - beta)[:-1]]))

    tau = pm.Gamma('tau', 1., 1., shape=K)
    lambda_ = pm.Uniform('lambda', 0, 5, shape=K)
    mu = pm.Normal('mu', 0, tau=lambda_ * tau, shape=K)
    obs = pm.NormalMixture('obs', w, mu, tau=lambda_ * tau,
                           observed=x_std)

with model:
    trace = pm.sample(2000, n_init=100000)

fig, ax = plt.subplots(figsize=(8, 6))

ax.bar(np.arange(K) - 0.4, trace['w'].mean(axis=0));

我们看到似乎使用了三个组件,并且它们的权重与真实值相当接近。

Mixture weights

最后,我们看到这三个组成部分的后验预期方法与真实(标准化)方法相当匹配。

trace['mu'].mean(axis=0)[:3]
  

数组([ - 0.73763891,-0.17284594,2.10423978])

(CENTROIDS - x.mean()) / x.std()
  

数组([ - 0.73017789,-0.16765707,2.0824262])