直方图与核密度估计

技术背景

直方图是一种经常被用于统计的图形表达形式,简单来说它的功能就是用一系列的样本数据,去分析样本的分布规律。而直方图跟核密度估计(Kernel Density Estimation,KDE)方法的主要差别在于,直方图得到的是一个离散化的统计分布,而KDE方法得到的是一个连续的概率分布函数。如果将得到的分布重新用于采样,两者都可以结合蒙特卡洛方法实现这样的功能,但是KDE的优点在于它得到的结果是可微分的,那么就可以应用于有偏估计的分子动力学模拟中,如元动力学(Meta Dynamics)方法。这里主要用Python实现一个简单的KDE函数的功能,也顺带介绍一下Numpy和Matplotlib中关于直方图的使用方法。

制备样本

在使用直方图和KDE前,我们需要先制备一些样本,这里可以使用Numpy生成一些随机数,便于测试,例如均匀随机数,其概率密度为:

\[f(x)=\left\{ \begin{matrix} \frac{1}{b-a}, a<x<b\\ 0, others \end{matrix} \right. \]

对应的numpy生成方法为:

data = np.random.uniform(-3, 3, (10000, ))

这个分布表示在-3到3的范围内进行均匀随机采样,采10000个样本点。还可以使用高斯分布,其概率密度为:

\[f(x)=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}} \]

对应的numpy生成方法为:

data = np.random.normal(0, 1, (10000, ))

这个采样表示从\(\mu=0, \sigma=1\)的条件下对高斯函数进行采10000个样本点,也就是正态分布。还有一种比较常见的指数分布:

\[f(x)=ax^{a-1},0\le x\le 1,a>0 \]

对应的numpy的采样方法为:

data = np.random.power(5, 10000)

这里配置参数\(a=5\),采10000个样本点。这种采样方法,随着\(x\)的增长,概率密度会越来越大。

核密度估计函数

首先我们可以给出核密度估计函数的形式:

\[f(x)=\frac{\sum_{t=1}^M\omega_tK(x-x_t,\sigma)}{\sum_{t=1}^M\omega_t} \]

其中\(K(x-x_t,\sigma)\)表示一个带宽为\(\sigma\)的核函数,比如这里我们可以选用前面提到的高斯函数(或者简化为正态分布),用其他的函数作为波包也是可以的。值得注意的是,这里的带宽\(\sigma\)可以理解为波包宽度的设定。从高斯函数的表达形式也可以看出来,当\(x=\mu\)\(f(x)\)取得最大值\(f_{max}=\frac{1}{\sqrt{2\pi}\sigma}\)\(\sigma\)的值越大,\(f_{max}\)的值就越小,那么波包的辐射范围就会越广,也就是所谓的带宽越大。

按照KDE的这种算法,假定我们用高斯函数为核函数,那么理论上应该用一个for循环来实现:

for t in range(0, M):for index in range(0, len(grids)):grids[index] += omega[t] * gaussian(x[index] - xt, sigma)

但是因为在Numpy中支持了自动广播的机制,因此我们只需要一行代码就可以完成整个for循环里面的计算:

grids = gaussian(z[None] - x[:, None], sigma=sigma).sum(axis=0)

完整示例

我们可以先用一个小样本示例,看一下核密度估计函数到底在做什么:

