回答:
これは「オーバーラップ係数」(OVL)とも呼ばれます。これをグーグルで検索すると、多くのヒットが得られます。ここで双正規の場合のノモグラムを見つけることができます。役に立つ論文は次のとおりです。
編集
今、あなたはこれにもっと興味を持ったので、先に進み、これを計算するためのRコードを作成しました(単純な統合です)。重複領域の陰影を含む2つの分布のプロットを投げました。
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
なります:with absolute error < 1e-04
。下の図。
これはBhattacharyya係数によって与えられます。他の分布については、一般化バージョンである2つの分布間のHellinger距離も参照してください。
これを計算するライブラリは知りませんが、マハラノビス距離と分散行列式に関する明示的な定式化を考えると、実装は問題になりません。
これを行うための明白な標準的な方法があるかどうかはわかりませんが、:
まず、2つの密度の交点を見つけます。これは、両方の密度を等しくすることで簡単に実現できます。これは、正規分布の場合、xの2次方程式になるはずです。
何かに近い:
これは基本的な計算で解決できます。
したがって、0、1、または2つの交点があります。現在、これらの交点は実際の線を1、2、または3つの部分に分割します。2つの密度のいずれかが最も低い密度です。これ以上数学的なことが思いつかない場合は、いずれかの部分内の任意のポイントを試して、どれが最も低いかを見つけてください。
関心のある値は、各部分の最低密度曲線の下の面積の合計です。この領域は、累積分布関数から見つけることができます(「パーツ」の両端の値を減算するだけです)。
後世のために、ウルフギャングのソリューションは私にとってはうまくいきませんでした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を再現できました。
これは単なる数値解であるため、開始値と終了値、間隔値を正確に調整する必要があります。