获取SciPy的gaussian_kde函数使用的带宽

时间:2014-05-13 11:52:41

标签: python kernel scipy bandwidth

我正在使用SciPy的stats.gaussian_kde函数从x,y点的数据集生成核密度估计(kde)函数。

这是我的代码的简单MWE:

import numpy as np
from scipy import stats

def random_data(N):
    # Generate some random data.
    return np.random.uniform(0., 10., N)

# Data lists.
x_data = random_data(100)
y_data = random_data(100)

# Obtain the gaussian kernel.
kernel = stats.gaussian_kde(np.vstack([x_data, y_data]))

由于我没有手动设置带宽(通过bw_method键),因此该功能默认使用Scott的规则(参见函数说明)。我需要的是获得stats.gaussian_kde函数自动设置的带宽值。

我尝试过使用:

print kernel.set_bandwidth()

但它始终返回None而不是浮动。

3 个答案:

答案 0 :(得分:3)

简短回答

带宽为kernel.covariance_factor() 乘以您正在使用的样本的标准。

(这是1D样本的情况,在默认情况下使用Scott的经验法则计算。)

示例:

from scipy.stats import gaussian_kde
sample = np.random.normal(0., 2., 100)
kde = gaussian_kde(sample)
f = kde.covariance_factor()
bw = f * sample.std()

你得到的PDF是:

from pylab import plot
x_grid = np.linspace(-6, 6, 200)
plot(x_grid, kde.evaluate(x_grid))

enter image description here

你可以这样检查,如果你使用一个新函数来创建一个kde,比如sklearn:

from sklearn.neighbors import KernelDensity
def kde_sklearn(x, x_grid, bandwidth):
    kde_skl = KernelDensity(bandwidth=bandwidth)
    kde_skl.fit(x[:, np.newaxis])
    # score_samples() returns the log-likelihood of the samples
    log_pdf = kde_skl.score_samples(x_grid[:, np.newaxis])
    pdf = np.exp(log_pdf)
    return pdf

现在使用上面相同的代码,你得到:

plot(x_grid, kde_sklearn(sample, x_grid, f))

enter image description here

plot(x_grid, kde_sklearn(sample, x_grid, bw))

enter image description here

答案 1 :(得分:1)

我已经知道了,这句话是:

kernel.covariance_factor()

来自scipy.stats.gaussian_kde.covariance_factor

  

计算乘以数据协方差矩阵的系数(kde.factor)以获得核协方差矩阵。默认值为scotts_factor。子类可以覆盖此方法以提供不同的方法,或通过调用kde.set_bandwidth来设置它。

可以检查使用此带宽值的结果内核是否等于使用默认带宽生成的内核。为此,请使用covariance_factor()给出的带宽获取新内核,并将其随机点的值与原始内核进行比较:

kernel = stats.gaussian_kde(np.vstack([x_data, y_data]))
print kernel([0.5, 1.3])

bw = kernel.covariance_factor()    
kernel2 = stats.gaussian_kde(np.vstack([x_data, y_data]), bw_method=bw)
print kernel2([0.5, 1.3])

答案 2 :(得分:0)

我遇到了这个老问题,因为我还想知道Scipy的gaussian_kde使用的带宽是多少。我想添加/修改先前的答案,即协方差因子在来自Scipy的kde.py代码中用作:         self.covariance = self._data_covariance * self.factor ** 2

因此,完整的内核协方差是样本协方差乘以所谓的协方差因子(斯科特因子)的平方,可以通过kde.factor或kde.covariance_factor()检索。