【问题标题】:How to implement Kernel density estimation in multivariate/3D如何在多变量/3D 中实现核密度估计
【发布时间】:2015-08-22 04:29:47
【问题描述】:

我有类似以下 fromat 的数据集,我试图找出具有最佳带宽的内核密度估计。

data = np.array([[1, 4, 3], [2, .6, 1.2], [2, 1, 1.2],
         [2, 0.5, 1.4], [5, .5, 0], [0, 0, 0],
         [1, 4, 3], [5, .5, 0], [2, .5, 1.2]])

但我不知道如何处理它。还有如何找到 Σ 矩阵。

更新

我尝试了 scikit-learn 工具包中的 KDE 函数来找出单变量 (1D) kde,

# kde function
def kde_sklearn(x, x_grid, bandwidth):
    kde = KernelDensity(kernel='gaussian', bandwidth=bandwidth).fit(x)
    log_pdf = kde.score_samples(x_grid[:, np.newaxis])
    return np.exp(log_pdf)

# optimal bandwidth selection
from sklearn.grid_search import GridSearchCV
grid = GridSearchCV(KernelDensity(), {'bandwidth': np.linspace(.1, 1.0, 30)}, cv=20)
grid.fit(x)
bw = grid.best_params_

# pdf using kde
pdf = kde_sklearn(x, x_grid, bw)
ax.plot(x_grid, pdf, label='bw={}'.format(bw))
ax.legend(loc='best')
plt.show()

谁能帮我把它扩展到多变量/在这种情况下是 3D 数据?

【问题讨论】:

  • 我想知道是否可以提供帮助,但需要了解更多。我可以看到每个数据点将具有三个值,但是按照您编写它的方式,这些三元组被进一步分组为三个一组。您的输入数据被分组两次是有原因的吗?还想仔细检查 Σ 矩阵的含义。我假设你的意思是估计的数据协方差 - 所以你可以使用 Σ^(-1/2) 的经验法则带宽?如果是这样,您打算将其作为开始带宽优化的地方,还是代替优化?
  • 我的回答有帮助吗?如果没有 - 请随意添加一些 cmets,因为我可能会根据您的需要对其进行调整。
  • @JRichardSnape 你是对的,我对数据进行了错误的分组,实际上在我的代码中它就像你实现的一样,但是当复制代码时我搞砸了。是的,我指的是协方差矩阵。
  • 好的。但我仍然不确定我下面的回答是否有帮助 - 这是否让你得到你想要的?或者你的问题还有什么?如果你想输出协方差矩阵,我可以添加。

标签: python numpy machine-learning scikit-learn kernel-density


【解决方案1】:

有趣的问题。您有几个选择:

  1. 继续使用 scikit-learn
  2. 使用不同的库。例如,如果您感兴趣的内核是高斯 - 那么您可以使用scipy.gaussian_kde,这可以说更容易理解/应用。这种技术有一个很好的例子in this question.
  3. 从第一原则开始你自己的。这个难度很大,不推荐

This blog post 详细介绍了内核密度估计 (KDE) 的各种库实现的相对优点。


我将向您展示什么(在我看来 - 是的,这有点基于意见)是最简单的方法,我认为在您的情况下是选项 2。

注意 此方法使用链接文档中描述的经验法则来确定带宽。使用的确切规则是斯科特规则。您提到的 Σ 矩阵让我认为经验法则带宽选择对您来说是可以的,但您也谈到了最佳带宽,并且您提供的示例使用交叉验证来确定最佳带宽。因此,如果此方法不适合您的目的,请在 cmets 中告诉我。

import numpy as np
from scipy import stats
data = np.array([[1, 4, 3], [2, .6, 1.2], [2, 1, 1.2],
         [2, 0.5, 1.4], [5, .5, 0], [0, 0, 0],
         [1, 4, 3], [5, .5, 0], [2, .5, 1.2]])

data = data.T #The KDE takes N vectors of length K for K data points
              #rather than K vectors of length N

kde = stats.gaussian_kde(data)

# You now have your kde!!  Interpreting it / visualising it can be difficult with 3D data
# You might like to try 2D data first - then you can plot the resulting estimated pdf
# as the height in the third dimension, making visualisation easier.

# Here is the basic way to evaluate the estimated pdf on a regular n-dimensional mesh
# Create a regular N-dimensional grid with (arbitrary) 20 points in each dimension
minima = data.T.min(axis=0)
maxima = data.T.max(axis=0)
space = [np.linspace(mini,maxi,20) for mini, maxi in zip(minima,maxima)]
grid = np.meshgrid(*space)

#Turn the grid into N-dimensional coordinates for each point
#Note - coords will get very large as N increases...
coords = np.vstack(map(np.ravel, grid))

#Evaluate the KD estimated pdf at each coordinate
density = kde(coords)

#Do what you like with the density values here..
#plot them, output them, use them elsewhere...

警告

这可能会产生糟糕的结果,具体取决于您的具体问题。要记住的事情显然是:

    1234563事实上你还有更多。
  1. 如正文中所述 - 带宽以特定方式选择 - 这可能会导致估计的 pdf 过度(或可能但不太可能)平滑。

【讨论】:

  • 非常感谢您的帮助。这很有帮助。我还有2个问题希望你能帮助我。 (1) 我如何像在 sklearn.kde (gridcrossover) 中那样使用我自己的带宽 (2) 正如你所说,首先在 2d 中绘制,然后在 3d 中绘制高度,你能否在这里告诉我如何做到这一点? codepad.co/s/ac8623
  • 有时间我会看看这些问题。
  • 对不起,我没有机会看这个。 1)您可以设置自己的带宽:docs.scipy.org/doc/scipy-0.14.0/reference/generated/…我没有使用过这个,示例似乎是针对一维情况的。在可视化方面 - 我建议从 2D 输入数据 开始,而不是 3D。您放在该链接上的代码没有正确的导入等,因此根本无法运行。
  • 嗨,你能帮我从你的代码中显示带宽矩阵吗?我试过 kde.factor 但它给了我浮点数。但是对于多变量情况(3d),它是否应该显示 3x3 带宽矩阵。谢谢
  • 你也需要看看kde.covariancekde.factor 乘以 kde.covariance 得到我认为你想看到的内核协方差矩阵或带宽(我认为你在上面称之为 Σ)。 the docs page底部有详细说明
猜你喜欢
  • 2014-03-22
  • 2013-12-05
  • 1970-01-01
  • 2013-04-15
  • 2015-06-09
  • 2020-04-23
  • 2016-09-18
  • 1970-01-01
  • 2018-09-22
相关资源
最近更新 更多