在做分类问题时,有时候需要使用样本的概率密度函数来求其后验概率。但是很多情况下并不知道其概率密度函数的形式(即样本的分布未知),此时就需要对样本进行非参数估计,来求解其概率密度函数。

       求解未知分布样本的概率密度函数的一种方法是:$n$个样本点中,在某点周围取一个区间$R_{n}$,计算区间$R_{n}$的体积$V_{n}$以及落在$R_{n}$中的样本的个数$k_{n}$,然后就可以求出该点处的概率密度:

$$p(\boldsymbol{x})=\frac{(k_{n}/n)}{V_{n}}\quad \quad \quad(1)$$

       Parzen窗方法就是一种非参数估计的方法,它的主要思想是选取一个窗函数$\varphi(\boldsymbol{u})$,通过该窗函数来统计落在所取区间中的样本个数$k_{n}$,然后通过公式(1)得到某个点的概率密度。一种窗函数$\varphi(\boldsymbol{u})$定义如下:

$$\varphi(\boldsymbol{u})= \begin{cases} \ 1 \qquad |u_{j}| \leq 0.5; \qquad j = 1,…,d \\\\
\ 0 \qquad 其它 \end{cases}$$

其中$d$表示空间的维度。若取区间$R_{n}$为一个超立方体,它的边长为$h_{n}$,则可以通过如下表达式计算$k_{n}$:

$$k_{n} = \sum _{i=1} ^{n}\varphi(\frac {\boldsymbol{x}- \boldsymbol{x_{i}}}{h_{n}})$$

因此样本中某点$\boldsymbol{x}$处的概率密度为:

$$p(\boldsymbol{x}) = \frac{1}{n} \sum _{i=1} ^{n} \frac{1}{h^d _{n}} \varphi(\frac {\boldsymbol{x}- \boldsymbol{x_{i}}}{h_{n}})$$

       Parzen窗方法的代码实现如下,其中参数$Data$为样本总体,$X$为需要求概率密度的点坐标,$h$为参数,$d$为样本空间的维度,$f$为窗函数$\varphi(\boldsymbol{u})$。

def Parzen(Data, X, h, d, f) :
    Prob = []
    n = len(Data)
    for x in X :
        p = 0.0
        for s in Data :
            p += f((s-x)/h)
        Prob.append(p / (n * (h**d)))
    return np.array(Prob) 

如下代码是上述$\varphi(\boldsymbol{u})$函数的实现,即判断当前样本点是否落在了所取的超立方体空间中:

def cube(u) :
    T = abs(u)
    if all(t <= 0.5 for t in T) :
        return 1
    else :
        return 0

       窗函数$\varphi(\boldsymbol{u})$的形式可以有很多方式,但必须满足如下的性质,以此保证最终求解的概率密度函数是合理的。

$$\varphi(\boldsymbol{u}) \geq 0 \quad 以及 \quad \int \varphi(\boldsymbol{u})d\boldsymbol{u} = 1$$

例如当样本空间为一维时,我们可以也定义窗函数是一个高斯函数:

$$\varphi(\boldsymbol{u})= \frac{1}{\sqrt{2 \pi}} e^{-u^{2}/2}$$

       Parzen窗方法是给定区间的范围$h_{n}$,求落在区间的样本点个数$k_{n}$,以此估计概率密度。除了Parzen窗方法外,k近邻估计也可以实现对概率密度函数的估计,与Parzen窗方法不同的是,k近邻估计是先给定要取的样本点的个数$k_{n}$,然后求点$\boldsymbol{x}$附近包含$k_{n}$个样本的区间的范围$h_{n}$,最后通过公式(1)求解概率密度。如下是k近邻估计的实现代码,其中参数$f$为求解两个点直接距离的函数。

def knn(Data, X, kn, d, f) :
    t = kn / len(Data)
    Prob = []
    for x in X :
        dis = []
        for s in Data :
            dis.append(f(x,s))
        dis.sort()
    	v = (dis[kn] * 2) ** d
        Prob.append(t/v)
    return np.array(Prob)

        下图是通过Parzen窗方法和k近邻估计对某个样本(二维正态分布样本随机采样获得)概率密度函数的估计结果。

nonparam

以上两种非参数估计的Python实现可以在我的GitHub中获取到。


1.参考文档:

       [1]. 模式分类              Richard O.Duda 等著       李宏东 等译