两个正态分布的重叠区域的百分比


46

我想知道,给定两个正态分布与σ1个 μ1个σ2 μ2

  • 如何计算两个分布的重叠区域的百分比?
  • 我想这个问题有一个特定的名称,您知道描述这个问题的任何特定名称吗?
  • 您是否知道对此有任何实现(例如Java代码)?

2
重叠区域是什么意思?您是指两条密度曲线下方的面积吗?
Nick Sabbe 2011年

我的意思是两个区域的交集
Ali Salehi

4
FGFXGXdX

Answers:


41

这通常也称为“重叠系数”(OVL)。对此进行谷歌搜索会给您带来很多成功。您可以在此处找到双正态情况的列线图。有用的论文可能是:

  • 亨利·F·英曼;小埃德温·布拉德利(1989)。重叠系数是概率分布与两个法线密度重叠的点估计之间的一致性的度量。统计学中的通信-理论与方法,18(10),3851-3874。(链接

编辑

现在,您对我有了更多的兴趣,因此我继续创建R代码来计算此值(这是一个简单的集成)。我绘制了两个分布的图,包括重叠区域的阴影:

min.f1f2 <- function(x, mu1, mu2, sd1, sd2) {
    f1 <- dnorm(x, mean=mu1, sd=sd1)
    f2 <- dnorm(x, mean=mu2, sd=sd2)
    pmin(f1, f2)
}

mu1 <- 2;    sd1 <- 2
mu2 <- 1;    sd2 <- 1

xs <- seq(min(mu1 - 3*sd1, mu2 - 3*sd2), max(mu1 + 3*sd1, mu2 + 3*sd2), .01)
f1 <- dnorm(xs, mean=mu1, sd=sd1)
f2 <- dnorm(xs, mean=mu2, sd=sd2)

plot(xs, f1, type="l", ylim=c(0, max(f1,f2)), ylab="density")
lines(xs, f2, lty="dotted")
ys <- min.f1f2(xs, mu1=mu1, mu2=mu2, sd1=sd1, sd2=sd2)
xs <- c(xs, xs[1])
ys <- c(ys, ys[1])
polygon(xs, ys, col="gray")

### only works for sd1 = sd2
SMD <- (mu1-mu2)/sd1
2 * pnorm(-abs(SMD)/2)

### this works in general
integrate(min.f1f2, -Inf, Inf, mu1=mu1, mu2=mu2, sd1=sd1, sd2=sd2)

对于此示例,结果为:0.6099324绝对错误< 1e-04。下图。

例


10
(+1)谷歌搜索至少出现了三个不同的定义(松下,森下和韦茨曼)。您的实现是韦茨曼的。
ub

1
0.60993 24是0.60993 43398 78944 33895 ...的近似值。
ub

10

这由Bhattacharyya系数给出。对于其他分布,另请参见广义版本,即两个分布之间的Hellinger距离。

我不知道有任何库可以计算出来,但是考虑到马氏距离和方差矩阵的确定性的明确表述,实现不应该成为问题。


3
Bhattacharyya系数是对重叠的量度,但并不相同,是吗?
斯特凡洛朗

7

我不知道是否有明显的标准方法,但是:

首先,找到两个密度之间的交点。可以通过将两个密度相等来轻松实现,对于正态分布,这两个密度将导致x的二次方程式。

X-μ222σ22-X-μ1个22σ1个2=日志σ1个σ2

这可以通过基本演算来解决。

因此,您有零个,一个或两个交点。现在,这些交点将实线分为1、2或3部分,其中两个密度中的任何一个都是最低的。如果没有什么数学上的想法,只需尝试其中一个部分中的任何一点,找出哪一个是最低的。

您感兴趣的值现在是每个部分中最低密度曲线下的面积之和。现在可以从累积分布函数中找到该区域(只需减去“零件”两边的值即可。


4
σ1个σ2μ1个μ2σ1个=σ2

2
@whuber你能把它变成一个完整的答案吗?也许尼克可以编辑他的。
Aleksandr Dubinsky

σ1个σ2μ1个μ2

@Stéphane我认为SD确定顺序是正确的:SD较小的密度最终将在正方向和负方向上都具有较小的尾部,因此在零与其他位置之间的值将较大。
ub

@whuber是的,的确很容易看出,SD的阶数决定了Nick导出的多项式的二阶系数的符号。
斯蒂芬·洛朗

1

为了后代,沃尔夫冈的解决方案对我不起作用-我在integrate函数中遇到错误。因此,我将其与Nick Staubbe的答案结合起来以开发以下小功能。与使用数值积分相比,应该更快,更可靠。

get_overlap_coef <- function(mu1, mu2, sd1, sd2){
  xs  <- seq(min(mu1 - 4*sd1, mu2 - 4*sd2), 
             max(mu1 + 4*sd1, mu2 + 4*sd2), 
             length.out = 500)
  f1  <- dnorm(xs, mean=mu1, sd=sd1)
  f2  <- dnorm(xs, mean=mu2, sd=sd2)
  int <- xs[which.max(pmin(f1, f2))]
  l   <- pnorm(int, mu1, sd1, lower.tail = mu1>mu2)
  r   <- pnorm(int, mu2, sd2, lower.tail = mu1<mu2)
  l+r
}

它不应该回来(l+r)/2吗?
RSHAP

0

这是Java版本的Apache Commons Mathematics Library

import org.apache.commons.math3.distribution.NormalDistribution;

public static double overlapArea(double mean1, double sd1, double mean2, double sd2) {

    NormalDistribution normalDistribution1 = new NormalDistribution(mean1, sd1);
    NormalDistribution normalDistribution2 = new NormalDistribution(mean2, sd2);

    double min = Math.min(mean1 - 6 * sd1, mean2 - 6 * sd2);
    double max = Math.max(mean1 + 6 * sd1, mean2 + 6 * sd2);
    double range = max - min;

    int resolution = (int) (range/Math.min(sd1, sd2));

    double partwidth = range / resolution;

    double intersectionArea = 0;

    int begin = (int)((Math.max(mean1 - 6 * sd1, mean2 - 6 * sd2)-min)/partwidth);
    int end = (int)((Math.min(mean1 + 6 * sd1, mean2 + 6 * sd2)-min)/partwidth);

    /// Divide the range into N partitions
    for (int ii = begin; ii < end; ii++) {

        double partMin = partwidth * ii;
        double partMax = partwidth * (ii + 1);

        double areaOfDist1 = normalDistribution1.probability(partMin, partMax);
        double areaOfDist2 = normalDistribution2.probability(partMin, partMax);

        intersectionArea += Math.min(areaOfDist1, areaOfDist2);
    }

    return intersectionArea;

}

0

我认为这样的事情可能是MATLAB中的解决方案:

[overlap] = calc_overlap_twonormal(2,2,0,1,-20,20,0.01)

% numerical integral of the overlapping area of two normal distributions:
% s1,s2...sigma of the normal distributions 1 and 2
% mu1,mu2...center of the normal distributions 1 and 2
% xstart,xend,xinterval...defines start, end and interval width
% example: [overlap] = calc_overlap_twonormal(2,2,0,1,-10,10,0.01)

function [overlap2] = calc_overlap_twonormal(s1,s2,mu1,mu2,xstart,xend,xinterval)

clf
x_range=xstart:xinterval:xend;
plot(x_range,[normpdf(x_range,mu1,s1)' normpdf(x_range,mu2,s2)']);
hold on
area(x_range,min([normpdf(x_range,mu1,s1)' normpdf(x_range,mu2,s2)']'));
overlap=cumtrapz(x_range,min([normpdf(x_range,mu1,s1)' normpdf(x_range,mu2,s2)']'));
overlap2 = overlap(end);

[overlap] = calc_overlap_twonormal(2,2,0,1,-10,10,0.01) 

至少我可以在此pdf中复制图1下方给出的值0.8026 。

您只需要调整起点和终点以及间隔值的精确度即可,因为这只是一个数字解决方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.