python - 周期数据的核密度估计

标签 python scikit-learn kernel-density

是否有可能在 sklearn 或不同的 Python 包中获取用于周期性 数据的 KDE?

这是一个简化的示例:我正在从两个正态分布创建模型数据集并将其映射到 0 到 20 的区间。

import numpy as np
import matplotlib.pyplot as plt

# create dataset
data = np.hstack((np.random.normal(8, 2, 200), np.random.normal(19, 4, 200))) % 20

当我绘制 KDE 的结果时

# fit
from sklearn.neighbors import KernelDensity
kde = KernelDensity(bandwidth=1, kernel='gaussian')
kde.fit(data[:, None])

# plot
x_d = np.linspace(0, 20, 100)
logprob = kde.score_samples(x_d[:, None])
plt.fill_between(x_d, np.exp(logprob), alpha=0.5)
plt.hist(data, histtype = "step", density = True)
plt.ion()
plt.show()

它(显然)不知道数据的周期性:

KDE result

正如您从估计中看到的那样具有三个峰值并且在边界处不平滑。

最佳答案

我自己一直在寻找这个,虽然找到一个直接/简单地支持它的包似乎出奇地困难......同时我不得不想出一个解决方法......它有点痛苦但它有效.

由于您处于一维周期域(从 0 到 20),一种解决方案是将数据映射到更高维度的二维圆形流形。例如。每个数据点从 0-20 映射到 0-2pi,然后映射到单位圆,如 x2d = cos(x_r), sin(x_r)。那时你可以运行 kde 以获得更高维度空间中的密度,然后对流形进行采样并归一化为概率/密度

最后一点,如果您想将其应用于纬度/经度数据,您的流形将改为单位球体,因此您需要进行相应的转换。

scaleFactor=2*np.pi/20. #need to rescale from 0-20 to 0-2pi
data2d=np.array(
    [
        np.cos(data*scaleFactor),
        np.sin(data*scaleFactor)
    ]
).T

#also need to scale the bandwidth appropriately (if you have one picked)
kde2d = KernelDensity(bandwidth=1*scaleFactor, kernel='gaussian')
kde2d.fit(data2d)

x_d=np.linspace(0,20,100)
x_2d=np.array(
    [
        np.cos(x_d*scaleFactor),
        np.sin(x_d*scaleFactor)
    ]
).T

logprob2d = kde2d.score_samples(x_2d)
prob2d=np.exp(logprob2d)
prob2d=prob2d/np.sum(prob2d)
densFactor=len(prob2d)/20. #convert from probability to density
dens2d=prob2d*densFactor
plt.fill_between(
    x_d, 
    dens2d,
    alpha=0.5)
plt.hist(data, histtype = "step", density = True)
plt.ion()
plt.show()

#verify that prob2d is now periodic
print(prob2d[0],prob2d[-1])

还有另一种选择...创建数据的移位副本并附加它们(例如在“中央单元格”周围添加周期性图像)...但这可能非常耗费内存和时间。在更高的维度中,您最终需要 (3^N)-1 个副本。这也将使缩放成为一个严重的问题,因为许多 KDE 方法在某个点后开始相对于样本大小进行非线性缩放。

关于python - 周期数据的核密度估计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65060491/

相关文章:

python - 如何使用 SciKit Learn 转换一次编码多个特征

python - 无法在 scikit-learn 中导入 sklearn.model_selection

javascript - 如何使用 D3.js 实现 R 核密度估计图?

r - 叠加密度图不包括直方图值

python - GAE Python 获取默认存储桶 fxn 返回 None

python - Django : What kind of querysets should i look for when deciding on model indexes?

python - Pandas 数据帧上的滞后数据

python - `python` 中的加权高斯核密度估计

python - Matplotlib:将不同的线组合成一个可以多次绘制的对象

python - 如何随机洗牌排列比 PRNG 周期更多的列表?