数据分布平滑化技术:核密度估计KDE解决直方图不连续问题

简介: 核密度估计(KDE)通过平滑处理解决直方图密度估计中的不连续问题,提供连续密度函数。其核心在于使用核函数对数据点进行加权,避免区间划分带来的信息丢失。带宽参数h影响估计效果,过小导致波动大,过大则过度平滑。常用核函数包括高斯核与Epanechnikov核,实际应用中可借助Statsmodels或Seaborn库快速实现。

直方图密度函数在密度函数估计中存在不连续性问题,即密度值在相邻区间边界处发生突变。为获得随机变量的连续密度函数估计,核密度估计(Kernel Density Estimation, KDE)提供了有效的解决方案。

核函数

核函数本质上是密度估计中用于平滑处理的概率密度函数,通常选择对称核函数。核函数必须满足以下基本性质:非负性、曲线下面积为1、以零为中心、具有非零方差。这些约束条件保证了核函数作为概率密度函数的有效性。

核函数的核心思想在于解决直方图估计的固有缺陷。在传统直方图中,诸如[1, 3)和[3, 5)的离散区间会导致2到3之间数据点信息的丢失,产生块状且不连续的估计结果。核密度估计通过在每个数据点上放置平滑曲线(如高斯核函数K(u))来替代固定区间,曲线峰值位于数据点位置,其扩散范围覆盖数据间隙。

点x处的密度估计需要计算x与各数据点的距离(以带宽h为度量单位),然后将这些标准化距离输入核函数。距离较近的点产生较高的核函数值,距离较远的点贡献相对较小。KDE的数学表达式为:

通过单个数据点示例来解析K(x — Xi / h)的工作机制。假设K(u)为高斯核函数:

针对直方图密度估计中使用的

waiting_times

数据,单个数据点的核函数表现如下:

 waiting_times = np.sort(waiting_times)  

K = lambda u: (2 * np.pi) ** (-0.5) * np.exp(-0.5 * u ** 2)  

plt.figure(figsize=(10, 6))  
plt.ylim(0, 0.001)  
plt.scatter(waiting_times, np.zeros_like(waiting_times), color='red', zorder=15)  

for X in np.random.choice(waiting_times, size=1, replace=False):  
    kernel = [(1/h) * K((x - X) / h) / len(waiting_times) for x in waiting_times]  
    # we will talk about h in a bit  
    plt.plot(waiting_times, kernel, color="#2C5B03")  
     plt.axvline(x=X, ymin=0, color='#D08770', linestyle='-', alpha=1, linewidth=1)


当X = 75时,计算远距离点x = 50的密度贡献值会显著降低。由于高斯分布的特性,该贡献值不为零但极小,可视为可忽略的贡献量。带宽参数h的大小直接影响估计质量:

当h较小时,u值增大,将u输入核函数K(u)后,对于Xi = 75的核函数,x = 50位置的贡献变得极其微小。带宽选择是KDE成功应用的关键因素。过小的h值使每个核函数过于狭窄,导致密度估计出现过度波动和噪声,捕获随机扰动而非真实分布形状;过大的h值使核函数过于宽泛,造成过度平滑而丢失数据中的重要细节。合适的h值需要在噪声抑制和细节保留之间达到最优平衡。

Silverman经验法则

Silverman经验法则为带宽选择提供了实用的起始估计。该方法利用样本标准差σ和样本容量n计算初始带宽值。虽然并非对所有数据集都是最优选择,但在多数情况下能够有效平衡偏差和方差,因此常作为精细调优前的默认选择。

 waiting_times = np.sort(waiting_times)  

K = lambda u: (2 * np.pi) ** (-0.5) * np.exp(-0.5 * u ** 2)  

sigma = np.std(waiting_times)  
n = len(waiting_times)  
h = 1.06 * sigma * n**(-1/5)  

plt.figure(figsize=(10, 6))  
plt.ylim(0, 0.001)  
plt.scatter(waiting_times, np.zeros_like(waiting_times), color='red', zorder=15)  

for X in waiting_times:  
    kernel = [(1/h) * K((x - X) / h) / len(waiting_times) for x in waiting_times]  
    plt.plot(waiting_times, kernel, color="#2C5B03")  
    plt.axvline(x=X, ymin=0, color='#D08770', linestyle='-', alpha=1, linewidth=1)  

plt.savefig("kernel_densities.png", dpi=300)  
plt.tight_layout()  
 plt.show()

分析结果表明,样本数据均值x̄附近区域具有较高的密度值,这是因为该区域聚集了多个高核密度贡献;而远离数据点集中区域的位置(如数值10附近)则表现出较低的密度值,因为其仅接收到较低的核密度贡献。

KDE公式中距离尺度变换为h后,各核函数的面积从单位面积变为h。为恢复单位面积特性,需要将每个核函数除以h。随后对n个单位面积求和得到总面积n,通过除以n进行归一化处理,最终得到:

 waiting_times = np.sort(waiting_times)  

K = lambda u: (2 * np.pi) ** (-0.5) * np.exp(-0.5 * u ** 2)  

sigma = np.std(waiting_times)  
n = len(waiting_times)  
h = 1.06 * sigma * n**(-1/5)  

def f(x, h):  
    kernel_values = [(1/h) * K((x - X) / h) for X in waiting_times]  
    return np.sum(kernel_values) / len(waiting_times)  

pdf = [f(x, h) for x in waiting_times]  

