SciPy KDE渐变

时间:2014-10-13 09:37:50

标签: python numpy scipy

我正在使用内核密度估计(KDE)(http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html)的SciPy实现,到目前为止工作正常。但是,我现在想在特定点获得KDE的梯度。

我查看了该库的Python源代码,但未能弄清楚如何轻松实现此功能。有人知道这样做的方法吗?

1 个答案:

答案 0 :(得分:1)

如果你看一下你引用的来源,你会发现密度估计是根据数据集中所有点的贡献构建的。假设你现在只想评估一个points[:,i]点(第219行) -222):

diff = self.dataset - points[:, i, newaxis]
tdiff = dot(self.inv_cov, diff)
energy = sum(diff * tdiff, axis=0) / 2.0
result[i] = sum(exp(-energy), axis=0)

在矩阵表示法中(没有可用的LaTeX?),这将编写,对于数据集中的单个点D和要评估为

的点p
d = D - p
t = Cov^-1 d
e = 1/2 d^T t
r = exp(-e)

您正在寻找的渐变是grad(r) = (dr/dx, dr/dy)

dr/dx = d(exp(-e))/dx 
      = -de/dx exp(-e)
      = -d(1/2 d^T Cov^-1 d)/dx exp(-e)
      = -(Cov^-1 d) exp(-e)

同样适用于dr/dy。因此,您需要做的就是计算术语Cov^-1 d并将其与您已经获得的结果相乘。

result = zeros((self.d,m), dtype=float)    
[...]
diff = self.dataset - points[:, i, newaxis]
tdiff = dot(self.inv_cov, diff)
energy = sum(diff * tdiff, axis=0) / 2.0
grad = dot(self.inv_cov, diff)
result[:,i] = sum(grad * exp(-energy), axis=1)

出于某种原因,我需要在计算-1时放弃grad以获得与评估所有四个方向上pp+delta的密度估算相关的结果,这是一个标志,我当然可以离开这里。