import numpy as np
import matplotlib.pyplot as pltdef gaussian(x, mu=0, sigma=1):“”“高斯波包函数“””return np.exp(-(x-mu)**2/2/sigma**2)/np.sqrt(2*np.pi)/sigmadef kde(x, grid_min, grid_max, bins, sigma):“”“带归一化的核密度估计函数”“”grid_size = (grid_max - grid_min) / binsz = grid_size*np.arange(bins) + grid_min + grid_size/2res = gaussian(z[None]-x[:, None], sigma=sigma).sum(axis=0) / x.shape[-1]res /= res.sum()*grid_sizereturn res, zplt.figure(figsize=(10, 9))
plt.title('Kernel Density Estimation')
# 正态分布采样
data = np.random.normal(0, 1, (3, ))
# Numpy生成的直方图参数
hist, bin_edges = np.histogram(data, bins=20, normed=True)
subplot1 = plt.subplot2grid((4, 3), (0, 0))
subplot1.set_title("Matplotlib Hist")
subplot1.set_ylabel("Normal Distribution")
# Matplotlib自带的直方图
subplot1.hist(data, bins=20, rwidth=0.9, color='black', density=True)
subplot2 = plt.subplot2grid((4, 3), (0, 1))
subplot2.set_title("Numpy Histogram")
subplot2.bar(bin_edges[:-1], hist, width=0.15, color='green', align='center')
subplot3 = plt.subplot2grid((4, 3), (0, 2))
subplot3.set_title("KDE Function")
# 三种不同带宽的核密度估计函数
k, z = kde(data, -3, 3, 30, 0.2)
subplot3.plot(z, k, color='orange', label=r'$\sigma$=0.2')
k, z = kde(data, -3, 3, 30, 0.6)
subplot3.plot(z, k, color='purple', label=r'$\sigma$=0.6')
k, z = kde(data, -3, 3, 30, 1.0)
subplot3.plot(z, k, color='red', label=r'$\sigma$=1.0')
subplot3.legend()
# 有偏置的正态分布
data = np.random.normal(0, 1, (3, )) + 1
hist, bin_edges = np.histogram(data, bins=20, normed=True)
subplot1 = plt.subplot2grid((4, 3), (1, 0))
subplot1.set_ylabel("Bias Normal Distribution")
subplot1.hist(data, bins=20, rwidth=0.9, color='black', density=True)
subplot2 = plt.subplot2grid((4, 3), (1, 1))
subplot2.bar(bin_edges[:-1], hist, width=0.15, color='green', align='center')
subplot3 = plt.subplot2grid((4, 3), (1, 2))
k, z = kde(data, -3, 3, 30, 0.2)
subplot3.plot(z, k, color='orange', label=r'$\sigma$=0.2')
k, z = kde(data, -3, 3, 30, 0.6)
subplot3.plot(z, k, color='purple', label=r'$\sigma$=0.6')
k, z = kde(data, -3, 3, 30, 1.0)
subplot3.plot(z, k, color='red', label=r'$\sigma$=1.0')
subplot3.legend()
# 指数分布
data = np.random.power(5, 3)*7-4
hist, bin_edges = np.histogram(data, bins=20, normed=True)
subplot1 = plt.subplot2grid((4, 3), (2, 0))
subplot1.set_ylabel("Exponential Distribution")
subplot1.hist(data, bins=20, rwidth=0.9, color='black', density=True)
subplot2 = plt.subplot2grid((4, 3), (2, 1))
subplot2.bar(bin_edges[:-1], hist, width=0.15, color='green', align='center')
subplot3 = plt.subplot2grid((4, 3), (2, 2))
k, z = kde(data, -3, 3, 30, 0.2)
subplot3.plot(z, k, color='orange', label=r'$\sigma$=0.2')
k, z = kde(data, -3, 3, 30, 0.6)
subplot3.plot(z, k, color='purple', label=r'$\sigma$=0.6')
k, z = kde(data, -3, 3, 30, 1.0)
subplot3.plot(z, k, color='red', label=r'$\sigma$=1.0')
subplot3.legend()
# 均匀分布
data = np.random.uniform(-3, 3, (3, ))
hist, bin_edges = np.histogram(data, bins=20, normed=True)
subplot1 = plt.subplot2grid((4, 3), (3, 0))
subplot1.set_ylabel("Uniform Distribution")
subplot1.hist(data, bins=20, rwidth=0.9, color='black', density=True)
subplot2 = plt.subplot2grid((4, 3), (3, 1))
subplot2.bar(bin_edges[:-1], hist, width=0.15, color='green', align='center')
subplot3 = plt.subplot2grid((4, 3), (3, 2))
k, z = kde(data, -3, 3, 30, 0.2)
subplot3.plot(z, k, color='orange', label=r'$\sigma$=0.2')
k, z = kde(data, -3, 3, 30, 0.6)
subplot3.plot(z, k, color='purple', label=r'$\sigma$=0.6')
k, z = kde(data, -3, 3, 30, 1.0)
subplot3.plot(z, k, color='red', label=r'$\sigma$=1.0')
subplot3.legend()
# 画图
plt.show()

