机器学习实战:Python基于KDE核密度估计进行分布估计(十六)

news2024/11/25 10:48:24

文章目录

    • 1. 前言
      • 1.1 KDE简介
      • 1.2 KDE应用领域
    • 2. diy数据集实战演示
      • 2.1 导入函数
      • 2.2 自定义数据
      • 2.3 可视化数据
      • 2.4 KDE建模
    • 3. 参数探讨
      • 3.1 带宽
      • 3.2 选择最佳带宽
      • 3.2 核函数
    • 3.4 挑选合适核函数
    • 4. 讨论

1. 前言

1.1 KDE简介

核密度估计(Kernel Density Estimation,简称KDE)是用于估计连续随机变量概率密度函数的非参数方法。它的工作原理是在每个数据点周围放置一个“”(通常是某种平滑的、对称的函数),然后将这些核加起来,形成一个整体的估计。这可以被视为对直方图的平滑,使得得到的密度函数更连续、更平滑。

KDE的主要组件是核函数带宽。核函数确定了每个数据点对估计的贡献的形状,而带宽决定了核的宽度,影响估计的平滑程度。正确选择这两个组件对于获得有意义的估计至关重要。

优点

  • 非参数性:KDE不假设数据遵循任何特定的概率分布,使其具有很高的灵活性,能够适应多种不同的数据形态。

  • 平滑性:与传统的直方图相比,KDE提供的概率密度估计是平滑的,它可以揭示数据中的细微特征而不是粗糙的组块。

  • 数据探索:KDE对于初步的数据探索和可视化非常有用,可以帮助我们直观地了解数据的分布和形状。

  • 核的选择:KDE允许使用不同的核,例如高斯核、三角核等,这为不同的应用和数据特点提供了选择的灵活性。

缺点

  • 计算复杂性:KDE的计算复杂性可以高,特别是当数据集很大时,因为它需要考虑每个数据点与其他所有数据点的关系。

  • 带宽选择:带宽是KDE中最关键的参数。不合适的带宽选择可能导致估计过于嘈杂(过小的带宽)或过于平滑(过大的带宽)。尽管有带宽选择的方法,但它们通常需要额外的计算和调优。

  • 边界问题:在数据分布的边界附近,KDE可能不会提供良好的估计。这是因为在边界附近,核函数可能会延伸到数据的实际范围之外,导致边界处的估计偏低。

  • 高维数据:随着数据维度的增加,KDE面临“维度灾难”。在高维空间中,数据点之间的距离变得相对更远,这使得密度估计变得更加困难。

1.2 KDE应用领域

核密度估计(KDE)是一种广泛应用的统计方法,它在多个领域都有其应用。以下是一些KDE部分应用领域的具体实例:

  1. 数据探索和可视化
    考虑一个电商网站,其中的产品有各种价格。为了了解大多数产品的价格范围,数据分析师可以使用KDE来估计价格分布。这不仅能够揭示价格的中心趋势,还可以揭示价格的多模态分布(例如,低端、中端和高端产品可能有明显的价格聚类)。
  2. 异常检测
    在信用卡欺诈检测中,可以使用KDE来估计正常的交易行为分布,例如交易金额和交易时间。然后,任何明显偏离这个估计的交易都可能被标记为可疑,然后进一步进行调查。
  3. 地理空间分析
    在城市治安管理中,警察部门可以利用KDE来分析报告的犯罪事件的地理位置,以确定犯罪的“热点”地区。这可以帮助他们更有效地部署警力和资源。
  4. 图像处理
    在医学图像分析中,KDE可以用于估计某一区域(如肿瘤)的像素强度分布。这有助于区分正常组织和异常组织,并可以用于自动检测和标记潜在的问题区域。
  5. 生物信息学
    考虑一项研究,旨在分析不同类型的细胞在特定环境下的基因表达。KDE可以用于估计特定基因在各种条件下的表达水平分布,从而帮助研究人员了解基因的激活和抑制模式。
  6. 市场研究
    一个汽车制造商想要了解其竞争对手车型的价格分布。使用KDE,他们可以揭示市场上的价格段,并据此确定他们自己车型的定价策略。

2. diy数据集实战演示

2.1 导入函数

import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KernelDensity
from sklearn.model_selection import GridSearchCV

2.2 自定义数据

生成一个数据集,其中数据来自两个不同的分布:一个对数正态分布和一个正态分布。两个分布各生成1000个数据点,并将这些数据点连接在一起:

  • 对数正态分布使用均值0和标准差0.3。
  • 正态分布使用均值3和标准差1。
def generate_data(rand=None):
    if rand is None:
        rand = np.random.RandomState()
    
    dat1 = rand.lognormal(0, 0.3, 1000)
    dat2 = rand.normal(3, 1, 1000)
    x = np.concatenate((dat1, dat2))
    return x

