核密度估计Kernel Density Estimation(KDE)-代码详细解释
?
在介紹核密度評(píng)估Kernel Density Estimation(KDE)之前,先介紹下密度估計(jì)的問(wèn)題。由給定樣本集合求解隨機(jī)變量的分布密度函數(shù)問(wèn)題是概率統(tǒng)計(jì)學(xué)的基本問(wèn)題之一。解決這一問(wèn)題的方法包括參數(shù)估計(jì)和非參數(shù)估計(jì)。(對(duì)于估計(jì)概率密度,如果確定數(shù)據(jù)服從的分布類(lèi)型,可以使用參數(shù)擬合,否則只能使用非參數(shù)擬合)
參數(shù)估計(jì)又可分為參數(shù)回歸分析和參數(shù)判別分析。在參數(shù)回歸分析中,人們假定數(shù)據(jù)分布符合某種特定的性態(tài),如線性、可化線性或指數(shù)性態(tài)等,然后在目標(biāo)函數(shù)族中尋找特定的解,即確定回歸模型中的未知參數(shù)。在參數(shù)判別分析中,人們需要假定作為判別依據(jù)的、隨機(jī)取值的數(shù)據(jù)樣本在各個(gè)可能的類(lèi)別中都服從特定的分布。經(jīng)驗(yàn)和理論說(shuō)明,參數(shù)模型的這種基本假定與實(shí)際的物理模型之間常常存在較大的差距,這些方法并非總能取得令人滿(mǎn)意的結(jié)果。
?
由于上述缺陷,Rosenblatt和Parzen提出了非參數(shù)估計(jì)方法,即核密度估計(jì)方法。由于核密度估計(jì)方法不利用有關(guān)數(shù)據(jù)分布的先驗(yàn)知識(shí),對(duì)數(shù)據(jù)分布不附加任何假定,是一種從數(shù)據(jù)樣本本身出發(fā)研究數(shù)據(jù)分布特征的方法,因而,在統(tǒng)計(jì)學(xué)理論和應(yīng)用領(lǐng)域均受到高度的重視。
因此,一句話(huà)概括,核密度估計(jì)Kernel Density Estimation(KDE)是在概率論中用來(lái)估計(jì)未知的密度函數(shù),屬于非參數(shù)檢驗(yàn)方法之一。
在密度函數(shù)估計(jì)中有一種方法是被廣泛應(yīng)用的——直方圖。如下圖中的第一和第二幅圖(名為Histogram和Histogram, bins shifted)。直方圖的特點(diǎn)是簡(jiǎn)單易懂,但缺點(diǎn)在于以下三個(gè)方面:
核密度估計(jì)有多種內(nèi)核,圖3(Tophat Kernl Density)為不平滑內(nèi)核,圖4(Gaussian Kernel Density,bandwidth=0.75)為平滑內(nèi)核。在很多情況下,平滑內(nèi)核(如高斯核密度估計(jì),Gaussian Kernel Density)使用場(chǎng)景較多。
雖然采用不同的核函數(shù)都可以獲得一致性的結(jié)論(整體趨勢(shì)和密度分布規(guī)律性基本一致),但核密度函數(shù)也不是完美的。除了核算法的選擇外,帶寬(bandwidth)也會(huì)影響密度估計(jì),過(guò)大或過(guò)小的帶寬值都會(huì)影響估計(jì)結(jié)果。如上圖中的最后三個(gè)圖,名為Gaussian Kernel Density,bandwidth=0.75、Gaussian Kernel Density,bandwidth=0.25、Gaussian Kernel Density,bandwidth=0.55.
上圖為使用Python的sklearn實(shí)現(xiàn),算法為KernelDensity。代碼如下:
#coding:utf-8 import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import KernelDensity np.random.seed(1) N = 20 X = np.concatenate((np.random.normal(0, 1, int(0.3 * N)),np.random.normal(5, 1, int(0.7*N)) ))[:, np.newaxis] #np.newaxis是None的意思 #前半部分的平均值是0,方差是1 #int(0.3 * N)指的是輸出多少數(shù)量符合要求的數(shù)據(jù) #---------------------------以上是創(chuàng)建數(shù)據(jù)集-----------------------------------------------------------------X_plot = np.linspace(-5, 10, 1000)[:, np.newaxis]#創(chuàng)建等差數(shù)列,在-5和10之間取1000個(gè)數(shù) bins = np.linspace(-5, 10, 10)#這個(gè)的作用是,在相鄰兩個(gè)邊界時(shí)間的數(shù)據(jù)對(duì)應(yīng)的y值都一樣大 print("bins=",bins) fig, ax = plt.subplots(2, 2, sharex=True, sharey=True) fig.subplots_adjust(hspace=0.05, wspace=0.05) # 直方圖 1 'Histogram' print("---------------------------------") ax[0, 0].hist(X[:, 0], bins=bins, fc='#AAAAFF', normed=True)#fc指的應(yīng)該是顏色的編碼 #這里的ax[0,0]的意思是畫(huà)在第幾副圖上ax[0, 0].text(-3.5, 0.31, 'Histogram')#-3.5, 0.31的意思是每張圖的logo要畫(huà)在什么地方 # 直方圖 2 'Histogram, bins shifted' ax[0, 1].hist(X[:, 0], bins=bins + 0.75, fc='#AAAAFF', normed=True)#histogram的縮寫(xiě) ax[0, 1].text(-3.5, 0.31, 'Histogram, bins shifted')#每個(gè)子圖內(nèi)畫(huà)標(biāo)簽#-----------------------------------------------------------------------------------# 核密度估計(jì) 1 'tophat KDE' kde = KernelDensity(kernel='tophat', bandwidth=0.75).fit(X)#什么是帶寬 log_dens = kde.score_samples(X_plot) #所以這里有兩組數(shù)據(jù),X和X_plot,其實(shí)是在利用X_plot對(duì)X進(jìn)行采樣。 #所以想要復(fù)用這段代碼的時(shí)候,改X即可,X_plot不用修改ax[1, 0].fill(X_plot[:, 0], np.exp(log_dens), fc='#AAAAFF')#fill就是用來(lái)畫(huà)概率密度的 ax[1, 0].text(-3.5, 0.31, 'Tophat Kernel Density')#設(shè)置標(biāo)題的位置 # 核密度估計(jì) 2 'Gaussian KDE' kde = KernelDensity(kernel='gaussian', bandwidth=0.75).fit(X) log_dens = kde.score_samples(X_plot)#返回的是點(diǎn)x對(duì)應(yīng)概率的log值,要使用exp求指數(shù)還原。 ax[1, 1].fill(X_plot[:, 0], np.exp(log_dens), fc='#AAAAFF')#fill就是用來(lái)畫(huà)概率密度的 #所以上面一句代碼就非常清晰了,X_plot[:, 0]是具體數(shù)據(jù),np.exp(log_dens)指的是該數(shù)據(jù)對(duì)應(yīng)的概率 ax[1, 1].text(-3.5, 0.31, 'Gaussian Kernel Density')#設(shè)置標(biāo)題的位置print("ax.ravel()=",ax.ravel()) print("X.shape[0]=",X.shape[0]) print("X=",X)#這個(gè)是為了在每個(gè)子圖的下面畫(huà)一些沒(méi)用的標(biāo)記,不看也罷 for axi in ax.ravel():axi.plot(X[:, 0], np.zeros(X.shape[0])-0.01, '+k')axi.set_xlim(-4, 9)#設(shè)定上下限axi.set_ylim(-0.02, 0.34)##畫(huà)圖過(guò)程是兩行兩列,這里是遍歷第1列,每個(gè)位置的左側(cè)畫(huà)一個(gè)“xNormalized Density” for axi in ax[:, 0]:print("axi=",axi)axi.set_ylabel('Normalized Density')##畫(huà)圖過(guò)程是兩行兩列,這里是遍歷第2行,每個(gè)位置畫(huà)一個(gè)“x” for axi in ax[1, :]:axi.set_xlabel('x') plt.show()#ravel函數(shù)的作用如下: # >>> x = np.array([[1, 2, 3], [4, 5, 6]]) # >>> print(np.ravel(x)) # [1 2 3 4 5 6]?
KernelDensity算法包括kd_tree和ball_tree,默認(rèn)自動(dòng)選擇。核模型包括gaussian、tophat、epanechnikov、exponential、linear、cosine,默認(rèn)是gaussian模型。可調(diào)整的參數(shù)如下:
?
核密度估計(jì)的應(yīng)用場(chǎng)景:
- 股票、金融等風(fēng)險(xiǎn)預(yù)測(cè);
總結(jié)
以上是生活随笔為你收集整理的核密度估计Kernel Density Estimation(KDE)-代码详细解释的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 先验概率与后验概率、贝叶斯区别与联系
- 下一篇: 根据数据集获取概率密度图像和概率分布图像