JSD-матрица представляет собой матрицу подобия распределений на основе Jensen-Shannon divergence. В данной матрице m, в строках которой представлены распределения, мы хотели бы найти расстояние JSD между каждым распределением. Результирующая JSD-матрица представляет собой квадратную матрицу с размерами nrow (m) x nrow (m). Это треугольная матрица, в которой каждый элемент содержит значение JSD между двумя строками в m.Какая реализация R дает самое быстрое вычисление матрицы JSD?
JSD можно рассчитать по следующей функции R:
JSD<- function(x,y) sqrt(0.5 * (sum(x*log(x/((x+y)/2))) + sum(y*log(y/((x+y)/2)))))
, где х, у строк в матрице м.
Я экспериментировал с различными алгоритмами вычисления матрицы JSD в R, чтобы выяснить самый быстрый. Для моего удивления алгоритм с двумя вложенными циклами работает быстрее, чем разные векторизованные версии (распараллеливаются или нет). Я не доволен результатами. Не могли бы вы определить лучшие решения, чем те, в которых я играю?
library(parallel)
library(plyr)
library(doParallel)
library(foreach)
nodes <- detectCores()
cl <- makeCluster(4)
registerDoParallel(cl)
m <- runif(24000, min = 0, max = 1)
m <- matrix(m, 24, 1000)
prob_dist <- function(x) t(apply(x, 1, prop.table))
JSD<- function(x,y) sqrt(0.5 * (sum(x*log(x/((x+y)/2))) + sum(y*log(y/((x+y)/2)))))
m <- t(prob_dist(m))
m[m==0] <- 0.000001
Алгоритм с двумя вложенными циклами:
dist.JSD_2 <- function(inMatrix) {
matrixColSize <- ncol(inMatrix)
resultsMatrix <- matrix(0, matrixColSize, matrixColSize)
for(i in 2:matrixColSize) {
for(j in 1:(i-1)) {
resultsMatrix[i,j]=JSD(inMatrix[,i], inMatrix[,j])
}
}
return(resultsMatrix)
}
Алгоритм с наружным:
dist.JSD_3 <- function(inMatrix) {
matrixColSize <- ncol(inMatrix)
resultsMatrix <- outer(1:matrixColSize,1:matrixColSize, FUN = Vectorize(function(i,j) JSD(inMatrix[,i], inMatrix[,j])))
return(resultsMatrix)
}
Алгоритм с combn и применения:
dist.JSD_4 <- function(inMatrix) {
matrixColSize <- ncol(inMatrix)
ind <- combn(matrixColSize, 2)
out <- apply(ind, 2, function(x) JSD(inMatrix[,x[1]], inMatrix[,x[2]]))
a <- rbind(ind, out)
resultsMatrix <- sparseMatrix(a[1,], a[2,], x=a[3,], dims=c(matrixColSize, matrixColSize))
return(resultsMatrix)
}
Алгоритм с combn и aaply:
dist.JSD_5 <- function(inMatrix) {
matrixColSize <- ncol(inMatrix)
ind <- combn(matrixColSize, 2)
out <- aaply(ind, 2, function(x) JSD(inMatrix[,x[1]], inMatrix[,x[2]]))
a <- rbind(ind, out)
resultsMatrix <- sparseMatrix(a[1,], a[2,], x=a[3,], dims=c(matrixColSize, matrixColSize))
return(resultsMatrix)
}
тест производительности:
mbm = microbenchmark(
two_loops = dist.JSD_2(m),
outer = dist.JSD_3(m),
combn_apply = dist.JSD_4(m),
combn_aaply = dist.JSD_5(m),
times = 10
)
ggplot2::autoplot(mbm)
> summary(mbm)
expr min lq mean median
1 two_loops 18.30857 18.68309 23.50231 18.77303
2 outer 38.93112 40.98369 42.44783 42.16858
3 combn_apply 20.45740 20.90747 21.49122 21.35042
4 combn_aaply 55.61176 56.77545 59.37358 58.93953
uq max neval cld
1 18.87891 65.34197 10 a
2 42.85978 48.82437 10 b
3 22.06277 22.98803 10 a
4 62.26417 64.77407 10 c
Вероятно, вы должны попытаться провести векторную реализацию самой реализации JSD. –
У меня нет хорошей идеи, как это сделать. Не могли бы вы дать какие-то намеки? –
Не реализовано в 'энтропии'? – Khashaa