跳至内容

核密度估计:从原理到实践

核密度估计是一种非参数方法,用于在不假设固定模型的情况下估计数据分布的形状。了解其公式、带宽选择,以及在 Python 与 R 中的上手实现。
更新 2026年6月16日  · 11分钟

尝试可视化一个分布时,是否遇到过这样的问题:每次调整直方图的分箱大小,图形的形状就变了?

通常是这样的。您选 10 个箱,看起来像一条平滑的曲线;换成 30 个箱,就出现了多个峰。数据没变,但不同的分箱数会给出不同的解读。这是直方图最大的毛病:它并不展示“分布”本身,而是展示某一种版本;而这种版本受到您随机设定的参数影响。

KDE(核密度估计)采用了不同的方法。它不把数据切分进箱,而是在每个数据点上放置一条小而平滑的曲线,然后把它们加总。这会给出一个对背后分布的单一、连续的估计。

本文将带您建立 KDE 的直觉、走读其公式、解释带宽如何控制平滑度,并提供 Python 和 R 的实用示例。

还不熟悉直方图?这里有一份全面指南:频率直方图,助您快速上手。

什么是核密度估计?

核密度估计是一种非参数方法,用于估计数据集的概率密度函数。

“非参数”正是它的不同之处。

参数方法需要假设数据服从某个特定分布——如正态、指数——然后拟合参数去匹配。如果假设错了,模型就错了。KDE 不做这样的假设。它让数据自己“发声”,直接从观测构建对底层分布的估计。

输出是一条平滑曲线,展示数值可能落在哪里——以及有多大可能。曲线的高点意味着密集区域,低点意味着稀疏区域。

为什么要用核密度估计?

直方图是可视化分布的默认工具,但它有个问题:您看到的形状取决于您选择的分箱数量。而这个分箱参数是由您来定。两个人看同一数据集,仅仅因为分箱数不同,就可能得出完全不同的结论。

使用 KDE,不再强行把数据塞进箱里,而是生成一条平滑、连续的曲线,不会因为您事先设定的任意参数而改变。

因此它在以下方面很有用:

  • 在不受分箱大小偏差影响的情况下可视化分布的整体形状
  • 检测多峰、偏态或厚尾等模式
  • 在同一图上比较不同组的分布
  • 在建模前更清晰地了解数据情况

KDE 的直观理解

对每个数据点放置一条小而平滑的曲线,这条曲线称为核(kernel)。然后,把这些单独的曲线全部相加。

最终得到一条展示数据密度的平滑曲线。数据点聚集的地方,多条核会重叠并叠加,曲线就会上升;数据稀疏的地方,核几乎不重叠,曲线就保持较低。每个点对最终估计的贡献都是相同的。

想象您记录了一门课学生的期末成绩。与其用直方图分箱,KDE 会在每个分数上放一条小而平滑的曲线。分数聚集的地方——比如 70–75 分附近——曲线会叠加上升;而一个考了 95 分的学生,只会在尾部加出一个小凸起。

下图正是这种效果。大多数学生集中在平均分附近,且有一位学生分数高得多:

KDE 可视化

KDE 可视化

核密度估计公式

KDE 的公式看起来比实际难。

KDE 公式

各部分含义如下:

  • n 是数据点的数量

  • x_i 是数据集中各个具体的数据点

  • K 是核函数——放在每个点上的平滑曲线

  • h 是带宽——控制每个核的宽度

  • x 是您要评估密度的位置

通俗地说,该公式表示:对于任意一点 x,看每个数据点 x_i 离它有多近,用核函数 K 对这种“接近程度”加权,并在全部 n 个点上取平均。对范围内的每个 x 都这么做,就得到完整的密度曲线。

带宽 h 位于 K 内部分数的分母。较小的 h 使核更窄,因此只有非常近的点会影响估计;较大的 h 会扩大影响范围。稍后将详细介绍。

什么是核函数?

核就是您放在每个数据点上的平滑曲线。它定义了该点的影响如何向邻近点扩散。

每个核都以某个数据点为中心,并根据距离分配权重。越靠近中心的点权重越高,越远的点权重越低,甚至为零。具体的加权形状取决于您选择的核。

常见的三种选择:

  • 高斯: 钟形曲线。为数据集中的每个点分配权重,且影响随距离衰减。这是大多数库的默认选项,实践中表现良好
  • 均匀: 平顶矩形。固定距离内的点权重相同,外部的权重为零。简单,但平滑度较差
  • Epanechnikov: 抛物线形,在均方误差意义上是数学上最优的。比高斯更高效,但在可视化效果上很少带来明显差异。

多数情况下,核的选择影响不大。对同一数据、用相同带宽,两个不同的核通常会产生几乎相同的曲线。真正更重要的是带宽——我们接下来就看它。

带宽在 KDE 中的作用

