我正在使用内核密度估计(KDE)(http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html)的SciPy实现,到目前为止工作正常。但是,我现在想在特定点获得KDE的梯度。
我查看了该库的Python源代码,但未能弄清楚如何轻松实现此功能。有人知道这样做的方法吗?
答案 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
以获得与评估所有四个方向上p
和p+delta
的密度估算相关的结果,这是一个标志,我当然可以离开这里。