Python:正值的内核密度估计

时间:2018-09-09 15:20:28

标签: python scipy statistics

我想对正数据点进行内核密度估计。使用Python Scipy Stats程序包,我想到了以下代码。

def get_pdf(data):
    a = np.array(data)
    ag = st.gaussian_kde(a)
    x = np.linspace(0, max(data), max(data))
    y = ag(x)
    return x, y

这对于大多数数据集都非常有效,但是对于“所有正数”数据点却给出了错误的结果。为了确保此方法正确运行,我使用数值积分来计算该曲线下的面积。

def trapezoidal_2(ag, a, b, n):
    h = np.float(b - a) / n
    s = 0.0
    s += ag(a)[0]/2.0
    for i in range(1, n):
        s += ag(a + i*h)[0]
    s += ag(b)[0]/2.0
    return s * h

由于数据分布在区域(0,int(max(data)))中,因此在执行以下行时,我们应该获得接近1的值。

b = 1
data = st.pareto.rvs(b, size=10000)
data = list(data)

a = np.array(data)
ag = st.gaussian_kde(a)
trapezoidal_2(ag, 0, int(max(data)), int(max(data))*2)

但是当我测试时,它给出的值接近0.5。

但是当我从-100积分到max(data)时,它提供的值接近1。

trapezoidal_2(ag, -100, int(max(data)), int(max(data))*2+200)

原因是,即使原始数据集仅包含正值,ag(KDE)也定义为小于0的值。

那么如何获得仅考虑正值的核密度估计,以使区域(o,max(data))中曲线下的面积接近1?

1 个答案:

答案 0 :(得分:1)

执行内核密度估计时,带宽的选择非常重要。我认为,斯科特定律和西尔弗曼定律与高斯相似,在分配方面效果很好。但是,它们不适用于帕累托分布。

引用doc

  

带宽选择强烈影响从   KDE(远远超过内核的实际形状)。带宽选择       可以通过“经验法则”,交叉验证,“插件”来完成       方法”或其他方式;有关评论,请参见[3] ,[4] gaussian_kde       使用经验法则,默认值为斯科特法则。

尝试使用不同的带宽值,例如:

import numpy as np
import matplotlib.pyplot as plt

from scipy import stats

b = 1

sample = stats.pareto.rvs(b, size=3000)
kde_sample_scott = stats.gaussian_kde(sample, bw_method='scott')
kde_sample_scalar = stats.gaussian_kde(sample, bw_method=1e-3)


# Compute the integrale:
print('integrale scott:', kde_sample_scott.integrate_box_1d(0, np.inf))
print('integrale scalar:', kde_sample_scalar.integrate_box_1d(0, np.inf))

# Graph:
x_span = np.logspace(-2, 1, 550)
plt.plot(x_span, stats.pareto.pdf(x_span, b), label='theoretical pdf')
plt.plot(x_span, kde_sample_scott(x_span), label="estimated pdf 'scott'")
plt.plot(x_span, kde_sample_scalar(x_span), label="estimated pdf 'scalar'")
plt.xlabel('X'); plt.legend();

给予:

integrale scott: 0.5572130540733236
integrale scalar: 0.9999999999968957

和:

pareto and kde

我们发现使用Scott方法的kde是错误的。