data = generate_data(np.random.RandomState(17))
data[:10]

# array([1.08641118, 0.57327576, 1.20583266, 1.41000519, 1.3650037 ,
#       1.76119346, 0.96704574, 0.89706191, 1.04561216, 0.876924  ])

2.3 可视化数据

  • 展示数据点的顺序和相对位置
  • 展示数据的分布情况
x_train = generate_data()[:, np.newaxis]
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 5))

ax[0].scatter(np.arange(len(x_train)), x_train, c='red')
ax[0].set_xlabel('Sample no.')
ax[0].set_ylabel('Value')
ax[0].set_title('Scatter plot')

ax[1].hist(x_train, bins=50)
ax[1].set_title('Histogram')

fig.subplots_adjust(wspace=.3)
plt.show()

2.4 KDE建模

x_test = np.linspace(-1, 7, 2000)[:, np.newaxis]
model = KernelDensity().fit(x_train)
log_dens = model.score_samples(x_test)

plt.fill_between(x_test.ravel(), np.exp(log_dens), color='pink')
plt.show()

3. 参数探讨

3.1 带宽

带宽(bandwidth)是核密度估计(KDE)中的一个关键参数,它决定了估计的平滑程度。选择合适的带宽对于获得有意义的密度估计至关重要。

bandwidths = [0.01, 0.05, 0.1, 0.5, 1, 4]
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(10, 7))

for ax, b in zip(axes.ravel(), bandwidths):
    kde_model = KernelDensity(kernel='gaussian', bandwidth=b).fit(x_train)
    score = kde_model.score_samples(x_test)
    ax.fill(x_test, np.exp(score), c='pink')
    ax.set_title(f"h={b}")

fig.subplots_adjust(hspace=0.5, wspace=.3)
plt.show()

3.2 选择最佳带宽

常见的就这四种方法:

  1. 经验法则:一些常见的方法,如Silverman’s rule,可以为一般情况提供一个好的起点。但这些方法可能不适用于所有数据集。

  2. 交叉验证:使用交叉验证选择带宽是一种常见方法。这涉及到将数据分成训练集和验证集,然后对于不同的带宽值,使用训练集进行拟合,并使用验证集计算对数似然评分。选择使得评分最大化的带宽值。

  3. 可视化:像您之前的代码那样,通过为不同的带宽值绘制KDE,可以帮助直观地选择一个合适的带宽。

  4. 数据的范围和分辨率:带宽的绝对值通常与数据的范围和单位有关。例如,如果数据是以米为单位的距离测量值,那么0.01米的带宽与100米的带宽意味着完全不同的事情。

这里用的是交叉验证:

bandwidth = np.arange(0.05, 2, .05)
grid = GridSearchCV(KernelDensity(kernel='gaussian'), {'bandwidth': bandwidth})
grid.fit(x_train)

kde = grid.best_estimator_
log_dens = kde.score_samples(x_test)

plt.fill_between(x_test.ravel(), np.exp(log_dens), color='cyan')
plt.title('Optimal estimate with Gaussian kernel')
plt.show()
print(f"optimal bandwidth: {kde.bandwidth:.2f}")

# optimal bandwidth: 0.15

3.2 核函数

KernelNameDescription
cosine余弦形状类似于余弦曲线的一部分,平滑地从中心下降到零。
epanechnikovEpanechnikov这是一个凸的、平滑的、有界的核,常被用作默认核,因为它在某些理论性质上优于其他核。
exponential指数这是一个从中心点开始快速下降的核,类似于高斯核,但下降得更快。
gaussian高斯或正态这是最常用的核,其形状是标准的正态分布曲线。它为数据点提供了平滑的、无界的权重。
linear线性这是一个三角形的核,从中心线性下降到零。
tophat平顶帽这是一个矩形的核,它在一个固定的范围内为数据点提供均匀的权重,然后突然下降到零。

吐槽一点,“Epanechnikov” 核函数并没有一个广泛接受的中文名字。它是以俄罗斯统计学家Urii Epanechnikov的名字命名的。文献常见被翻译成 “埃潘尼克尼科夫” 核。

kernels = ['cosine', 'epanechnikov', 'exponential', 'gaussian', 'linear', 'tophat']
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(10, 7))
x_range = np.arange(-2, 2, 0.1)[:, None]

for ax, k in zip(axes.ravel(), kernels):
    kde_model = KernelDensity(kernel=k).fit([[0]])
    score = kde_model.score_samples(x_range)
    ax.fill(x_range, np.exp(score), c='blue')
    ax.set_title(k)

fig.subplots_adjust(hspace=0.5, wspace=.3)
plt.show()

