双变量正态分布的离散近似
Discrete approximation to a bivariate normal distribution
我想对二元正态分布进行离散近似。也就是说,我想计算一个矩阵,其中每个条目都是落入下图小方块之一的概率。
这是我目前所做的。
library(mvtnorm)
library(graphics)
euclide = function(x,y){sqrt(x^2+y^2)}
maxdist = 40
sigma = diag(2)
m = matrix(0,ncol=maxdist*2 + 1, nrow=maxdist*2 + 1)
for (row in -maxdist:maxdist){
for (col in -maxdist:maxdist){
if ( euclide(abs(row), abs(col)) < maxdist ){
lower = c(row-0.5, col-0.5)
upper = c(row+0.5, col+0.5)
p = pmvnorm(lower = lower , upper = upper, mean = c(0,0), sigma = sigma)
} else {
p = 0
}
m[row + maxdist + 1,col + maxdist + 1] = p
}
}
m = m[rowSums(m)!=0,colSums(m)!=0]
contour(m, levels = exp(-20:0), xlim=c(0.3,0.7), ylim=c(0.3,0.7))
它工作正常。虽然它很慢(对于大 maxdist
),但我希望改进它的计算时间。但这不是我的主要问题...
主要问题是,使用我的方法,我无法更改靠近中心的小方块的数量以更好地接近均值。我只能在周围添加正方形。换句话说,我希望能够设置双变量正态分布的两个轴的方差。
我不是 R 人,但我确定正态分布有 CDF 函数。如果你想要的是字面上描述落入每个正方形的概率的矩阵,我们可以使用这个 CDF 函数来得到答案。由于 2D 正态分布具有独立的边缘分布,这里的问题只是针对轴位置 [x_left、x_right] 和 [y_left、[y_left、y_right]:
- 一维正态随机变量在区间 [x_left, x_right] 中的概率是多少?
- 另一个独立的一维正态随机变量在区间 [y_left, y_right] 中的概率是多少?
由于两者是独立的,所以正方形的完整概率是:
P = (CDF(x_right) - CDF(x_left))*(CDF(y_right) - CDF(y_left))
这是一个准确的答案,所以计算时间应该不是问题!
编辑:我还应该说,您可以选择一个网格,每个轴上的刻度都接近于零,以获得您想要的分辨率。以上每个方块的概率公式仍然成立。
这是一个简单的实现。就像@DanielJohnson 说的那样,您可以只使用 cdf 形式的单变量法线,但它应该与使用 pmvnorm
相同,如下所示。使用 pnorm
的版本要快得多。
## Choose the matrix dimensions
yticks <- xticks <- seq(-3, 3, length=100)
side <- diff(yticks[1:2]) # side length of squares
sigma <- diag(2) # standard devs. for f2
mu <- c(0,0) # means
## Using pnorm
f <- Vectorize(function(x, y, side, mu1, mu2, s1, s2)
diff(pnorm(x+c(-1,1)*side/2, mu1, s1)) * diff(pnorm(y+c(-1,1)*side/2, mu2, s2)),
vec=c("x", "y"))
## Using pmvnorm
f2 <- Vectorize(function(x, y, side, mu, sigma)
pmvnorm(lower=c(x,y)-side/2, upper=c(x,y)+side/2, mean=mu, sigma=sigma),
vec=c("x", "y"))
## get prob. of squares, mu are means, s are standards devs.
mat <- outer(xticks, yticks, f, side=side, mu1=0, mu2=0, s1=1,s2=1)
mat2 <- outer(xticks, yticks, f2, side=side, mu=mu, sigma=sigma)
## test equality
all(abs(mat2-mat) < 1e-11) # TRUE
all.equal(mat2, mat) # TRUE
## See how it looks
library(lattice)
persp(mat, col="lightblue", theta=35, phi=35, shade=0.1)
我想对二元正态分布进行离散近似。也就是说,我想计算一个矩阵,其中每个条目都是落入下图小方块之一的概率。
这是我目前所做的。
library(mvtnorm)
library(graphics)
euclide = function(x,y){sqrt(x^2+y^2)}
maxdist = 40
sigma = diag(2)
m = matrix(0,ncol=maxdist*2 + 1, nrow=maxdist*2 + 1)
for (row in -maxdist:maxdist){
for (col in -maxdist:maxdist){
if ( euclide(abs(row), abs(col)) < maxdist ){
lower = c(row-0.5, col-0.5)
upper = c(row+0.5, col+0.5)
p = pmvnorm(lower = lower , upper = upper, mean = c(0,0), sigma = sigma)
} else {
p = 0
}
m[row + maxdist + 1,col + maxdist + 1] = p
}
}
m = m[rowSums(m)!=0,colSums(m)!=0]
contour(m, levels = exp(-20:0), xlim=c(0.3,0.7), ylim=c(0.3,0.7))
它工作正常。虽然它很慢(对于大 maxdist
),但我希望改进它的计算时间。但这不是我的主要问题...
主要问题是,使用我的方法,我无法更改靠近中心的小方块的数量以更好地接近均值。我只能在周围添加正方形。换句话说,我希望能够设置双变量正态分布的两个轴的方差。
我不是 R 人,但我确定正态分布有 CDF 函数。如果你想要的是字面上描述落入每个正方形的概率的矩阵,我们可以使用这个 CDF 函数来得到答案。由于 2D 正态分布具有独立的边缘分布,这里的问题只是针对轴位置 [x_left、x_right] 和 [y_left、[y_left、y_right]:
- 一维正态随机变量在区间 [x_left, x_right] 中的概率是多少?
- 另一个独立的一维正态随机变量在区间 [y_left, y_right] 中的概率是多少?
由于两者是独立的,所以正方形的完整概率是:
P = (CDF(x_right) - CDF(x_left))*(CDF(y_right) - CDF(y_left))
这是一个准确的答案,所以计算时间应该不是问题!
编辑:我还应该说,您可以选择一个网格,每个轴上的刻度都接近于零,以获得您想要的分辨率。以上每个方块的概率公式仍然成立。
这是一个简单的实现。就像@DanielJohnson 说的那样,您可以只使用 cdf 形式的单变量法线,但它应该与使用 pmvnorm
相同,如下所示。使用 pnorm
的版本要快得多。
## Choose the matrix dimensions
yticks <- xticks <- seq(-3, 3, length=100)
side <- diff(yticks[1:2]) # side length of squares
sigma <- diag(2) # standard devs. for f2
mu <- c(0,0) # means
## Using pnorm
f <- Vectorize(function(x, y, side, mu1, mu2, s1, s2)
diff(pnorm(x+c(-1,1)*side/2, mu1, s1)) * diff(pnorm(y+c(-1,1)*side/2, mu2, s2)),
vec=c("x", "y"))
## Using pmvnorm
f2 <- Vectorize(function(x, y, side, mu, sigma)
pmvnorm(lower=c(x,y)-side/2, upper=c(x,y)+side/2, mean=mu, sigma=sigma),
vec=c("x", "y"))
## get prob. of squares, mu are means, s are standards devs.
mat <- outer(xticks, yticks, f, side=side, mu1=0, mu2=0, s1=1,s2=1)
mat2 <- outer(xticks, yticks, f2, side=side, mu=mu, sigma=sigma)
## test equality
all(abs(mat2-mat) < 1e-11) # TRUE
all.equal(mat2, mat) # TRUE
## See how it looks
library(lattice)
persp(mat, col="lightblue", theta=35, phi=35, shade=0.1)