- こちらで数学知らずの乳幼児による度数分布平滑化手法というのをやってみた
- 多次元空間の場合も、直交軸に関する2階の差分を評価することで、いい感じの平滑化を取り出すことができるようだった
- 今度は、点の数がものすごく多いとき、どうするかと言う話
- 生物のように、発熱もしないエネルギー効率がものすごく優秀な光学センサーと情報処理系を持っていて、超高度な並列処理回路になっていれば問題ないが、お手軽PCでそれをまねようとすると、空間の広さ(度数をとる単位超立方体の数)が問題になる
- 度数分布を考えるとき、すべての超立方体についてそこに存在する点の数を知ろうとするのが普通だろうが、空間が広くなると、結構粗い区画(1軸50分割とか)でも、超立方体の数はになり、nが10とかになるとやりきれない数になる。に比べれば、大量のシグナル(など)はかわいいもので、シグナル件数を相手にする方がまだましになってくる。それがたとえ、というように、全シグナルの間のペアワイズな評価を必要とするとしても、同程度の厄介さかげんになってくる。空間の区画数を相手にするか、シグナル点を相手にするかは、場合によるが、どちらもできる方がよいだろう
vision.scale <- function(x,scl){
(x-min(x))/(max(x)-min(x)) * scl + (1-scl)/2
}
vision.standard <- function(x,scl = 0.9){
rg <- apply(x,2,range)
tmp <- apply(x,2,vision.scale, scl)
return(list(st.x = tmp,rg=rg))
}
round.coords <- function(x,n.cell=50){
d <- length(x[1,])
matrix(floor(x * n.cell),ncol=d)
}
library(igraph)
cluster.g <- function(d){
sign.d <- sign(-(sign(d)-1))
g <- graph.adjacency(sign.d)
clusters(g)
}
unique.dist <- function(d){
cl <- cluster.g(d)
unique.id <- which(!duplicated(cl[[1]]))
return(list(cl=cl,unique.id=unique.id))
}
one.direction.2 <- function(unique.d,tmp.x){
d <- length(tmp.x[1,])
up.ud <- unique.d
up.ud[upper.tri(up.ud)] <- 0
ones <- matrix(which(up.ud==1,arr.ind=TRUE),ncol=2)
twos <- matrix(which(up.ud==2,arr.ind=TRUE),ncol=2)
diff.ones <- matrix(tmp.x[ones[,1],],ncol=d) - matrix(tmp.x[ones[,2],],ncol=d)
ones.axis <- apply(abs(diff.ones),1,which.max)
ones.dir <- apply(diff.ones,1,sum)
ones.directed <- ones
ones.directed[which(ones.dir==-1),1] <- ones[which(ones.dir==-1),2]
ones.directed[which(ones.dir==-1),2] <- ones[which(ones.dir==-1),1]
trees <- list()
for(i in 1:d){
tmp.dir <- which(ones.axis==i)
if(length(tmp.dir)>0){
trees[[i]] <- tandem.one(matrix(ones.directed[tmp.dir,],ncol=2))
}
}
diff.twos <- matrix(tmp.x[twos[,1],],ncol=d) - matrix(tmp.x[twos[,2],],ncol=d)
sign.diff.twos <- sign(abs(diff.twos))
twos.line.id <- which(apply(sign.diff.twos,1,sum)==1)
if(length(twos.line.id)>0){
twos.line <- twos[twos.line.id,]
diff.twos.line <- diff.twos[twos.line.id,]
twos.axis <- apply(abs(diff.twos.line),1,which.max)
twos.dir <- sign(apply(diff.twos.line,1,sum))
twos.line.directed <- twos.line
twos.line.directed[which(twos.dir==-1),1] <- twos.line[which(twos.dir==-1),2]
twos.line.directed[which(twos.dir==-1),2] <- twos.line[which(twos.dir==-1),1]
for(i in 1:d){
tmp.dir <- which(twos.axis==i)
if(length(tmp.dir)>0){
trees[[i]] <- tandem.two(trees[[i]],matrix(twos.line.directed[tmp.dir,],ncol=2))
}
}
}
return(list(trees))
}
one.direction <- function(unique.id,unique.d,tmp.x){
d <- length(tmp.x[1,])
up.ud <- unique.d
up.ud[upper.tri(up.ud)] <- 0
ones <- matrix(which(up.ud==1,arr.ind=TRUE),ncol=2)
twos <- matrix(which(up.ud==2,arr.ind=TRUE),ncol=2)
diff.ones <- matrix(tmp.x[ones[,1],],ncol=d) - matrix(tmp.x[ones[,2],],ncol=d)
ones.axis <- apply(abs(diff.ones),1,which.max)
ones.dir <- apply(diff.ones,1,sum)
ones.directed <- ones
ones.directed[which(ones.dir==-1),1] <- ones[which(ones.dir==-1),2]
ones.directed[which(ones.dir==-1),2] <- ones[which(ones.dir==-1),1]
trees <- list()
for(i in 1:d){
tmp.dir <- which(ones.axis==i)
if(length(tmp.dir)>0){
trees[[i]] <- tandem.one(matrix(ones.directed[tmp.dir,],ncol=2))
}
}
diff.twos <- matrix(tmp.x[twos[,1],],ncol=d) - matrix(tmp.x[twos[,2],],ncol=d)
sign.diff.twos <- sign(abs(diff.twos))
twos.line.id <- which(apply(sign.diff.twos,1,sum)==1)
if(length(twos.line.id)>0){
twos.line <- twos[twos.line.id,]
diff.twos.line <- diff.twos[twos.line.id,]
twos.axis <- apply(abs(diff.twos.line),1,which.max)
twos.dir <- sign(apply(diff.twos.line,1,sum))
twos.line.directed <- twos.line
twos.line.directed[which(twos.dir==-1),1] <- twos.line[which(twos.dir==-1),2]
twos.line.directed[which(twos.dir==-1),2] <- twos.line[which(twos.dir==-1),1]
for(i in 1:d){
tmp.dir <- which(twos.axis==i)
if(length(tmp.dir)>0){
trees[[i]] <- tandem.two(trees[[i]],matrix(twos.line.directed[tmp.dir,],ncol=2))
}
}
}
return(list(trees))
}
omit.twos <- function(ones,twos){
nec <- unnec <- rep(0,length(twos[,1]))
for(i in 1:length(twos[,1])){
if(sum(which(ones[,1] == twos[i,1])) * sum(which(ones[,2] == twos[i,2]))){
unnec[i] <- 1
}else{
nec[i] <- 1
}
}
return(list(nec=nec,unnec=unnec))
}
tandem.one <- function(m){
trees <- list(m[1,])
st.end <- matrix(m[1,],nrow=1)
if(length(m[,1])>1){
for(i in 2:length(m[,1])){
tailer <- which(st.end[,2]==m[i,1])
header <- which(st.end[,1]==m[i,2])
if(length(tailer)>0){
if(length(header)>0){
trees[[tailer]] <- c(trees[[tailer]],trees[[header]])
trees[[header]] <- c()
st.end[tailer,2] <- st.end[header,2]
st.end <- matrix(st.end[-header,],ncol=2)
}else{
trees[[tailer]] <- c(trees[[tailer]],m[i,2])
st.end[tailer,2] <- m[i,2]
}
}else{
if (length(header)>0){
trees[[header]] <- c(m[i,1],trees[[header]])
st.end[header,1] <- m[i,1]
}else{
trees[[length(st.end[,1])+1]] <- m[i,]
st.end <- rbind(st.end,matrix(m[i,],nrow=1))
}
}
}
}
return(list(trees=trees,st.end=st.end))
}
tandem.two <- function(trees,m){
tr <- trees$trees
st.end <- trees$st.end
for(i in 1:length(m[,1])){
tailer <- which(st.end[,2]==m[i,1])
header <- which(st.end[,1]==m[i,2])
if(length(tailer)>0){
if(length(header)>0){
tr[[tailer]] <- c(tr[[tailer]],0,tr[[header]])
tr[[header]] <- c()
st.end[tailer,2] <- st.end[header,2]
st.end <- matrix(st.end[-header,],ncol=2)
}else{
tr[[tailer]] <- c(tr[[tailer]],0,m[i,2])
st.end[tailer,2] <- m[i,2]
}
}else{
if(length(header)>0){
tr[[header]] <- c(m[i,1],0,tr[[header]])
st.end[header,1] <- m[i,1]
}else{
if(length(which(unlist(tr)==m[i,1]))>0 & length(which(unlist(tr)==m[i,2]))>0){
}else{
tr[[length(st.end[,1])+1]] <- c(m[i,1],0,m[i,2])
st.end <- rbind(st.end,matrix(m[i,],nrow=1))
}
}
}
}
return(list(trees=tr,st.end=st.end))
}
d <- 3
x1 <- c(rnorm(1000,10),rnorm(500,80,20),runif(1500,30,50))
x2 <- c(rnorm(500,5),rnorm(1500,20,10),runif(1000,4,50))
x3 <- c(rnorm(1500,40),rnorm(500,10,100),runif(1000,40,50))
x <- cbind(x1,x2,x3)
x.st <- vision.standard(x,scl=0.7)
x <- x.st$st.x
n <- length(x[,1])
library(rgl)
Ls <- seq(from=min(dist(x,method="manhattan")),to=1,length=10)
Ls <- Ls[-1]
Ls <- Ls[-1]
round.x <- list()
dist.out <- dist.m <- cl <- uni.d <- trees <- list()
par(ask=FALSE)
for(i in 1:length(Ls)){
round.x[[i]] <- round.coords(x,1/Ls[i])
dist.out[[i]] <- dist(round.x[[i]],method="manhattan")
tmp <- unique.dist(dist.out[[i]])
cl[[i]] <- tmp$cl
unique.id <- tmp$unique.id
unique.d <- as.matrix(dist.out[[i]])[unique.id,unique.id]
tmp.x <- matrix(round.x[[i]][unique.id,],ncol=d)
trees[[i]] <- one.direction(unique.id,unique.d,tmp.x)
}
vision.scale <- function(x,scl){
(x-min(x))/(max(x)-min(x)) * scl + (1-scl)/2
}
vision.standard <- function(x,scl = 0.9){
rg <- apply(x,2,range)
tmp <- apply(x,2,vision.scale, scl)
return(list(st.x = tmp,rg=rg))
}
round.coords <- function(x,n.cell=50){
d <- length(x[1,])
matrix(floor(x * n.cell),ncol=d)
}
d <- 3
x1 <- c(rnorm(1000,10),rnorm(500,80,20),runif(1500,30,50))
x2 <- c(rnorm(500,5),rnorm(1500,20,10),runif(1000,4,50))
x3 <- c(rnorm(1500,40),rnorm(500,10,100),runif(1000,40,50))
x <- cbind(x1,x2,x3)
x.st <- vision.standard(x,scl=0.7)
x <- x.st$st.x
n <- length(x[,1])
library(rgl)
round.x <- count.x <- membership.x <- cluster.x <- represent.x <- infos <- list()
dist.mat.x <- list()
trees.out <- list()
dist.mat.x[[1]] <- NULL
round.x[[1]] <- x
N <- length(x[,1])
membership.x[[1]] <- 1:N
count.x[[1]] <- rep(1,N)
cluster.x[[1]] <- 1:N
represent.x[[1]] <- 1:N
Ls <- 1/(c(16,8,4,2))
for(i in 1:length(Ls)){
if(length(matrix(round.x[[i]],ncol=d)[,1])>1){
if(i==1){
tmp <- round.coords(x,1/Ls[i])
}else{
tmp <- round.coords(round.x[[i]]*Ls[i-1],1/Ls[i])
}
n <- length(tmp[,1])
membership.x[[i+1]] <- rep(0,n)
count.x[[i+1]] <- vector()
represent.x[[i+1]] <- vector()
tobechecked <- rep(1,n)
while(sum(tobechecked)>0){
current.checker <- which(tobechecked==1)[1]
current.tobechecked <- which(tobechecked==1)[-1]
diffs <- matrix(t(tmp[current.tobechecked,])-tmp[current.checker,],nrow=d)
diff.all <- apply(diffs,2,sum)
zeros <- which(diff.all==0)
membership.x[[i+1]][c(current.checker,current.tobechecked[zeros])] <- max(membership.x[[i+1]])+1
tobechecked[c(current.checker,current.tobechecked[zeros])] <- 0
represent.x[[i+1]] <- c(represent.x[[i+1]],current.checker)
count.x[[i+1]] <- c(count.x[[i+1]],sum(count.x[[i]][c(current.checker,current.tobechecked[zeros])]))
}
round.x[[i+1]] <- tmp[represent.x[[i+1]],]
dist.mat.x[[i+1]] <- as.matrix(dist(round.x[[i+1]],method="manhattan"))
trees.out[[i+1]] <- one.direction.2(dist.mat.x[[i+1]],round.x[[i+1]])
tmp.prob <- count.x[[i+1]]/sum(count.x[[i+1]])
infos[[i+1]] <- sum(tmp.prob*log(tmp.prob))
}else{
break
}
}
- 平滑化のためには、次元方向の2階の差分について考える必要がある
- 空間が広いので、ほとんどの超立方体では、その周辺に関して0の平原になっているとすれば、シグナルが帰属している超立方体とその隣接超立方体についてのみ2階差分を取ればよい
- しかも、今、次元の数の軸について、軸の組合せは気にせず、軸の方向のみを考えるとき、ある超立方体に関する2階の差分は、すべての隣の超立方体に帰属するシグナル数だけがわかればよい
- また、軸方向についてのみを考えるときには、軸方向ごとに処理を分離することができるのも、ハンドリング上ありがたい特徴となる
- シグナルが帰属する超立方体はすでに上記の処理で検出されている。このほかに必要なのは、その隣接超立方体であって、シグナルが帰属していないものである
- そのようなシグナルなし超立方体は2つに分けることができて、ある方向に関して両隣りにシグナルがあるか、型隣りにしかシグナルがないか、のいずれかである
- ここで、シグナルなし超立方体に関して全方向を同時に考慮するとなると、場合分けが非常に多くなるが、軸方向別に分離して処理できることから、ある超立方体を考えるときに、ある軸についての両隣りの状態のみを考慮して、それを軸数分だけ積み上げることで事足りる
- このように、シグナルなし超立方体を扱うためには、このような超立方体を2つのシグナルありの超立方体がはさんでいるかそうでないかの評価は必要となる。従って、シグナルあり超立方体同士の関係としては、隣(ハミング距離が1)か否かと、ある方向に距離2(折れ曲がっての距離ではなく)の飛び隣か否かの2点のみの確認が必要である
- その上で、軸別に、「隣」「飛び隣」の具合での直線上グラフを1個以上作成し、それについて2階差分を合算することとなる
vision.scale <- function(x,scl){
(x-min(x))/(max(x)-min(x)) * scl + (1-scl)/2
}
vision.standard <- function(x,scl = 0.9){
rg <- apply(x,2,range)
tmp <- apply(x,2,vision.scale, scl)
return(list(st.x = tmp,rg=rg))
}
round.coords <- function(x,n.cell=50){
d <- length(x[1,])
matrix(floor(x * n.cell),ncol=d)
}
library(igraph)
cluster.g <- function(d){
sign.d <- sign(-(sign(d)-1))
g <- graph.adjacency(sign.d)
clusters(g)
}
unique.dist <- function(d){
cl <- cluster.g(d)
unique.id <- which(!duplicated(cl[[1]]))
return(list(cl=cl,unique.id=unique.id))
}
one.direction <- function(unique.id,unique.d,tmp.x){
d <- length(tmp.x[1,])
up.ud <- unique.d
up.ud[upper.tri(up.ud)] <- 0
ones <- matrix(which(up.ud==1,arr.ind=TRUE),ncol=2)
twos <- matrix(which(up.ud==2,arr.ind=TRUE),ncol=2)
diff.ones <- matrix(tmp.x[ones[,1],],ncol=d) - matrix(tmp.x[ones[,2],],ncol=d)
ones.axis <- apply(abs(diff.ones),1,which.max)
ones.dir <- apply(diff.ones,1,sum)
ones.directed <- ones
ones.directed[which(ones.dir==-1),1] <- ones[which(ones.dir==-1),2]
ones.directed[which(ones.dir==-1),2] <- ones[which(ones.dir==-1),1]
trees <- list()
for(i in 1:d){
tmp.dir <- which(ones.axis==i)
if(length(tmp.dir)>0){
trees[[i]] <- tandem.one(matrix(ones.directed[tmp.dir,],ncol=2))
}
}
diff.twos <- matrix(tmp.x[twos[,1],],ncol=d) - matrix(tmp.x[twos[,2],],ncol=d)
sign.diff.twos <- sign(abs(diff.twos))
twos.line.id <- which(apply(sign.diff.twos,1,sum)==1)
if(length(twos.line.id)>0){
twos.line <- twos[twos.line.id,]
diff.twos.line <- diff.twos[twos.line.id,]
twos.axis <- apply(abs(diff.twos.line),1,which.max)
twos.dir <- sign(apply(diff.twos.line,1,sum))
twos.line.directed <- twos.line
twos.line.directed[which(twos.dir==-1),1] <- twos.line[which(twos.dir==-1),2]
twos.line.directed[which(twos.dir==-1),2] <- twos.line[which(twos.dir==-1),1]
for(i in 1:d){
tmp.dir <- which(twos.axis==i)
if(length(tmp.dir)>0){
trees[[i]] <- tandem.two(trees[[i]],matrix(twos.line.directed[tmp.dir,],ncol=2))
}
}
}
return(list(trees))
}
omit.twos <- function(ones,twos){
nec <- unnec <- rep(0,length(twos[,1]))
for(i in 1:length(twos[,1])){
if(sum(which(ones[,1] == twos[i,1])) * sum(which(ones[,2] == twos[i,2]))){
unnec[i] <- 1
}else{
nec[i] <- 1
}
}
return(list(nec=nec,unnec=unnec))
}
tandem.one <- function(m){
trees <- list(m[1,])
st.end <- matrix(m[1,],nrow=1)
if(length(m[,1])>1){
for(i in 2:length(m[,1])){
tailer <- which(st.end[,2]==m[i,1])
header <- which(st.end[,1]==m[i,2])
if(length(tailer)>0){
if(length(header)>0){
trees[[tailer]] <- c(trees[[tailer]],trees[[header]])
trees[[header]] <- c()
st.end[tailer,2] <- st.end[header,2]
st.end <- matrix(st.end[-header,],ncol=2)
}else{
trees[[tailer]] <- c(trees[[tailer]],m[i,2])
st.end[tailer,2] <- m[i,2]
}
}else{
if (length(header)>0){
trees[[header]] <- c(m[i,1],trees[[header]])
st.end[header,1] <- m[i,1]
}else{
trees[[length(st.end[,1])+1]] <- m[i,]
st.end <- rbind(st.end,matrix(m[i,],nrow=1))
}
}
}
}
return(list(trees=trees,st.end=st.end))
}
tandem.two <- function(trees,m){
tr <- trees$trees
st.end <- trees$st.end
for(i in 1:length(m[,1])){
tailer <- which(st.end[,2]==m[i,1])
header <- which(st.end[,1]==m[i,2])
if(length(tailer)>0){
if(length(header)>0){
tr[[tailer]] <- c(tr[[tailer]],0,tr[[header]])
tr[[header]] <- c()
st.end[tailer,2] <- st.end[header,2]
st.end <- matrix(st.end[-header,],ncol=2)
}else{
tr[[tailer]] <- c(tr[[tailer]],0,m[i,2])
st.end[tailer,2] <- m[i,2]
}
}else{
if(length(header)>0){
tr[[header]] <- c(m[i,1],0,tr[[header]])
st.end[header,1] <- m[i,1]
}else{
if(length(which(unlist(tr)==m[i,1]))>0 & length(which(unlist(tr)==m[i,2]))>0){
}else{
tr[[length(st.end[,1])+1]] <- c(m[i,1],0,m[i,2])
st.end <- rbind(st.end,matrix(m[i,],nrow=1))
}
}
}
}
return(list(trees=tr,st.end=st.end))
}
d <- 3
x1 <- c(rnorm(1000,10),rnorm(500,80,20),runif(1500,30,50))
x2 <- c(rnorm(500,5),rnorm(1500,20,10),runif(1000,4,50))
x3 <- c(rnorm(1500,40),rnorm(500,10,100),runif(1000,40,50))
x <- cbind(x1,x2,x3)
x.st <- vision.standard(x,scl=0.7)
x <- x.st$st.x
n <- length(x[,1])
library(rgl)
Ls <- seq(from=min(dist(x,method="manhattan")),to=1,length=10)
Ls <- Ls[-1]
Ls <- Ls[-1]
round.x <- list()
dist.out <- dist.m <- cl <- uni.d <- trees <- list()
par(ask=FALSE)
for(i in 1:length(Ls)){
round.x[[i]] <- round.coords(x,1/Ls[i])
dist.out[[i]] <- dist(round.x[[i]],method="manhattan")
tmp <- unique.dist(dist.out[[i]])
cl[[i]] <- tmp$cl
unique.id <- tmp$unique.id
unique.d <- as.matrix(dist.out[[i]])[unique.id,unique.id]
tmp.x <- matrix(round.x[[i]][unique.id,],ncol=d)
trees[[i]] <- one.direction(unique.id,unique.d,tmp.x)
}