我尝试使用内核密度估算器(KDE)制作过滤器(去除异常值和噪声)。我在我的3D(d = 3)数据点中应用了KDE,这给了我概率密度函数(PDF)f(x)。现在我们知道密度估计的局部最大值f(x)定义了数据点簇的中心。所以我的想法是定义适当的f(x)来确定那些簇。
我的问题是如何以及什么方法更适合于在f(x)中找到局部最大值的目的。如果有人能提供一些示例代码/想法,我将非常感激。
以下是查找在3D数据中给出f(x)的KDE的代码。
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
kde = stats.gaussian_kde(data)
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)
coords = np.vstack(map(np.ravel, grid))
#Evaluate the KD estimated pdf at each coordinate
density = kde(coords)
答案 0 :(得分:3)
您将需要使用名为Mean Shift的算法。它是一种聚类算法,通过查找KDE的模式(也就是f(x)的最大值)来工作。请注意,为KDE设置的带宽将影响模式的数量及其位置。由于您使用的是python,因此scikit-learn中有一个实现。
答案 1 :(得分:1)
这是一个简短的函数,它演示了如何估算最大值。注意: no_samples 的数量越多,最大值的精度越高。
from scipy.stats import gaussian_kde
import numpy as np
def estimate_maxima(data):
kde = gaussian_kde(data)
no_samples = 10
samples = np.linspace(0, 10, no_samples)
probs = kde.evaluate(samples)
maxima_index = probs.argmax()
maxima = samples[maxima_index]
return maxima
答案 2 :(得分:0)
您可以使用 scipy.optimize。
一维数据示例:
import numpy as np
from scipy import optimize
from scipy import stats
# Generate some random data
shape, loc, scale = .5, 3, 10
n = 1000
data = np.sort(stats.lognorm.rvs(shape, loc, scale, size=n))
kernel = stats.gaussian_kde(data)
# Minimize the negative instead of maximizing
# Depending on the shape of your data, you might want to set some bounds
opt = optimize.minimize_scalar(lambda x: -kernel(x))
opt
fun: array([-0.08363781])
nfev: 21
nit: 14
success: True
x: array([10.77361776])
这个分布的实际模式是
mode = scale/np.exp(shape**2) + loc
mode
10.788007830714049
绘制结果:
import matplotlib.pyplot as plt
data_es = np.linspace(0, data.max(), 201) # x-axis points
ecdf = (np.arange(n) + 1)/n # empirical CDF
fig, axes = plt.subplots(2, 1, sharex=True, dpi=300, figsize=(6,7))
axes[0].hist(x, bins=30, density=True, alpha=.5, rwidth=.9) # histogram
axes[0].plot(data_es, kernel.pdf(data_es), 'C0') # estimated PDF
axes[0].plot(data_es, stats.lognorm.pdf(data_es, shape, loc, scale), 'k--', alpha=.5) # true PDF
axes[0].plot(opt.x, kernel.pdf(opt.x), 'C0.') # estimated mode
axes[0].plot(mode, stats.lognorm.pdf(mode, shape, loc, scale), 'k.', alpha=.5) # true mode
axes[1].plot(np.sort(data), ecdf) # estimated CDF
axes[1].plot(opt.x, np.interp(opt.x, np.sort(data), ecdf), 'C0.') #estimated mode
axes[1].plot(data_es, stats.lognorm.cdf(data_es, shape, loc, scale), 'k--', alpha=.5) # true CDF
axes[1].plot(mode, stats.lognorm.cdf(mode, shape, loc, scale), 'k.', alpha=.5) # true mode
fig.tight_layout()
如您所见,估计模式非常适合。我认为它可以使用 scipy.optimize 中的其他方法扩展到多变量数据。