plt.figure(figsize=(10, 6))  
plt.plot(waiting_times, pdf, color='#E15759', linewidth=2, label='Kernel Density Estimate')  
plt.xlabel("Waiting Time (minutes)", fontsize=14)  
plt.ylabel("Density", fontsize=14)  
plt.title("Kernel Density Estimation of Waiting Times", fontsize=16, pad=15)  
plt.legend()  
plt.tight_layout()  
plt.savefig("kde_plot.png", dpi=300)  
 plt.show()

高斯核函数虽为最常用选择,但并非唯一方案。Epanechnikov核函数对邻近x的数据点赋予更高权重,同时完全忽略距离过远的点,即在特定范围外其贡献降为零。这种特性使其在计算上更为高效,因为远距离数据点不会影响x处的密度计算。Epanechnikov核函数的表达式为:

观察可见,当距离Xi超过单位距离时,贡献值降为零。

均匀核函数

均匀核函数是另一种选择方案。在该核函数中,带宽窗口内的所有点均等贡献,窗口外的点不产生贡献。实际上,使用均匀核函数的核密度估计等价于直方图密度估计器(HDE)的平滑化版本。

实际应用中无需手动实现KDE算法,现有软件库已提供完整实现。Statsmodels库的实现与手工编码逻辑一致,但密度曲线更为平滑,因为其在精细网格点上评估函数而非仅在样本值处计算。Seaborn的

kdeplot

函数默认使用高斯核函数并自动选择带宽参数,仅需一行代码即可生成平滑的密度曲线。

 from statsmodels.nonparametric.kde import KDEUnivariate  
import seaborn as sns  

kde = KDEUnivariate(waiting_times)  
kde.fit(kernel="gau") # gau = gaussian kernel, epa = epanechnikov kernel, uni = uniform kernel  

plt.figure(figsize=(10, 6))  
plt.plot(kde.support, kde.density, color='#E15759', label='Gaussian Kernel (Statsmodels)')  
sns.kdeplot(waiting_times, color='#4C78A8', label='Gaussian Kernel (Seaborn)')  
plt.xlabel("Waiting Time (minutes)", fontsize=14)  
plt.ylabel("Density", fontsize=14)  
plt.title("Different Kernels for KDE", fontsize=16, pad=15)  
plt.legend()  
plt.tight_layout()  
plt.savefig("kde.png", dpi=300)  
 plt.show()

总结

直方图提供了分布的粗略概念,但存在跳跃性和块状特征。核密度估计通过在数据点上放置平滑曲线并求和的方式解决了这一问题,提供了密度的连续视图。核函数形状在实践中的影响有限,但带宽参数h至关重要,它决定了曲线是否过于嘈杂或过于平滑。Statsmodels和Seaborn等库提供的一行代码实现使得手动编程变得不再必要,但理解其底层机制对于正确应用和参数调优仍然重要。

https://avoid.overfit.cn/post/deb03b1a58884b478d19c8f5b6507f93

作者:Mohith

目录
相关文章
|
机器学习/深度学习 数据采集 编解码
深度学习之实时医学影像增强
基于深度学习的实时医学影像增强是一种将先进的深度学习技术应用于医学影像处理的创新方法,旨在通过高效的图像增强算法帮助医生更准确地诊断和治疗患者。
629 2
|
机器学习/深度学习 资源调度 算法
【机器学习基础】多元线性回归(适合初学者的保姆级文章)
【机器学习基础】多元线性回归(适合初学者的保姆级文章)
1453 0
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习】聚类算法任务,评价指标SC、DBI、ZQ等系数详解和实战演示(附源码 图文解释)
【Python机器学习】聚类算法任务,评价指标SC、DBI、ZQ等系数详解和实战演示(附源码 图文解释)
1800 0
|
机器学习/深度学习 边缘计算 算法
【无人机】无人机群在三维环境中的碰撞和静态避障仿真(Matlab代码实现)
【无人机】无人机群在三维环境中的碰撞和静态避障仿真(Matlab代码实现)
529 0
|
机器学习/深度学习
 GHSL: 全球1975 年到 2030 年以 5 年间隔建成面积的分布情况(100m)
全球人类住区图层(GHSL)项目提供了1975年至2030年建成面积的分布数据,以每100米网格单元为单位,涵盖建筑总面积及非住宅用途面积。该数据集由欧盟委员会联合研究中心(EC JRC)提供,时间间隔为5年,支持时空分析与预测。详情参见[GHSL 数据包 2023](https://ghsl.jrc.ec.europa.eu/documents/GHSL_Data_Package_2023.pdf?t=1683540422)。
868 7
|
机器学习/深度学习 机器人
《解密奖励函数:引导智能体走向最优策略》
在强化学习中,奖励函数是核心要素,指导智能体学习与决策。它通过明确目标、合理分配奖励和考虑环境因素,激励智能体探索最优策略。设计恰当的奖励函数能让智能体在复杂环境中不断优化行为,实现长期目标。即时、延迟和全局奖励的不同类型,以及奖励函数的稳定性和适应性,都是设计时需关注的重点。
805 13
|
机器学习/深度学习 资源调度 自动驾驶
OFDM:赋能5G通信的基石
OFDM:赋能5G通信的基石
1920 3
|
物联网 Java 测试技术
蓝桥杯-01简介
蓝桥杯-01简介
|
数据挖掘 Python
利用Python进行数据分析PDF下载经典数据分享推荐
**Python数据分析大师作,Wes McKinney亲著,详述数据操作、清洗与分析。第2版面向Python 3.6,涵盖pandas、NumPy、IPython和Jupyter更新,实战案例丰富;第3版已升级至Python 3.10和pandas 1.4,继续引领数据科学潮流。[PDF下载](https://zhangfeidezhu.com/?p=337)**
1088 0
利用Python进行数据分析PDF下载经典数据分享推荐

热门文章

最新文章