3.4 挑选合适核函数

这里直接用刚刚的最佳带宽0.15即可

def my_scores(estimator, X):
    scores = estimator.score_samples(X)
    scores = scores[scores != float('-inf')]
    return np.mean(scores)

kernels = ['cosine', 'epanechnikov', 'exponential', 'gaussian', 'linear', 'tophat']
h_vals = np.arange(0.05, 1, .1)
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(10, 7))

for ax, k in zip(axes.ravel(), kernels):
    grid = GridSearchCV(KernelDensity(kernel=k), {'bandwidth': h_vals}, scoring=my_scores)
    grid.fit(x_train)
    kde = grid.best_estimator_
    log_dens = kde.score_samples(x_test)
    ax.fill(x_test.ravel(), np.exp(log_dens), c='cyan')
    ax.set_title(f"{k} h={kde.bandwidth:.2f}")

fig.subplots_adjust(hspace=.5, wspace=.3)
plt.show()

还是用交叉验证:

grid = GridSearchCV(KernelDensity(),
                    {'bandwidth': h_vals, 'kernel': kernels},
                    scoring=my_scores)
grid.fit(x_train)

best_kde = grid.best_estimator_
log_dens = best_kde.score_samples(x_test)

plt.fill_between(x_test.ravel(), np.exp(log_dens), color='cyan')
plt.title(f"Best Kernel: {best_kde.kernel} h={best_kde.bandwidth:.2f}")
plt.show()

4. 讨论

核密度估计(KDE)是一种非参数方法,用于估计随机变量的概率密度函数。通过在每个观测数据点处放置一个核函数并将它们相加,KDE提供了数据的平滑估计,可以捕捉数据的复杂分布特性,而不受特定参数分布的限制。

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

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

相关文章

结构体和数组结合使用

1、定义结构体 struct Student {int num;char name[32]; }; 2、结构体数组定义 #include<iostream> using namespace std;struct Student {int num;char name[32]; }; int main() {//结构体变量复制方式2struct Student arr[2] { {1,"张三"}, {2,"李四…

从系统角度,看智能制造|百世慧®

7月31日我们结束了智能制造专题第二期“电池智能制造质量管理应用及案例分享”的线上研讨会&#xff0c;有不少朋友没有来得及参加智能制造专题第一期研讨会&#xff0c;同时又工作繁忙。所以&#xff01;今天就由我百小能为大家快速讲解第一期研讨会——“电池智能制造应用”的…

【C++】移动赋值运算符

2023年8月15日&#xff0c;周二上午 概述 移动赋值运算符是一个特殊的赋值运算符&#xff0c;用于从一个对象中移动&#xff08;转移&#xff09;资源到另一个对象&#xff0c;而不是进行复制操作。它通常与右值引用一起使用&#xff0c;以实现高效的资源转移&#xff0c;提高…

用AI解锁声音的奥秘——启英泰伦新成果发布交流会

声音&#xff0c;是由物体或介质的振动引起的&#xff0c;振动源的多样性、振动的频率和波形的差异、传播介质的差异等因素共同作用&#xff0c;使我们能够感知到丰富而多样化的声音世界。听得到、听得清、听得懂、辨得明&#xff0c;是AI语音技术的重要研究课题。 启英泰伦一…

leetcode810. 黑板异或游戏(博弈论 - java)

黑板异或游戏 lc 810 - 黑板异或游戏题目描述博弈论 动态规划 lc 810 - 黑板异或游戏 难度 - 困难 原题链接 - 黑板异或游戏 题目描述 黑板上写着一个非负整数数组 nums[i] 。 Alice 和 Bob 轮流从黑板上擦掉一个数字&#xff0c;Alice 先手。如果擦除一个数字后&#xff0c;剩…

考研算法45天:首字母大写 【字符串:简单】

题目前置知识 如何使用scanf输入一个有空格的字符串 如何输入带空格的字符串_我码了的博客-CSDN博客 scanf("%[^\n]",str); 如何用ascll码将字符串的小写换为大写 char a; a a - 32; 题目概况 AC代码 #include <iostream> using namespace std;int main()…

2023年武汉中级工程师职称评审条件是什么?评审材料需要哪些呢?

2023年武汉中级职称评审马上全面开启&#xff0c;预计8月底或者9月初就会开始申报了。 要求&#xff1a;学历、社保、论文、业绩等各类材料等 出证时间&#xff1a;现在申报&#xff0c;年底出结果&#xff0c;次年3-5月出证 一、2023年武汉中级工程师职称评审条件学历条件是什…

insightface安装过程中提示 Microsoft Visual C++ 14.0 or greater is required.