得到的结果如下图所示:

在这个结果中我们看到,因为采样比较稀疏,直方图只会显示被采到的那个格点,而核密度估计函数则是以波包的形式,将采样概率密度辐射到整个的采样空间上,这就实现了一个连续化。如果把采样密度调大一点,比如我们调整为采样10000次,那么得到的结果是这样的:

这也表明,只有足够多的样本数量,才能够相对准确的复原出采样的分布函数,而且这跟边界条件的连续性有比较大的关系。

总结概要

核密度估计(KDE)方法,相当于用多个波包的组合形式来近似一个真实的概率密度,以获得一个连续可微分的概率密度函数。本文通过一些简单的概率分布的示例,演示了一下KDE的使用方法。其实KDE的思想在很多领域都会以不同的形式出现,是一个比较基础的概率分布近似手段。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/kde.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/825231.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【全开源】多功能完美运营版商城 虚拟商品全功能商城 全能商城小程序 智慧商城系统 全品类百货商城

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 完美运营版商城/拼团/团购/秒杀/积分/砍价/实物商品/虚拟商品等全功能商城 干干净净 没有一丝多余收据 还没过手其他站 还没乱七八走的广告和后门 后台可以自由拖曳修改前端UI页面 …

Aigtek功率放大器的使用方法有哪些

功率放大器是一种将小信号放大为大信号的电子设备&#xff0c;广泛应用于无线通信、音频系统、雷达等领域。在使用功率放大器时&#xff0c;需要注意以下几个方面&#xff1a; 电源供应&#xff1a;功率放大器需要提供稳定的电源供应以保证正常工作。通常情况下&#xff0c;功率…

正式发布的Spring AI,能让Java喝上AI赛道的汤吗

作者:鱼仔 博客首页: https://codeease.top 公众号:Java鱼仔 前言 最近几年AI发展实在太快了&#xff0c;仿佛只要半年没关注&#xff0c;一个新的大模型所产生的效果就能超越你的想象。Java在AI这条路上一直没什么好的发展&#xff0c;不过Spring最近出来了一个新的模块叫做S…

[Linux][进程间通信][一][匿名管道][命名管道]详细解读

目录 0.进程间通信&#xff1f;1.进程间通信目的2.进程间通信分类3.进程间通信的本质理解 1.什么是管道&#xff1f;2.匿名管道1.认识函数2.如何让不同的进程&#xff0c;看到同一份资源&#xff1f;3.用fork来共享管道原理4.站在文件描述符角度 -- 深刻理解管道5.站在内核角度…

目标检测——食品饮料数据集

一、重要性及意义 对食品和饮料进行目标检测的重要性和意义体现在多个方面&#xff1a; 商业应用与市场分析&#xff1a;目标检测技术在食品和饮料行业有着广泛的应用前景。通过对超市货架、餐馆菜单或广告海报中的食品和饮料进行自动识别和计数&#xff0c;商家可以获取关于产…

【微服务】spring状态机模式使用详解

一、前言 在很多系统中,通常会涉及到某个业务需要进行各种状态的切换操作,例如在审批流程场景下,某个审批的向下流转需要依赖于上一个状态的结束,再比如电商购物场景中,一个订单的生命周期往往伴随着不同的状态,比如待支付,支付完成,已发货等等,状态的存在,让一个业…

登录解析(后端)

调试登录接口 进入实现类可以有 验证码校验 登录前置校验 用户验证 验证码校验 通过uuid获取redis 中存储的验证码信息&#xff0c;获取后对用户填写的验证码数据进行校验比对 用户验证 1.进入控制器的 /login 方法 2.进入security账号鉴权功能&#xff0c;经过jar内的流…

HTML:Form表单控件主要标签及属性。name属性,value属性,id属性详解。表单内容的传递流程,get和post数据传递样式。表单数据传递实例

form表单 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…

c语言中什么是冒泡排序,冒泡排序的计算

在c语言中&#xff0c;冒泡排序的解释是&#xff0c;将被排序的记录数组arr[1..n]垂直排列&#xff0c;每个记录arr看作是重量为一个arr气泡。根据轻气泡不能在重气泡之下的原则&#xff0c;从下往上扫描数组arr&#xff0c;凡扫描到违反该原则的轻气泡&#xff0c;就使其向上飘…

