在概率密度估计过程中,如果我们队随机变量的分布是已知的,那么可以直接使用参数估计的方法进行估计,如最大似然估计方法。

然而在实际情况中,随机变量的参数是未知的,因此需要进行非参数估计.核密度估计是非参数估计的一种方法,也就是大家经常听见的parzen 窗方法了.

本文主要介绍 非参数估计的过程以及 parzen窗方法估计概率密度的过程.

非参数估计

过程

python带有核密度曲线的直方图 核密度估计r语言_机器学习

如图1所示,对于一个未知的概率密度函数python带有核密度曲线的直方图 核密度估计r语言_机器学习_02,某一个随机变量python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03落在区域python带有核密度曲线的直方图 核密度估计r语言_机器学习_04里的概率可以表示成如下形式:

python带有核密度曲线的直方图 核密度估计r语言_python_05

如果python带有核密度曲线的直方图 核密度估计r语言_机器学习_04足够窄,我们可以用python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_07来表示python带有核密度曲线的直方图 核密度估计r语言_机器学习_02的一个平均后的结果。假设我们现在有python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_09个样本,
且他们服从独立同分布,那么python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_09个样本中的python带有核密度曲线的直方图 核密度估计r语言_python带有核密度曲线的直方图_11个落在区域python带有核密度曲线的直方图 核密度估计r语言_机器学习_04中的概率可以表示成下面的公式:

python带有核密度曲线的直方图 核密度估计r语言_机器学习_13

由上面的公式我们可以得到python带有核密度曲线的直方图 核密度估计r语言_python带有核密度曲线的直方图_11的期望为:

python带有核密度曲线的直方图 核密度估计r语言_机器学习_15

同时,当python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_09足够大时,我们可以近似地认为python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_17可以作为python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_07的一个近似值。

然后,假设python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_09足够大,python带有核密度曲线的直方图 核密度估计r语言_机器学习_04足够小,并且假设python带有核密度曲线的直方图 核密度估计r语言_机器学习_02是连续的,那么我们可以得到:

python带有核密度曲线的直方图 核密度估计r语言_机器学习_22

其中python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03是区域python带有核密度曲线的直方图 核密度估计r语言_机器学习_04中的一个点,python带有核密度曲线的直方图 核密度估计r语言_机器学习_25python带有核密度曲线的直方图 核密度估计r语言_机器学习_04的面积(体积),结合上述4个式子,得:

python带有核密度曲线的直方图 核密度估计r语言_机器学习_27
python带有核密度曲线的直方图 核密度估计r语言_python_28

因此,某一小区域内的概率密度函数就可以用上述公式表示了。

问题

我们再看一下公式(6):

python带有核密度曲线的直方图 核密度估计r语言_机器学习_29

显然我们估计的这个概率密度是一个平滑的结果,即当python带有核密度曲线的直方图 核密度估计r语言_机器学习_25选择的越大,估计的结果和真实结果相比就越平滑;因此看起来我们需要把python带有核密度曲线的直方图 核密度估计r语言_机器学习_25设置的小一点,然而如果我们把python带有核密度曲线的直方图 核密度估计r语言_机器学习_25选择的过小,也会出现问题:太小的python带有核密度曲线的直方图 核密度估计r语言_机器学习_25会导致这块小区域里面没有一个点落在里面,因此就会得到该点的概率密度为0;另外,假设刚好有一个点落在了这个小区域里,那由于V过于小,我们计算得到的概率密度可能也会趋近于无穷,两个结果对于我们来说都是没有太大意义的.

实际的角度来看,我们获取的数据量一定是有限的,因此体积python带有核密度曲线的直方图 核密度估计r语言_机器学习_25不可能取到无穷小,我们可以总结下,使用非参数概率密度估计有以下两方面限制,且是不可避免的:

  1. 在有限数据下,使用非参数估计方法计算的概率密度一定是真实概率密度平滑后的结果.
  2. 在有限数据下,体积趋于无穷小计算的概率密度没有意义.

理论的角度来看,我们希望知道如果有无限多的采样数据,那么上述两个限制条件应该怎样克服?假设我们使用下面的方法来估计点 python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03 处的概率密度: 构造一系列包含 python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03 的区域 python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_37, 其中 python带有核密度曲线的直方图 核密度估计r语言_核密度估计_38 中包含一个样本,python带有核密度曲线的直方图 核密度估计r语言_核密度估计_39中包含 python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_09

python带有核密度曲线的直方图 核密度估计r语言_机器学习_41

其中python带有核密度曲线的直方图 核密度估计r语言_python带有核密度曲线的直方图_42表示第python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_09次估计结果,如果要求python带有核密度曲线的直方图 核密度估计r语言_python带有核密度曲线的直方图_42能够收敛到python带有核密度曲线的直方图 核密度估计r语言_机器学习_02,则需要满足下面三个条件:

  • python带有核密度曲线的直方图 核密度估计r语言_核密度估计_46
  • python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_47
  • python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_48

parzen窗法

原理

