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

本文涉及的产品
实时计算 Flink 版,1000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 核密度估计(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

目录
相关文章
freeswitch 默认拨号方案(下)
freeswitch默认拨号方案中(conf/dialplan/default.xml)设置了一些基本的测试功能和PBX电话系统功能 包含了分机互拨及简单IVR功能
|
26天前
|
JSON 移动开发 网络协议
Java网络编程:Socket通信与HTTP客户端
本文全面讲解Java网络编程,涵盖TCP与UDP协议区别、Socket编程、HTTP客户端开发及实战案例,助你掌握实时通信、文件传输、聊天应用等场景,附性能优化与面试高频问题解析。
|
26天前
|
存储 弹性计算 容灾
新手小白如何购买阿里云服务器?2025最新图文流程
本文详细介绍阿里云ECS服务器自定义购买全流程,涵盖付费模式、地域、网络、实例规格、镜像、存储、公网IP、带宽、安全组等配置选择,帮助用户全面了解如何根据需求选购阿里云服务器。
142 2
|
26天前
|
机器学习/深度学习 存储 缓存
DNS解析中TTL参数深度解析
本文深度解析DNS解析中的TTL参数,涵盖技术规范、优化策略及工程实践。内容包括TTL定义、分层缓存机制、企业配置建议、变更管理流程、特殊场景应对方案及前沿技术演进,助你全面掌握TTL优化方法。
204 1
|
1月前
|
运维 Dubbo Cloud Native
Dubbo 云原生重构出击:更快部署、更强控制台、更智能运维
Apache Dubbo 最新升级支持云原生,提供一键部署微服务集群与全新可视化控制台,提升全生命周期管理体验,助力企业高效构建云原生应用。
209 25
|
6月前
|
人工智能
「域名+AI」全新体验,等你来玩!
「域名+AI」全新体验,等你来玩!
180 3
「域名+AI」全新体验,等你来玩!
|
26天前
|
XML API 数据安全/隐私保护
API接口使用全指南:从基础调用到实战技巧
API(应用程序编程接口)是软件系统间交互的桥梁,通过标准化的数据格式和调用规则,帮助开发者快速复用功能或数据。本文系统讲解API接口的使用流程、核心技术及实战技巧,涵盖RESTful、SOAP、GraphQL等常见类型,并提供多语言请求示例与错误处理方案,助你掌握现代开发必备技能。