带宽是对 KDE 输出影响最大的单一参数,甚至超过核的选择。

它控制每个核的宽度。窄核只吸收附近点的影响,宽核则把影响扩散到更大的范围。结果要么是紧贴数据的曲线,要么是更平滑的曲线。

小带宽

小带宽会让每个核紧而窄。估计会对每个数据点产生剧烈反应,这意味着既能捕捉到数据的真实结构,也会拾取噪声。

在实践中,这看起来像是一条多处尖峰的曲线。其中一些峰反映了真实聚类,另一些只是平滑不足造成的伪影。难点在于很难区分二者。

小带宽的 KDE

小带宽的 KDE

大带宽

大带宽会让每个核更宽。相邻核大量重叠,最终曲线会更平滑。

如果过于平滑,就会失去真实结构。两个明显的聚类可能被抹成一条曲线;厚尾分布可能看起来对称。可视化反而可能在“藏”信息。

大带宽的 KDE

大带宽的 KDE

如何找到合适的带宽

没有普适正确的带宽。目标是在足以滤掉噪声的同时,不至于把真实模式抹平。

大多数库提供自动带宽选择方法,其中Silverman 经验法则最常见。它根据样本量和数据的标准差选择带宽。对近似正态分布效果好,但可能对多峰分布过度平滑。

如果拿不准,可以尝试几个带宽值并比较曲线。差异会告诉您很多关于数据的信息。

KDE 与直方图

直方图和 KDE 都能展示数据的分布——但方式截然不同。

直方图

直方图把数据划分到离散的箱中,并统计每个箱中点的数量。它快速、直观,易于向非技术受众解释。

问题在于对分箱的敏感性。只要改变箱数,形状就变了。没有客观正确的分箱数量,这意味着两个人看同一数据,仅因这个选择不同就会得出不同结论。

直方图还会产生台阶状、不连续的形状。用于快速查看还好,但可能遮蔽真实的底层分布。

KDE

KDE 给出的是没有分箱参与的平滑、连续曲线。它更擅长揭示分布的真实形状——诸如偏态、多峰或厚尾等,而直方图可能因为分箱选择而忽略或误导。

代价是 KDE 引入了自己的参数——带宽——并且计算量更大。它也不太直观,因为 y 轴显示的是概率密度而不是计数,这可能会让不熟悉该概念的读者困惑。

各自何时使用

当您需要对数据进行快速、易解释的总结,或受众不熟悉密度估计时,用直方图;当分布形状很重要——比如要比较不同组,或要检测数据中的多峰——则使用 KDE。

直方图与 KDE 对比

直方图与 KDE 对比

实践中,它们常常结合使用:直方图显示计数,叠加一条 KDE 曲线展示形状。

Python 中的核密度估计

在 Python 中,有多种方式计算和绘制 KDE,取决于您是需要快速出图还是要更精细地控制估计本身。

用 seaborn 可视化 KDE

获取 KDE 图的最快方式是 seaborn.kdeplot()。只需如下代码:

import seaborn as sns
import numpy as np

np.random.seed(42)
scores = np.concatenate([
    np.random.normal(65, 4, 60),
    np.random.normal(80, 3, 40)
])

sns.kdeplot(scores, bw_adjust=1)

使用 seaborn 的 KDE

使用 seaborn 的 KDE

参数 bw_adjust 会缩放自动选择的带宽。小于 1 会让曲线更紧,超过 1 会让曲线更平滑。它是在 seaborn 内部带宽之上的一个倍数,因此您无需自己设定原始带宽值。

y 轴显示的是概率密度,而不是计数。曲线告诉您相对于整个分布来说某个数值有多可能。越高意味着那里数据越集中。

用 scipy 计算 KDE

如果您需要实际的密度数值——而不仅仅是图——可以使用 scipy.stats.gaussian_kde。它会返回一个可调用对象,您可以在任意点上进行评估。

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

kde = gaussian_kde(scores, bw_method="scott")
x = np.linspace(45, 100, 500)
density = kde(x)

plt.plot(x, density)

bw_method="scott" 使用 Scott 法则自动选择带宽。这在大多数情况下是不错的默认值。您也可以传入一个标量手动设置带宽。

使用 scipy 与 matplotlib 的 KDE

使用 scipy 与 matplotlib 的 KDE

R 中的核密度估计

在 R 中,KDE 内置于基础语言,无需额外包。

用 density() 计算 KDE

函数 density() 接受一个数值向量并返回 KDE 对象。

set.seed(42)
scores <- c(rnorm(60, mean = 65, sd = 4),
            rnorm(40, mean = 80, sd = 3))

kde <- density(scores, bw = "SJ")

参数 bw 控制带宽选择。"SJ" 使用 Sheather–Jones 方法,相比默认值更适合处理多峰分布。您也可以传入数值手动设置带宽。