假设python带有核密度曲线的直方图 核密度估计r语言_核密度估计_39是一个python带有核密度曲线的直方图 核密度估计r语言_机器学习_50维的超立方体(hypercube),且其边长为python带有核密度曲线的直方图 核密度估计r语言_核密度估计_51, 那么我们可以用如下公式表示python带有核密度曲线的直方图 核密度估计r语言_python_52:

python带有核密度曲线的直方图 核密度估计r语言_机器学习_53

然后我们再定义一个窗函数(window function):

python带有核密度曲线的直方图 核密度估计r语言_核密度估计_54

python带有核密度曲线的直方图 核密度估计r语言_机器学习_55 定义了一个以圆点为中心的单位超立方体,这样我们就可以用python带有核密度曲线的直方图 核密度估计r语言_机器学习_55来表示体积python带有核密度曲线的直方图 核密度估计r语言_机器学习_25内的样本个数:

python带有核密度曲线的直方图 核密度估计r语言_python_58

好了,有了python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_59python带有核密度曲线的直方图 核密度估计r语言_python_52,直接把他们带入公式(6),我们可以得到parzen窗法的计算公式:
python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_61

我们发现这个python带有核密度曲线的直方图 核密度估计r语言_机器学习_62不仅可以是上述的单位超立方体的形式,只要其满足如下两个约束就可以,因此也就出现了各种各样更能表现样本属性的窗函数,比如用的非常多的高斯窗.

  1. python带有核密度曲线的直方图 核密度估计r语言_python_63
  2. python带有核密度曲线的直方图 核密度估计r语言_python_64

解释

网上经常会见到这样的解释: 某一点的概率密度是其他样本点在这一点的概率密度分布的平均值.还有这样一张图:

python带有核密度曲线的直方图 核密度估计r语言_核密度估计_65

上面一句话可以这样解释:
我们定义核函数:
python带有核密度曲线的直方图 核密度估计r语言_python_66

那么某一点python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03的概率密度可以用如下函数来表示:
python带有核密度曲线的直方图 核密度估计r语言_机器学习_68

从公式(13)(14)我们可以看出,当python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_69很大的时候,python带有核密度曲线的直方图 核密度估计r语言_机器学习_70就是一个 矮胖的函数,由公式(14)将每个样本点在点python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03处的贡献取平均之后,点python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03处的概率密度就是一个非常平滑的结果; 当python带有核密度曲线的直方图 核密度估计r语言_概率密度估计_69太小的时候,python带有核密度曲线的直方图 核密度估计r语言_机器学习_70就是一个 高瘦的函数,由公式(14)将每个样本点在点python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03处的贡献取平均之后,点python带有核密度曲线的直方图 核密度估计r语言_核密度估计_03处的概率密度就是一个受噪声影响非常大的值,因此估计的概率密度平滑性就很差,反而和真实值差的很远.这两点和1.2节总结的两点缺陷正好吻合.

仿真实验

如下我做了两个仿真

  1. 第一个是生成了均值是0,方差是2的服从高斯分布的数据,分别使用bandwidth为0.1, 1, 5三个值进行估计
  2. 第二个是生成了100个服从高斯混合分布的数据,分别是均值为0,方差为1以及均值为5,方差为1的两个高斯混合模型,两者相互独立。

这里核函数选的是高斯核。

python带有核密度曲线的直方图 核密度估计r语言_机器学习_77

可以很明显得看到估计的概率密度是如何受到bandwidth影响的,当bandwidth选择的太小,则估计的密度函数受到噪声影响很大,这种结果是不能用的;当bandwidth选择过大,则估计的概率密度又太过于平滑。总之,无论bandwidth过大还是过小,其结果都和实际情况相差的很远,因此合理地选择bandwidth是很重要的。

下面是高斯混合分布密度估计的代码。

import matplotlib.pyplot as plt 
import numpy as np 
from sklearn.neighbors.kde import KernelDensity
from scipy.stats import norm

if __name__ == "__main__":
    np.random.seed(1)

    x = np.concatenate((np.random.normal(0, 1, int(0.3*100)), np.random.normal(5, 1, int(0.7*100))))[:, np.newaxis]
    plot_x = np.linspace(-5, 10, 1000)[:, np.newaxis]
    true_dens = 0.3*norm(0, 1).pdf(plot_x) + 0.7*norm(5, 1).pdf(plot_x)

    log_dens = KernelDensity(bandwidth=1).fit(x).score_samples(plot_x)

    plt.figure(),
    plt.fill(plot_x, true_dens, fc='#AAAAFF', label='true_density')
    plt.plot(plot_x, np.exp(log_dens), 'r', label='estimated_density')
    for _ in range(x.shape[0]):
        plt.plot(x[:, 0], np.zeros(x.shape[0])-0.01, 'g*') 
    plt.legend()

    plt.show()

参考资料

[1.] sklearn:Simple 1D Kernel Density Estimation

[2.] Richard O. Duda, Peter E. Hart, and David G. Stork. 2000. Pattern Classification (2nd Edition). Wiley-Interscience, New York, NY, USA.

[3. ]Kernel density estimation

[4.] 边肇祺, 张学工, 2000. 模式识别. 清华大学出版社.