算法练习第19天|222.完全二叉树的节点个数

222.完全二叉树的节点个数 222. 完全二叉树的节点个数 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/count-complete-tree-nodes/description/ 题目描述&#xff1a; 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。题目数据保…

振动信号幅值成分分析手段

提示&#xff1a;振动信号幅值成分分析手段 文章目录 一、特征值分析二、概率密度分析2.1、原理2.2、代码2.3、结果分析 三、总结&#xff08;自己的思想&#xff09; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、特征值分析 均值和平均幅值可以…

【缓存常见问题】

在使用缓存时特别是在高并发场景下会遇到很多问题&#xff0c;常用的问题有缓存穿透、缓存击穿、缓存雪崩以及缓存一致性问题。 1、缓存穿透 首先&#xff0c;什么是缓存穿透呢&#xff1f; 缓存穿透是指请求一个不存在的数据&#xff0c;缓存层和数据库层都没有这个数据&…

虚拟天空解决方案,创造出令人惊叹的换天效果

在汽车视频领域&#xff0c;如何打破传统拍摄限制&#xff0c;呈现出更具创意和想象力的画面&#xff0c;成为众多企业和创作者追求的目标。美摄科技作为业界领先的视频技术提供商&#xff0c;凭借其强大的AI技术和三维渲染引擎&#xff0c;推出了全新的虚拟天空解决方案&#…

集成电路测试学习

集成电路&#xff08;Integrated Circuit&#xff0c;IC&#xff09;整个设计流程包括&#xff1a;电路设计、晶圆制造、晶圆测试、IC封装、封装后测试。 IC测试目的&#xff1a;一、确认芯片是否满足产品手册上定义的规范&#xff1b;二、通过测试测量&#xff0c;确认芯片可以…

李国武:QFD是如何将顾客需求转换为产品技术要求的?

如何将顾客的多样化需求精准地转化为产品的技术要求&#xff0c;成为企业赢得市场、提升竞争力的关键。质量功能展开&#xff08;Quality Function Deployment&#xff0c;简称QFD&#xff09;作为一种先进的质量管理工具&#xff0c;正是实现这一转换的有效桥梁。具体如天行健…

vim相关指令

vim的各种模式及其转换关系图 vim 默认处于命令模式&#xff01;&#xff01;&#xff01; 模式之间转换的指令 除【命令模式】之外&#xff0c;其它模式要切换到【命令模式】&#xff0c;只需要无脑 ESC 即可&#xff01;&#xff01;&#xff01; [ 命令模式 ] 切换至 [ 插…

unity动画的关键帧添加event-同步语音

在iclone中做的语音嘴型动画&#xff0c;因是用下图自带的方式语音生成的动画&#xff0c;而不是用plugin(面捕live会连同语音一起导出)&#xff0c;所以导出来到Unity中&#xff0c;之后口型、动作、表情等没有声音。 我需要把原有的语音也重新在unity中加载上&#xff0c;原来…

解决WPS右键菜单冗余选项,去除WPS右键菜单选项

问题描述 安装WPS后&#xff0c;右键菜单会多出许多无用的选项&#xff0c;如何去除&#xff1f; 解决方法 按下WindowsS打开搜索栏&#xff0c;搜索配置工具打开 勾选所有的关闭和隐藏选项

汽车视频智能剪辑解决方案,满足用户对高品质汽车视频的追求

随着汽车智能化和互联网技术的快速发展&#xff0c;车载视频已经成为现代驾驶生活不可或缺的一部分。然而面对海量的行车视频&#xff0c;如何高效地剪辑、整理并分享这些精彩瞬间&#xff0c;一直是车主和汽车内容创作者们所面临的难题。美摄科技&#xff0c;作为领先的视频智…

Postgres数据库中的死锁是如何产生的,如何避免和解决?

文章目录 死锁的产生原因如何避免死锁如何解决死锁示例代码查询死锁信息终止事务 在Postgres数据库中&#xff0c;死锁是一种特殊的情况&#xff0c;其中两个或多个事务相互等待对方释放资源&#xff0c;从而导致它们都无法继续执行。这种情况通常发生在多个事务尝试以不同的顺…