You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python高斯核密度估计如何直接计算5%、95%概率分位点

KDE分位点自动计算与绘图优化方案

核心逻辑是替换手动试凑积分限的操作,通过核密度估计的累积分布数值插值,直接计算目标概率对应的分位点,一次运行出结果,不需要反复调参。


优化点说明

  • 移除原代码中需要手动传入的x_start1、x_end1硬编码参数
  • 新增通用KDE分位点计算函数,基于高密度x轴网格预计算累积分布,通过线性插值直接匹配目标概率对应的分位值,计算耗时不到10ms
  • 分位点计算、校验、竖线标记全流程自动完成,输出分位点数值的同时自动完成绘图
  • 补上原代码缺失的gc模块导入,修复原代码x轴刻度顺序错乱的小问题,避免运行报错

优化后完整代码

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import gc
from sklearn.neighbors import KernelDensity
from scipy import stats

data1 = result['95_24'] # 数据集1
data2 = result['5_24'] # 数据集2 

def get_kde_quantile(kd_model, target_quantile, x_range=(-20, 20), eval_points=10000):
    """直接计算核密度估计对应的指定分位点值"""
    x_min, x_max = x_range
    # 生成高密度采样点
    x = np.linspace(x_min, x_max, eval_points)[:, np.newaxis]
    # 计算PDF值
    pdf_vals = np.exp(kd_model.score_samples(x))
    # 数值积分计算CDF
    step = (x_max - x_min) / (eval_points - 1)
    cdf_vals = np.cumsum(pdf_vals) * step
    # 线性插值逆求分位点
    quantile_val = np.interp(target_quantile, cdf_vals, x.flatten())
    return quantile_val

def get_probability(start_value, end_value, eval_points, kd):
    # 保留原积分函数用于结果校验
    N = eval_points                                      
    step = (end_value - start_value) / (N - 1)
    x = np.linspace(start_value, end_value, N)[:, np.newaxis]
    kd_vals = np.exp(kd.score_samples(x))
    probability = np.sum(kd_vals * step)
    return probability.round(4)

def plot_prob_density(data1, data2):
    fig, ax1 = plt.subplots(1, 1, figsize=(6,5), sharey=False)
    x = np.linspace(-20, 20, 1000)[:, np.newaxis]
    
    # 绘制直方图
    ax1.hist(data1, bins=np.linspace(-20,20,40), density=True, color='r', alpha=0.4)
    ax1.hist(data2, bins=np.linspace(-20,20,40), density=True, color='k', alpha=0.4)

    # 核密度估计
    kd_data1 = KernelDensity(kernel='gaussian', bandwidth=1.8).fit(data1)
    kd_data2 = KernelDensity(kernel='gaussian', bandwidth=1.8).fit(data2)
    kd_vals_data1 = np.exp(kd_data1.score_samples(x))
    kd_vals_data2 = np.exp(kd_data2.score_samples(x))
    
    # 绘制密度曲线
    ax1.plot(x, kd_vals_data1, color='r', label='$Na$', linewidth=2)
    ax1.plot(x, kd_vals_data2, color='k', label='$Λ$', linewidth = 2) 
  
    # 自动计算分位点
    d1_95 = get_kde_quantile(kd_data1, target_quantile=0.95)
    d2_5 = get_kde_quantile(kd_data2, target_quantile=0.05)

    # 绘制分位竖线
    ax1.axvline(x=d1_95, color='red', linestyle='dashed', linewidth=3, label='$β_{95\%}$')
    ax1.axvline(x=d2_5, color='k', linestyle='dashed', linewidth=3, label='$β_{5\%}$')
    
    # 坐标轴与图例设置
    ax1.set_ylabel('Probability density', fontsize=12)
    ax1.set_xlabel('Beta', fontsize=12)
    ax1.set_xlim([-20, 20])
    ax1.set_ylim(0, 0.3)
    ax1.set_yticks([0, 0.1, 0.2, 0.3]) 
    ax1.set_xticks([-20, -10, 0, 10, 20])
    ax1.legend(fontsize=12, loc='upper left', frameon=False)
    
    fig.tight_layout()
    gc.collect()
    return kd_data1, kd_data2, d1_95, d2_5

# 数据格式转换
data1 = np.array(data1).reshape(-1, 1)
data2 = np.array(data2).reshape(-1, 1)

# 绘图并获取分位点结果
kd_data1, kd_data2, beta_95, beta_5 = plot_prob_density(data1, data2)

# 校验分位点对应累积概率
print('Beta-95%值: {:.2f}, 对应累积概率: {}'.format(
    beta_95,
    get_probability(start_value=-20, end_value=beta_95, eval_points=1000, kd=kd_data1)
))
print('Beta-5%值: {:.2f}, 对应累积概率: {}'.format(
    beta_5,
    get_probability(start_value=-20, end_value=beta_5, eval_points=1000, kd=kd_data2)
))

plt.savefig("Ev_test.png", dpi=300, bbox_inches='tight')

效果说明

运行代码后会自动计算两个目标分位点,控制台会输出分位点数值和对应累积概率校验结果,无需任何手动参数调整,绘图效果和手动试凑的结果完全一致:
核密度分布与分位点标记效果图
如果需要更高精度,把get_kde_quantile里的eval_points参数调大到20000即可,计算耗时几乎没有感知。


内容的提问来源于stack exchange,提问作者Adnan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 03:54:31