高斯滤波器和高斯核密度估计中sigma与带宽的关系

6 投票
1 回答
4672 浏览
提问于 2025-04-20 17:23

使用 scipy.ndimage.filters.gaussian_filterscipy.stats.gaussian_kde 这两个函数处理一组数据时,如果分别合理选择 sigmabw_method 这两个参数,得到的结果可能会非常相似。

举个例子,我可以通过在 gaussian_filter 中设置 sigma=2.(左边的图)和在 gaussian_kde 中设置 bw_method=sigma/30.(右边的图)来获得一个随机的二维点分布的图像:

enter image description here

(最小可重现示例在问题底部)

这两个参数之间显然有关系,因为一个是对数据应用高斯滤波,另一个是使用高斯核密度估计。

每个参数的定义如下:

sigma:标量或标量序列,高斯核的标准差。高斯滤波器的标准差可以为每个轴提供一个序列,或者作为一个单一的数字,这种情况下所有轴的值是相等的。

这个定义我能理解,因为它涉及到高斯算子的定义:

enter image description here

bw_method:字符串、标量或可调用对象,选填。用于计算估计器带宽的方法。可以是‘scott’、‘silverman’、一个标量常数或一个可调用对象。如果是标量,这将直接用作 kde.factor。如果是可调用对象,它应该接受一个 gaussian_kde 实例作为唯一参数并返回一个标量。如果为 None(默认值),则使用‘scott’。更多细节请查看说明。

在这种情况下,假设 bw_method 的输入是一个标量(浮点数),以便与 sigma 进行比较。这里我就有点迷糊了,因为我找不到关于这个 kde.factor 参数的任何信息。

我想知道的是,如果可能的话,连接这两个参数(即:当使用浮点数时的 sigmabw_method)的 精确数学公式


最小可重现示例:

import numpy as np
from scipy.stats import gaussian_kde
from scipy.ndimage.filters import gaussian_filter
import matplotlib.pyplot as plt

def rand_data():
    return np.random.uniform(low=1., high=200., size=(1000,))

# Generate 2D data.
x_data, y_data = rand_data(), rand_data()
xmin, xmax = min(x_data), max(x_data)
ymin, ymax = min(y_data), max(y_data)

# Define grid density.
gd = 100
# Define bandwidth
bw = 2.

# Using gaussian_filter
# Obtain 2D histogram.
rang = [[xmin, xmax], [ymin, ymax]]
binsxy = [gd, gd]
hist1, xedges, yedges = np.histogram2d(x_data, y_data, range=rang, bins=binsxy)
# Gaussian filtered histogram.
h_g = gaussian_filter(hist1, bw)

# Using gaussian_kde
values = np.vstack([x_data, y_data])
# Data 2D kernel density estimate.
kernel = gaussian_kde(values, bw_method=bw / 30.)
# Define x,y grid.
gd_c = complex(0, gd)
x, y = np.mgrid[xmin:xmax:gd_c, ymin:ymax:gd_c]
positions = np.vstack([x.ravel(), y.ravel()])
# Evaluate KDE.
z = kernel(positions)
# Re-shape for plotting
z = z.reshape(gd, gd)

# Make plots.
fig, (ax1, ax2) = plt.subplots(1, 2)
# Gaussian filtered 2D histograms.
ax1.imshow(h_g.transpose(), origin='lower')
ax2.imshow(z.transpose(), origin='lower')

plt.show()

1 个回答

3

这两者之间没有关系,因为你在做两件不同的事情。

使用scipy.ndimage.filters.gaussian_filter时,你是在用一个叫做高斯的滤波器对一个二维变量(比如一张图片)进行处理,实际上就是在对这张图片进行平滑处理。

而使用scipy.stats.gaussian_kde时,你是在尝试估计你的二维变量的概率密度函数。这里的带宽(或者说平滑参数)就是你的积分步长,应该尽量小,直到数据允许的范围。

这两张图片看起来相似,是因为你抽样的均匀分布和正态分布差别不大。显然,使用正态核函数会得到更好的估计。

你可以了解一下核密度估计

编辑: 在核密度估计(KDE)中,核的大小是经过调整的,使得带宽等于平滑核的标准差。选择哪个带宽并不明显,因为这取决于数据。对于单变量数据,有一个叫做Silverman法则的最佳选择。

总的来说,高斯滤波器的标准差和KDE的带宽之间没有关系,因为我们在讨论的是不同的东西。不过,如果只讨论KDE,那么KDE的带宽和同一个KDE核的标准差之间是有关系的,它们是相等的!实际上,具体的实现细节可能不同,可能会有一个与核的大小相关的缩放。你可以查看你使用的具体包的gaussian_kde.py。

撰写回答