- 昨日の記事では酔歩を使って平滑化する話
- そのとき、観測点の密度が違うと平滑化後の値が密度推定にはならないことを書いた
- それを修正するために、ドロネー図的に(多次元に一般化しやすくするため)各点に与えうる密度っぽい値を計算することにしたこちらにドロネー図やら、ドロネー図的体積計算やらを書いた
- もちろん、それを使うと、凸凹になるので、密度っぽい値にした後で酔歩平滑化を入れることにする
- まずは、1次元分布について、いろいろな例を見てみよう
- 単純な正規分布。図は、青が「真の分布」、黒はRのdensity()によるSJ-ste幅による推定密度、赤はドロネー体積を使わず、ただの酔歩平滑化による値、緑はドロネー体積による補正後の酔歩平滑化による値
- どれも同じような結果
my.simplex.volume <- function(V,factorial=FALSE){
n <- length(V[1,])
K <- matrix(V[1:n,],ncol=n)
K. <- t(K)-V[n+1,]
if(factorial){
return(det(K.)/factorial(n))
}else{
return(det(K.))
}
}
my.delaunay.vol <- function(a,X){
tmp <- matrix(X[a,],ncol=length(X[1,]))
my.simplex.volume(tmp)
}
my.delaunay.rw.density <- function(X,n=1000,r=0.1){
delaunay.X <- delaunayn(X)
spx.vol <- apply(delaunay.X,1,my.delaunay.vol,X)
Vol <- rep(0,length(X[,1]))
for(i in 1:length(Vol)){
tmp <- (delaunay.X==i)
tmp.2 <- apply(tmp,1,any)
Vol[i] <- sum(abs(spx.vol[which(tmp.2)]))
}
Y.d <- 1/Vol
RW.Mx.d <- my.rw.density.mx(X,Y.d,n,r)
Y.post <- RW.Mx.d %*% Y.d
return(list(Vol=Vol,Y.d=Y.d,Y.post=Y.post,M = RW.Mx.d))
}
means <- c(0,0)
sds <- c(1,1)
ratio <- c(0.4,0.6)
N.pt <- 50
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
- 2峰性にしてみる
- density()が2峰の谷をうまく拾っているようだ
means <- c(0,3)
sds <- c(1,1)
ratio <- c(0.4,0.6)
N.pt <- 200
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
- もっと離してみる
- 「離す」と酔歩平滑化法では、離れた2つの峰の間の酔歩拡散が起きにくくなるので、ドロネー的密度補正をしないと(赤)、山の高さが2峰で変わらない問題が起きるが、ドロネー的密度補正でそれが防げていることがわかる
means <- c(0,10)
sds <- c(1,1)
ratio <- c(0.4,0.6)
N.pt <- 200
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
- 離れた2ピークの分散に差が出てくると分布推定は難しくなってくる
means <- c(0,50)
sds <- c(1,8)
ratio <- c(0.2,0.8)
N.pt <- 500
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
means <- c(0,2)
sds <- c(1,8)
ratio <- c(0.3,0.7)
N.pt <- 500
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)