我想知道,给定两个正态分布与和
- 如何计算两个分布的重叠区域的百分比?
- 我想这个问题有一个特定的名称,您知道描述这个问题的任何特定名称吗?
- 您是否知道对此有任何实现(例如Java代码)?
我想知道,给定两个正态分布与和
Answers:
这通常也称为“重叠系数”(OVL)。对此进行谷歌搜索会给您带来很多成功。您可以在此处找到双正态情况的列线图。有用的论文可能是:
编辑
现在,您对我有了更多的兴趣,因此我继续创建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
。下图。
这由Bhattacharyya系数给出。对于其他分布,另请参见广义版本,即两个分布之间的Hellinger距离。
我不知道有任何库可以计算出来,但是考虑到马氏距离和方差矩阵的确定性的明确表述,实现不应该成为问题。
我不知道是否有明显的标准方法,但是:
首先,找到两个密度之间的交点。可以通过将两个密度相等来轻松实现,对于正态分布,这两个密度将导致x的二次方程式。
这可以通过基本演算来解决。
因此,您有零个,一个或两个交点。现在,这些交点将实线分为1、2或3部分,其中两个密度中的任何一个都是最低的。如果没有什么数学上的想法,只需尝试其中一个部分中的任何一点,找出哪一个是最低的。
您感兴趣的值现在是每个部分中最低密度曲线下的面积之和。现在可以从累积分布函数中找到该区域(只需减去“零件”两边的值即可。
为了后代,沃尔夫冈的解决方案对我不起作用-我在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
吗?
这是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;
}
我认为这样的事情可能是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 。
您只需要调整起点和终点以及间隔值的精确度即可,因为这只是一个数字解决方案。