Arrays 一种计算数组求和雅可比矩阵的简洁方法

Arrays 一种计算数组求和雅可比矩阵的简洁方法,arrays,r,derivative,matrix-indexing,Arrays,R,Derivative,Matrix Indexing,我在R中做一些优化,与之相关,我需要编写一个返回雅可比矩阵的函数。这是一个非常简单的雅可比矩阵——只有0和1——但我想快速、干净地填充它。我当前的代码可以工作,但非常草率 我有一个四维的概率数组。按i、j、k、l索引尺寸。我的限制是,对于每个i,j,k,索引l上的概率之和必须等于1 我计算约束向量如下: get_prob_array_from_vector <- function(prob_vector, array_dim) { return(array(prob_vector,

我在R中做一些优化,与之相关,我需要编写一个返回雅可比矩阵的函数。这是一个非常简单的雅可比矩阵——只有0和1——但我想快速、干净地填充它。我当前的代码可以工作,但非常草率

我有一个四维的概率数组。按
i、j、k、l
索引尺寸。我的限制是,对于每个
i,j,k
,索引
l
上的概率之和必须等于1

我计算约束向量如下:

get_prob_array_from_vector <- function(prob_vector, array_dim) {
    return(array(prob_vector, array_dim))
}

constraint_function <- function(prob_vector, array_dim) {
    prob_array <- get_prob_array_from_vector(prob_vector, array_dim)
    prob_array_sums <- apply(prob_array, MARGIN=c(1, 2, 3), FUN=sum)
    return(as.vector(prob_array_sums) - 1)  # Should equal zero
}

我的函数以
prob\u vector
作为输入,即概率数组的平坦表示,因为优化函数需要向量参数。

花一些时间来理解您试图做的事情,但这里有一个命题来替换您的
约束函数\u jacobian

enhanced <- function(prob_vector,array_dim) {
  firstdim <- Reduce("*", array_dim[1:3])
  seconddim <- length(prob_vector)
  jacobian <- matrix(0, firstdim, seconddim)
  idxs <- split(1:seconddim,cut(1:seconddim,array_dim[4],labels=F))
  for( i in seq_along(idxs)) {
    diag(jacobian[, idxs[[i]] ]) <- 1
  }
  stopifnot(sum(jacobian) == length(prob_vector))
  stopifnot(all(jacobian == 0 | jacobian == 1))
  jacobian
}
根据benchmark,它提供了极大的加速:

> microbenchmark(constraint_function_jacobian(my_prob_vector,array_dim),enhanced(my_prob_vector,array_dim),times=100)

Unit: microseconds
                                                    expr       min        lq      mean     median         uq       max neval cld
 constraint_function_jacobian(my_prob_vector, array_dim) 16946.979 18466.491 20150.304 19066.7410 19671.4100 28148.035   100   b
                     enhanced(my_prob_vector, array_dim)   678.222   737.948   799.005   796.3905   834.5925  1141.773   100  a 

谢谢,这是一个坚实的进步!
> identical(constraint_function_jacobian(my_prob_vector,array_dim),enhanced(my_prob_vector,array_dim))
[1] TRUE
> microbenchmark(constraint_function_jacobian(my_prob_vector,array_dim),enhanced(my_prob_vector,array_dim),times=100)

Unit: microseconds
                                                    expr       min        lq      mean     median         uq       max neval cld
 constraint_function_jacobian(my_prob_vector, array_dim) 16946.979 18466.491 20150.304 19066.7410 19671.4100 28148.035   100   b
                     enhanced(my_prob_vector, array_dim)   678.222   737.948   799.005   796.3905   834.5925  1141.773   100  a