结果是一个列表对象,包含两个关键组件:

  • kde$x: 进行密度评估的一系列点
  • kde$y: 对应的密度值

绘制曲线

将结果直接传给 plot() 即可。

plot(kde,
     main = "Exam Score Distribution",
     xlab = "Score",
     ylab = "Density")

在 R 中绘制的 KDE

要在直方图上叠加 KDE,先用 hist() 并设定 freq = FALSE,然后用 lines() 添加曲线。

hist(scores, freq = FALSE, main = "Histogram + KDE", xlab = "Score")
lines(kde, col = "blue", lwd = 2)

R 中的直方图与 KDE

freq = FALSE 会将直方图按密度缩放,使柱形与曲线共享同一 y 轴。

KDE 的优点与局限

KDE 确实是很有用的可视化手段,但和任何方法一样,在用它替代直方图之前,值得了解其中的取舍。

优点

最大优点在于 KDE 不对数据分布做假设。您无需事先决定数据是否正态、指数或其他类型。形状来自数据本身,使 KDE 足够灵活,可处理多峰分布及其他不符合标准参数形式的情况。

其输出是一条平滑、连续的曲线,而非台阶式近似。这更便于发现模式——如多峰或长尾——而这些可能会因直方图的分箱选择而被遮蔽。

且由于 KDE 直接作用于原始数据,无需先拟合模型,它是任何探索性分析的良好第一步。

局限

带宽选择是主要弱点。若选得不当,估计要么追逐噪声,要么把真实模式抹平。像 Silverman 经验法则这样的自动方法对近似正态的数据效果不错,但在复杂分布下可能误导您。通常需要手动检查几个带宽值,才能对结果放心。

在大规模数据上,性能可能成为问题。KDE 需要在每个评估位置对每个数据点计算一次核函数,因此随着数据集变大,计算量会快速增长。对于大多数探索性工作这不是问题,但在包含几十万点的数据上可能会变慢。

边界效应更为微妙。标准 KDE 假设数据可在两个方向上无限延伸。当数据存在硬边界——如不能小于零的取值——估计会将概率质量“泄漏”到边界之外,从而使边缘附近的曲线被人为压低。存在边界校正版本的 KDE,但在标准库中较少实现。

结论

相比直方图,KDE 为查看数据分布提供了更干净的方式。无需分箱选择,也无需参数假设——只有一条展示数据集中实际内容的平滑曲线。

带宽是唯一真正重要的参数。尝试几个取值、比较曲线、使用自动选项,并在下结论前确保估计与您对数据的认知一致。

建立 KDE 直觉的最佳方法是把它用在真实数据上。选一个您熟悉的数据集,应用 KDE,并与直方图对比,看看此前忽略了什么。

对数据可视化感兴趣?如果您使用 Python,请查看我们的课程用 Seaborn 进行数据可视化;如果您使用 R,请查看用 ggplot2 进行数据可视化

FAQs

核密度估计用于什么?

KDE 用于在不假设数据服从特定形状(如正态或指数分布)的前提下,估计数据集的概率分布。它常见于探索性数据分析,在建模前用于可视化数据的分布情况。您还会在异常检测、跨组分布比较、以及统计流程中的平滑步骤中看到它的应用。

KDE 与直方图有何不同?

直方图将数据分到离散的箱中,统计每个箱内的点数。得到的形状取决于您选择的箱数,因而对一个任意参数敏感。KDE 则在每个数据点上放置平滑曲线并求和,从而得到不依赖分箱数量的连续估计。

使用 KDE 是否需要大数据集?

KDE 可用于小数据集,但当数据点很少时估计的可靠性会下降。由于数据有限,单个观测对最终曲线影响很大,难以将真实结构与噪声区分开来。随着数据集增大,估计会更稳定,更准确地反映真实分布。

选择错误带宽会怎样?

带宽过小会产生对每个点都敏感的尖刺曲线,使整体形状难以辨认。带宽过大会过度平滑,可能把不同峰合并成一个隆起,掩盖真实结构。大多数库提供如 Silverman 经验法则的自动带宽选择作为起点,但在得出结论前,最好手动测试几个取值。

KDE 在数据边界附近表现如何?

标准 KDE 假设数据可在两个方向上无限延伸,这在变量存在硬下限或上限(如年龄、收入或任何不能小于零的计数)时会带来问题。靠近这些边界时,估计会将概率质量“泄漏”到有效范围之外,导致边缘附近的曲线被人为压低。为此存在边界校正的 KDE 方法,但并非所有库都提供,且需要额外设置。

主题

与 DataCamp 一起学习

Courses

Support Vector Machines in R

4小时
11K
This course will introduce the support vector machine (SVM) using an intuitive, visual approach.
查看详情Right Arrow
开始课程
查看更多Right Arrow