非參數估計之 kernel density estimation (核密度估計)
在概率密度估計過程中,如果我們隊隨機變量的分布是已知的,那么可以直接使用參數估計的方法進行估計,如最大似然估計方法。
然而在實際情況中,隨機變量的參數是未知的,因此需要進行非參數估計.核密度估計是非參數估計的一種方法,也就是大家經常聽見的parzen 窗方法了.
本文主要介紹 非參數估計的過程以及 parzen窗方法估計概率密度的過程.
非參數估計
過程

如圖1所示,對於一個未知的概率密度函數,某一個隨機變量
落在區域
里的概率可以表示成如下形式:
如果足夠窄,我們可以用
來表示
的一個平均后的結果。假設我們現在有
個樣本,
且他們服從獨立同分布,那么個樣本中的
個落在區域
中的概率可以表示成下面的公式:
由上面的公式我們可以得到的期望為:
同時,當足夠大時,我們可以近似地認為
可以作為
的一個近似值。
然后,假設足夠大,
足夠小,並且假設
是連續的,那么我們可以得到:
其中是區域
中的一個點,
是
的面積(體積),結合上述4個式子,得:
因此,某一小區域內的概率密度函數就可以用上述公式表示了。
問題
我們再看一下公式(6):
顯然我們估計的這個概率密度是一個平滑的結果,即當選擇的越大,估計的結果和真實結果相比就越平滑;因此看起來我們需要把
設置的小一點,然而如果我們把
選擇的過小,也會出現問題:太小的
會導致這塊小區域里面沒有一個點落在里面,因此就會得到該點的概率密度為0;另外,假設剛好有一個點落在了這個小區域里,那由於V過於小,我們計算得到的概率密度可能也會趨近於無窮,兩個結果對於我們來說都是沒有太大意義的.
從 實際的角度來看,我們獲取的數據量一定是有限的,因此體積不可能取到無窮小,我們可以總結下,使用非參數概率密度估計有以下兩方面限制,且是不可避免的:
- 在有限數據下,使用非參數估計方法計算的概率密度一定是真實概率密度平滑后的結果.
- 在有限數據下,體積趨於無窮小計算的概率密度沒有意義.
從 理論的角度來看,我們希望知道如果有無限多的采樣數據,那么上述兩個限制條件應該怎樣克服?假設我們使用下面的方法來估計點 處的概率密度: 構造一系列包含
的區域
, 其中
中包含一個樣本,
中包含
個樣本.則:
其中表示第
次估計結果,如果要求
能夠收斂到
,則需要滿足下面三個條件:
parzen窗法
原理
假設是一個
維的超立方體(hypercube),且其邊長為
, 那么我們可以用如下公式表示
:
然后我們再定義一個窗函數(window function):
定義了一個以圓點為中心的單位超立方體,這樣我們就可以用
來表示體積
內的樣本個數:
好了,有了和
,直接把他們帶入公式(6),我們可以得到parzen窗法的計算公式:
我們發現這個
不僅可以是上述的單位超立方體的形式,只要其滿足如下兩個約束就可以,因此也就出現了各種各樣更能表現樣本屬性的窗函數,比如用的非常多的高斯窗.
解釋
網上經常會見到這樣的解釋: 某一點的概率密度是其他樣本點在這一點的概率密度分布的平均值.還有這樣一張圖:

上面一句話可以這樣解釋:
我們定義核函數:
那么某一點的概率密度可以用如下函數來表示:
從公式(13)(14)我們可以看出,當很大的時候,
就是一個 矮胖的函數,由公式(14)將每個樣本點在點
處的貢獻取平均之后,點
處的概率密度就是一個非常平滑的結果; 當
太小的時候,
就是一個 高瘦的函數,由公式(14)將每個樣本點在點
處的貢獻取平均之后,點
處的概率密度就是一個受噪聲影響非常大的值,因此估計的概率密度平滑性就很差,反而和真實值差的很遠.這兩點和1.2節總結的兩點缺陷正好吻合.
仿真實驗
如下我做了兩個仿真
- 第一個是生成了均值是0,方差是2的服從高斯分布的數據,分別使用bandwidth為0.1, 1, 5三個值進行估計
- 第二個是生成了100個服從高斯混合分布的數據,分別是均值為0,方差為1以及均值為5,方差為1的兩個高斯混合模型,兩者相互獨立。
這里核函數選的是高斯核。
bandwidth = 0.1 | bandwidth = 1 | bandwidth = 5 |
---|---|---|
![]()
0.1-1.png
|
![]()
1-1.png
|
![]()
5-1.png
|
bandwidth = 0.1 | bandwidth = 0.5 | bandwidth = 1 |
{
![]()
0.1-2.png
|
![]()
0.5-2.png
|
![]()
1-2.png
|
可以很明顯得看到估計的概率密度是如何受到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.