Python是否存在带权重的双变量插补法带宽选择核密度估计器?
多变量加权核密度估计Python实现方案
方案1:statsmodels 内置KDE实现
- 完全匹配需求:原生支持样本加权、内置插补法(正态参考规则)自动计算带宽、支持多变量输入、无需交叉验证,双变量场景下处理1e6量级数据速度达标。
- 代码示例:
import numpy as np from statsmodels.nonparametric.kernel_density import KDEMultivariateWeighted # 生成1e6量级带权双变量测试数据 n = 10**6 data = np.column_stack([np.random.normal(0, 1, n), np.random.normal(0, 1, n)]) weights = np.random.uniform(0, 1, n) # 替换为你的实际权重 # 初始化KDE:var_type='cc'表示两个变量均为连续型,bw='normal_reference'为插补法自动算带宽 kde = KDEMultivariateWeighted(data=data, var_type='cc', bw='normal_reference', weights=weights) # 计算指定点的密度值 test_points = np.array([[0, 0], [1, 1]]) density_values = kde.pdf(test_points)
- 性能优化提示:如果需要批量计算网格上的密度,直接传入整个网格数组调用pdf即可,接口已做批量查询优化。
方案2:scikit-learn KDE + 手动实现插补带宽
如果对性能要求更高,可以用scikit-learn的KernelDensity,新版本已支持样本权重参数,插补法带宽可通过双变量正态参考规则手动计算,整体速度比statsmodels快3~5倍:
- 代码示例:
import numpy as np from sklearn.neighbors import KernelDensity def bivariate_plugin_bw(data): # 双变量Silverman插补法带宽计算 n = data.shape[0] dim = data.shape[1] std_arr = np.std(data, axis=0) return std_arr * (n * (dim + 2) / 4) ** (-1 / (dim + 4)) # 调用示例 n = 10**6 data = np.column_stack([np.random.normal(0, 1, n), np.random.normal(0, 1, n)]) weights = np.random.uniform(0, 1, n) bw = bivariate_plugin_bw(data) # 初始化KDE,可根据需求切换核函数 kde = KernelDensity(kernel='gaussian', bandwidth=bw.mean()) kde.fit(data, sample_weight=weights) # 计算密度(返回值为对数密度,用np.exp转换为原始密度) test_points = np.array([[0, 0], [1, 1]]) log_density = kde.score_samples(test_points) density_values = np.exp(log_density)
方案3:rpy2调用R ks包(可选)
如果需要完全对齐R ks包的插补带宽计算结果,可通过rpy2在Python中直接调用对应函数,无需额外学习R语法,仅需简单的接口封装即可实现调用。
内容的提问来源于stack exchange,提问作者Peanutlex
相关产品推荐
相关产品推荐