pip install insightface安装过程中提示 Microsoft Visual C 14.0 or greater is required.Get it with "Microsoft C Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/ 根据提示网站访问官网下载生成工具 打开软件后会自动更新环境&#…

一键免费部署自己的GPT网站

先看看效果 https://chat-gpt-next-web2-xi-three.vercel.app 为啥推荐这个呢&#xff0c;其实市面上已经有很多了&#xff0c;这个主要是UI蛮漂亮的&#xff0c;嘿嘿&#xff01; 你要是简单想弄的话&#xff0c;CSDN就能免费搭建一个&#xff0c;这个就自行百度吧&#xff0c…

solidworks图纸加密软件——「天锐绿盾」图纸防泄密系统

如何保护设计的Solidworks图纸的安全&#xff0c;成为设计行业的朋友普遍遇到的问题&#xff0c;建立一套安全系统来维护内部图纸和文件流通的加密安全。在数据时代&#xff0c;电子图纸文档是设计行业和办公人员无法或缺的工作伙伴&#xff0c;成为信息数据的主要存储方式和外…

Java课题笔记~ EL

1.EL (1).JSP脚本的缺点 使用JSP脚本可以实现页面输出显示&#xff0c;那为什么还需要使用EL简化输出呢&#xff1f; 这是因为单纯使用JSP脚本与HTML标签混合&#xff0c;实现输出显示的方式存在一些弊端&#xff0c;归纳如下&#xff1a; 代码结构混乱&#xff0c;可读性差…

win11系统nvm管理多个node版本并踩坑

需求&#xff1a;公司用的老项目需要使用低版本node&#xff0c;但是自己想用最新的技术&#xff0c;需要使用高版本node&#xff0c;所以下了个nvm来管理多个node版本&#xff0c;进行切换使用。网上那么多nvm的教程为啥我还要写&#xff0c;因为我遇到的问题太离谱了&#xf…

Linux6.38 Kubernetes 集群存储

文章目录 计算机系统5G云计算第三章 LINUX Kubernetes 集群存储一、emptyDir存储卷2.hostPath存储卷3.nfs共享存储卷4.PVC 和 PV 计算机系统 5G云计算 第三章 LINUX Kubernetes 集群存储 容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出…

半导体蚀刻系统市场预计从2021年的101亿美元增长到2028年的120亿美元,复合年增长率为2.5%。

半导体蚀刻设备是半导体製造过程中使用的设备。 化学溶液通过将晶片浸入化学溶液&#xff08;蚀刻剂&#xff09;中来选择性地去除半导体晶片的特定层或区域&#xff0c;化学溶液溶解并去除晶片表面所需的材料。 根据阿谱尔&#xff08;APO&#xff09;的统计及预测&#xff0c…

centos7安装erlang及rabbitMQ

下载前注意事项&#xff1a; 第一&#xff1a;自己的系统版本&#xff0c;centos中uname -a指令可以查看&#xff0c;el8&#xff0c;el7&#xff0c;rabbitMQ的包不一样&#xff01; 第二&#xff1a;根据rabbitMQ中erlang version找到想要下载rabbitMQ对应erlang版本&#x…

ABAP Der Open SQL command is too big.

ABAP Der Open SQL command is too big. DBSQL_STMNT_TOO_LARGE CX_SY_OPEN_SQL_DB 应该是选择条件中 维护的条件值条数太多了

五个独特且有趣的ChatGPT指令

今天分享5个很实用的指令&#xff0c;这几个指令很多时候对我们输出内容的连贯性、文章风格、创意性等方面有着决定性的作用。 目录 第一个&#xff1a;Max tokens&#xff08;最大令牌&#xff09; 第二个&#xff1a;Top_p(控制采样) 第三个&#xff1a;Presence_penalty …

视频汇聚平台EasyCVR视频监控播放平台WebRTC流地址无法播放的问题解决方案

开源EasyDarwin视频监控TSINGSEE青犀视频平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多…

msvcp140.dll是什么东西?msvcp140.dll丢失的解决方法

修复msvcp140.dll文件的过程可能会让人感到有些困扰&#xff0c;尤其是对于不太熟悉计算机维护的人来说。当出现msvcp140.dll文件缺失的错误提示时&#xff0c;我意识到这是一个关键的问题&#xff0c;因为该文件是许多应用程序正常运行所必需的。因此&#xff0c;我立即采取行…

实现文件的拖放功能

文章目录 实现文件的拖放功能1 拖放文件至QT窗口1.1 实现方法1.2 效果演示 2 拖放文件至python脚本2.1 实现方法2.2 效果演示 实现文件的拖放功能 试想一下&#xff0c;我们希望将一个python项目文件夹或者脚本在IDE中打开&#xff0c;无论是去IDE中选择文件夹路径&#xff0c;…