python - 如何规范 scikit learn 的 kde?
问题描述
假设我有一个形状数组 (100000,1),表示变量 X 在 0 和 1 之间均匀分布的样本。我想估计这个变量的概率密度,我使用 Scikit-Learn KernelDensity 来做到这一点。
问题是我只得到一个未标准化的结果。概率密度的积分总和不等于 1。我应该如何自动归一化?难道我做错了什么 ?
def kde_sklearn(data, grid, **kwargs):
"""
Kernel Density Estimation with Scikit-learn
Parameters
----------
data : numpy.array
Data points used to compute a density estimator. It
has `n x p` dimensions, representing n points and p
variables.
grid : numpy.array
Data points at which the desity will be estimated. It
has `m x p` dimensions, representing m points and p
variables.
Returns
-------
out : numpy.array
Density estimate. Has `m x 1` dimensions
"""
kde_skl = KernelDensity(**kwargs)
kde_skl.fit(data)
# score_samples() returns the log-likelihood of the samples
log_pdf = kde_skl.score_samples(grid)
return np.exp(log_pdf)
X = np.random.uniform(0,1,1000).reshape(-1,1)
X1 = np.linspace(0,1,100)[:,np.newaxis]
kde_sklearn(X,X1,kernel='tophat')
Out[43]:
array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
我希望向量为 1,因为积分的总和应为 1。
解决方案
问题不在于规范化,我可以从一个例子中看出。假设我运行以下代码,将 KDE 拟合到来自标准正态分布的样本:
import numpy as np
import sklearn.neighbors as sn
# Sample from a standard normal distribution
XX = np.random.randn(1000).reshape(-1, 1)
# Fit a KDE
kde_sklg = sn.KernelDensity()
kde_sklg.fit(XX)
# Get estimated densities
XX1 = np.linspace(-4.0, 4.0, 100)[:, np.newaxis]
gdens = np.exp(kde_sklg.score_samples(XX1))
然后我可以使用梯形规则估计 PDF 下的面积,如下所示:
my_area = 0.0
for i in range(1,gdens.shape[0]):
my_area += 0.5*(gdens[i] + gdens[i-1])*(XX1[i,0] - XX1[i-1,0])
我得到的估计面积 ( my_area
) 约为 0.996,非常接近 1。
问题是您的 KDE 没有处理统一 PDF 中发生在 0 和 1 处的跳跃,因此它会将它们涂抹得太多。KDE 对您的 PDF 的估计值下大约有一半的区域最终会落在那些模糊区域之下。如果您将您的值替换为X1
,X2 = np.linspace(-1,2,200)[:,np.newaxis]
您可以看到 KDE 在 [-1,0] 和 [1,2] 区间内的 PDF 估计部分中存在显着的密度。
推荐阅读
- python - 下拉菜单不会关闭使用 - Selenium 和 Python
- javascript - 访问开放图层要素对象不起作用
- typescript - 如何将一个对象绑定到一个组件到另一个组件?
- google-colaboratory - 在本地运行时使用 google-colab 时如何访问谷歌驱动器数据?
- shell - Shell 脚本中的 Grep 搜索
- c++ - 数组打印出垃圾值
- python - 在 PYOD 中计算基于直方图的异常值分数的异常分数
- sql - 为什么 T-SQL 中的一批只能有一个 create 语句?
- wpf - WPF - 移动画布
- python - 运行后 Django Docker 应用程序容器未在浏览器上打开