当前位置:   article > 正文

核密度估计-KDE_kde核密度估计

kde核密度估计

核密度估计(Kernel Density Estimation)

密度评估器是一种利用D维数据集生成D维概率分布估计的算法,GMM使用不同的高斯分布的加权汇总来表示概率分布估计。
核密度估计算法将高斯混合理念扩展到了逻辑极限,它通过对每一个点生成高斯分布的混合成分,获得本实质上是无参数的密度评估器。

核密度估计的自由参数是核类型和核带宽,前者指定每个点核密度分布的形状,后者指定每个点核的大小。

一维数据的密度估计——直方图,是一个简单的密度评估器,直方图将数据分成若干区间,统计落入每个区间内的点的数量,然后用直观的方式将结果可视化。

核密度估计示例

核密度估计的自由参数是核类型(kernel)参数,他可以指定每个点核密度分布的形状。

核带宽(kernel bandwidth)参数控制每个点的核的大小

核密度估计算法在sklearn.neighbors.KernelDensity评估器中实现,借助六个核中的任意一个核、二三十个距离量度就可以处理具有多个维度的KDE。

由于KDE计算量非常大,因此Scikit-Learn评估器底层使用了一种基于树的算法,可以利用atol(绝对容错)和rtol(相对容错)参数来平衡计算时间与准确性,可以用Scikit-Learn的标准交叉检验工具来确定自由参数核带宽。

以下代码生成一组高斯分布的随机数据,分别绘制其直方图与KDE图,查看效果;

  1. import numpy as np
  2. from matplotlib import pyplot as plt
  3. from sklearn.model_selection import GridSearchCV, LeaveOneOut
  4. from sklearn.neighbors import KernelDensity
  5. x_train = np.hstack((np.random.normal(2, 1.66, 200), np.random.normal(8, 2.33, 200))) # 两个高斯分布组合到一起
  6. bandwidth = 1.0
  7. model = KernelDensity(bandwidth=bandwidth, kernel='gaussian')
  8. model.fit(x_train[:, np.newaxis])
  9. x_range = np.linspace(x_train.min() - 1, x_train.max() + 1, 500)
  10. x_log_prob = model.score_samples(x_range[:, np.newaxis]) # 这个东西返回概率的对数
  11. x_prob = np.exp(x_log_prob)
  12. plt.figure(figsize=(10, 10))
  13. r = plt.hist(
  14. x=x_train,
  15. bins=50,
  16. density=True,
  17. histtype='stepfilled',
  18. color='red',
  19. alpha=0.5,
  20. label='histogram',
  21. )
  22. plt.fill_between(
  23. x=x_range,
  24. y1=x_prob,
  25. y2=0,
  26. color='green',
  27. alpha=0.5,
  28. label='KDE',
  29. )
  30. plt.plot(x_range, x_prob, color='gray')
  31. plt.vlines(x=2, ymin=0, ymax=r[0].max() + 0.01, color='k', linestyle='--', alpha=0.7) # 分布中心
  32. plt.vlines(x=8, ymin=0, ymax=r[0].max() + 0.01, color='k', linestyle='--', alpha=0.7) # 分布中心
  33. plt.ylim(0, r[0].max() + 0.011)
  34. plt.legend(loc='upper right')
  35. plt.title('histogram and kde')
  36. plt.show()

结果:

使用交叉检验确定带宽

kernel参数指定需要用到的核函数,来适应不同的需求;

在使用核密度估计时,如果带宽设置过小,会出现过拟合的现象,如果带宽设置过大,会出现欠拟合的现象,因此需要确定好最佳的带宽;
sklearn中的KernelDensity类支持使用GridSearchCV来寻找最佳参数,以下是一个示例:

  1. def get_suit_bandwidth(x_train):
  2. grid = GridSearchCV(
  3. estimator=KernelDensity(kernel='gaussian'),
  4. param_grid={'bandwidth': 10 ** np.linspace(-1, 1, 100)},
  5. cv=LeaveOneOut(),
  6. )
  7. grid.fit(x_train[:, np.newaxis])
  8. print(f'最佳带宽:{grid.best_params_["bandwidth"]}')
  9. return grid.best_params_["bandwidth"]
  10. bandwidth = get_suit_bandwidth(x_train)

 bandwidth 大约0.7左右,再次运行上述代码:

 可以看出宽度变窄后你和效果更完美一些。

用二维数据也试验了一下,也不错:


 

参考:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/575352
推荐阅读
相关标签
  

闽ICP备14008679号