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

KL散度与JS散度自定义实现与Scipy内置函数结果差异排查

散度指标计算差异问题排查

核心根源:PDF生成函数致命错误

你的create_prob_dist函数存在逻辑错误:计算概率时,错误地将事件出现次数除以样本空间的大小(sample_space.size),而概率的正确定义是「事件出现次数 / 数据总事件数」,即应该除以len(data)。

错误代码片段:

sum_of_events = sample_space.size  # 错误:样本空间大小≠总事件数

修正后代码:

sum_of_events = len(data)  # 正确:总事件数为输入数据的长度

这个错误导致生成的p_pdf和q_pdf根本不是合法的概率分布(求和远大于1),后续所有散度计算都基于错误输入,这是所有结果差异的核心原因。


一、KL散度:自定义实现与Scipy函数的差异

修正PDF生成逻辑后,KL散度的差异原因如下:

  • 你的自定义KL_divergence和scipy.special.rel_entr:
    两者实现的是标准KL散度,公式为:
    $$D_{KL}(P||Q) = \sum_{i: P_i>0, Q_i>0} P_i \cdot \ln\left(\frac{P_i}{Q_i}\right)$$
    仅在$P_i$和$Q_i$均不为0时累加有效项,逻辑完全匹配,结果会一致。
  • scipy.special.kl_div:
    该函数实现的是$x \log(x/y) - x + y$,属于交叉熵的变形公式,并非标准KL散度。若需计算标准KL散度,必须使用rel_entr对元素结果求和。

二、JS散度:自定义实现与Scipy函数的差异

修正PDF后,JS散度的差异源于三种实现的定义不同:

  1. 第一个自定义JS_divergence:
    你实现的是对称KL散度(J散度),公式为$\frac{1}{2}(D_{KL}(P||Q)+D_{KL}(Q||P))$,这不是真正的JS散度,只是KL散度的对称版本,和Scipy的jensenshannon定义完全无关。

  2. 第二个自定义mod_JS_divergence:
    你实现的是标准JS散度,公式为$\frac{1}{2}(D_{KL}(P||M)+D_{KL}(Q||M))$(其中$M=(P+Q)/2$),逻辑正确,但和jensenshannon结果不同有两个原因:

    • Scipy的jensenshannon返回的是JS距离,即标准JS散度的平方根:$JS(P,Q)=\sqrt{JSD(P||Q)}$
    • jensenshannon默认使用底数为2的对数,而你的自定义函数用的是自然对数(math.log),若要匹配,需将自定义JS散度转换为底数2的结果后再取平方根。
  3. Scipy的jensenshannon:
    严格遵循JS距离的数学定义,返回标准JS散度的平方根,且默认使用底数2计算对数,这是和自定义实现差异的直接原因。


内容的提问来源于stack exchange,提问作者cs.lev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:09:50