And*_*ham 5 python statistics numpy scipy scikit-learn
我有两个GMM用于在同一空间中拟合两组不同的数据,我想计算它们之间的KL分歧.
目前我正在使用sklearn中定义的GMM(http://scikit-learn.org/stable/modules/generated/sklearn.mixture.GMM.html)和KL-divergence的SciPy实现(http://docs.scipy) .org/doc/scipy-dev/reference/generated/scipy.stats.entropy.html)
我该怎么做呢?我是否只想创建大量的随机点,在两个模型中的每个模型(称为P和Q)上获取它们的概率,然后将这些概率用作我的输入?或者在SciPy/SKLearn环境中有更多规范的方法吗?
Dou*_*gal 15
对于GMM之间的KL分歧,没有封闭形式.不过,你可以很容易地做蒙特卡洛.回想一下KL(p||q) = \int p(x) log(p(x) / q(x)) dx = E_p[ log(p(x) / q(x)).所以:
def gmm_kl(gmm_p, gmm_q, n_samples=10**5):
X = gmm_p.sample(n_samples)
log_p_X, _ = gmm_p.score_samples(X)
log_q_X, _ = gmm_q.score_samples(X)
return log_p_X.mean() - log_q_X.mean()
Run Code Online (Sandbox Code Playgroud)
(mean(log(p(x) / q(x))) = mean(log(p(x)) - log(q(x))) = mean(log(p(x))) - mean(log(q(x)))在计算上稍微便宜一些.)
你不想用scipy.stats.entropy; 这是离散分布.
如果你想要对称和平滑的Jensen-Shannon发散 KL(p||(p+q)/2) + KL(q||(p+q)/2),那就非常相似:
def gmm_js(gmm_p, gmm_q, n_samples=10**5):
X = gmm_p.sample(n_samples)
log_p_X, _ = gmm_p.score_samples(X)
log_q_X, _ = gmm_q.score_samples(X)
log_mix_X = np.logaddexp(log_p_X, log_q_X)
Y = gmm_q.sample(n_samples)
log_p_Y, _ = gmm_p.score_samples(Y)
log_q_Y, _ = gmm_q.score_samples(Y)
log_mix_Y = np.logaddexp(log_p_Y, log_q_Y)
return (log_p_X.mean() - (log_mix_X.mean() - np.log(2))
+ log_q_Y.mean() - (log_mix_Y.mean() - np.log(2))) / 2
Run Code Online (Sandbox Code Playgroud)
(log_mix_X/ log_mix_Y实际上是混合密度的两倍的对数;从平均操作中拉出来可以节省一些失败.)
| 归档时间: |
|
| 查看次数: |
4631 次 |
| 最近记录: |