【问题标题】:m functions of n variables in RR中n个变量的m个函数
【发布时间】:2021-09-08 00:35:17
【问题描述】:

假设我要构造如下函数:

f <- function(beta) c(y[1]*beta[1]+z[1]*1/beta[2],
                      y[2]*beta[1]+z[2]*1/beta[2],
                      :   :     :    :
                    y[i]*beta[1]^2+z[i]*1/beta[2])

假设我有以下数据。

y = 1:10
z = 10:19
f <- function(beta) cbind(y) %*% beta^2   
jacobian(f, c(1)) #where c(1) is the value for beta.
g <- function(beta) cbind(z) %*% 1/beta
jacobian(g, c(1)) #where c(1) is the value for beta.

分别为 f 和 g 产生所需的输出:

     [,1]
 [1,]    2
 [2,]    4
 [3,]    6
 [4,]    8
 [5,]   10
 [6,]   12
 [7,]   14
 [8,]   16
 [9,]   18
[10,]   20

#and

     [,1]
 [1,]  -10
 [2,]  -11
 [3,]  -12
 [4,]  -13
 [5,]  -14
 [6,]  -15
 [7,]  -16
 [8,]  -17
 [9,]  -18
[10,]  -19

现在我可以合并这两个矩阵来获得 f 和 g 的雅可比。但是,我只想要一个函数来获得所需的输出。

我尝试了以下方法,但这并没有产生我想要的结果:

u <- function(beta) (cbind(y, z) %*% cbind(beta^2,1/beta))
jacobian(u, c(1,1))

给出不正确的输出:

     [,1] [,2]
 [1,]    2   20
 [2,]    4   22
 [3,]    6   24
 [4,]    8   26
 [5,]   10   28
 [6,]   12   30
 [7,]   14   32
 [8,]   16   34
 [9,]   18   36
[10,]   20   38
[11,]   -1  -10
[12,]   -2  -11
[13,]   -3  -12
[14,]   -4  -13
[15,]   -5  -14
[16,]   -6  -15
[17,]   -7  -16
[18,]   -8  -17
[19,]   -9  -18
[20,]  -10  -19

有谁知道如何组合函数 f 和 g 以获得 10 x 2 雅可比矩阵?

雅可比函数的结构如下

library('pracma')
jacobian(f, x0, heps = .Machine$double.eps^(1/3), ...)
f: m functions of n variables.
x0: Numeric vector of length n.
heps: This is h in the derivative formula.
jacobian(): Computes the derivative of each function f_j by variable x_i separately, taking the discrete step h.

我想要得到的输出是

     [,1]   [,2]
 [1,]    2   -10
 [2,]    4   -11
 [3,]    6   -12
 [4,]    8   -13
 [5,]   10   -14
 [6,]   12   -15
 [7,]   14   -16
 [8,]   16   -17
 [9,]   18   -18
[10,]   20   -19

【问题讨论】:

  • 您能否举例说明您确实想要的输出?我想它可以从您在最顶部对f 的定义中推断出来,但您似乎打错了一两个:beta[1]^2 中的指数^2 缺少i ∈ {1, 2}.
  • 另外,您能否消除您的jacobian() 函数的歧义?快速搜索会发现numDeriv::jacobian()pracma::jacobian() 等函数;我想还有更多带有jacobian() 功能的软件包。哪个是你的?
  • 感谢您的考虑。我已经编辑了最初的帖子以回答您的问题
  • 太棒了!我有你的答案;只需输入即可。
  • 太棒了!慢慢来。

标签: r function matrix nonlinear-functions


【解决方案1】:

注意

你在一个特定的地方出错了:

u <- function(beta) (cbind(y, z) %*% cbind(beta^2,1/beta))
#                                    ^^^^^^^^^^^^^^^^^^^^
#                                            HERE

您使用cbind(beta^2, 1/beta) 创建了一个 2 × 2 矩阵

     [,1] [,2]
[1,]    1    1
[2,]    1    1

而不是使用c(beta[1]^2, 1/beta[2])) 创建一个长度为2 的向量c(1^2, 1/1)

当您执行矩阵乘法 cbind(y, z) %*% ... 时,您将 10 × 2 矩阵 cbind(y, z) 乘以一个 2 × 2 矩阵,得到一个 >10 × 2 矩阵作为函数u() 的输出。然而,使用正确生成的向量,乘积将是一个 10 × 1 矩阵。

不出所料,numDeriv::jacobian() 为 10 × 2 矩阵提供的结果与您预期的 10 × 1 矩阵不同。

广义解

我可以给你一个泛化函数h(),它可以被u() 包装,以创建你在这里描述的“伪函数”:

function(beta) c(y[1] * beta[1]^2 + z[1] * 1/beta[2],
                 y[2] * beta[1]^2 + z[2] * 1/beta[2],
                   :   :     :    :
                 y[i] * beta[1]^2 + z[i] * 1/beta[2])

对于h(),我们提供参数

  • beta: 一个数字向量,长度为 n
  • funslist of n functions.
  • ...: n 个数字向量,每个长度为 m,将合并为单个 m × n 中的列em> 矩阵A。或者,数字 matrix A 本身。
  • expand:一个逻辑值,指示如何将funs 应用于beta,以产生 m × n 矩阵 A 将相乘:
    • TRUE:应用于beta(作为一个整体)列出的funs中的每一个n,然后将每一个n结果合并为一列长度nn × n 矩阵 B 中。
    • FALSE:将funs中的第ifunction应用到beta中的第i个元素,并合并每个n 结果是长度为 n 的向量 b 中的一个元素。

我们收到 m × n 矩阵 AB (expand = TRUE) 或向量 Ab长度 m (expand = FALSE)。您的目的需要后者作为pracma::jacobian() 的输入。

这里是h()的定义

h <- function(beta, funs, ..., expand = FALSE) {
  # If there is only one function, encapsulate it in a list for mapply.
  if(!is.list(funs)) {
    funs <- list(funs)
  }
  
  # If expansion is desired, encapsulate beta in a list for mapply, to yield
  # a set of vectors that can be consolidated as columns into a matrix.
  # Otherwise, do neither, to yield a set of numbers consolidated as elements
  # in a vector.
  if(isTRUE(expand)) {
    beta <- list(beta)
    consolidate <- cbind
  } else {
    beta <- as.vector(beta)
    consolidate <- base::c
  }
  
  return(
    as.matrix(cbind(...) %*%
              do.call(consolidate,
                      mapply(FUN = function(f, x) {
                                     as.vector(sapply(X = x, FUN = f, simplify = TRUE))
                                   },
                             funs, beta,
                             SIMPLIFY = FALSE)))
  )
}

这里是方便函数 u() 为您的特定目的包装 h()

y <- 1:10
z <- 10:19

u <- function(beta) {
  h(beta = beta, funs = list(function(x){x^2}, function(x){1/x}), y, z, expand = FALSE)
}

您现在可以使用

pracma::jacobian(u, c(1,1))

获得你想要的输出:

      [,1] [,2]
 [1,]    2  -10
 [2,]    4  -11
 [3,]    6  -12
 [4,]    8  -13
 [5,]   10  -14
 [6,]   12  -15
 [7,]   14  -16
 [8,]   16  -17
 [9,]   18  -18
[10,]   20  -19

【讨论】:

  • 感谢您的广泛锻炼!它完美地工作
  • 很高兴听到这个消息!如果您想简单地在我的 Note 中应用更正并继续使用您的原始代码,那也可以。我只是想让h() 为未来的情况提供更多的灵活性。具体来说,您不必手动输入c(beta[1]^2, 1/beta[2], ...)),这对于冗长的betas 和比x^2 更复杂的函数(function(x){...})来说是不愉快的。您也不必手动输入cbind(y, z, ...),这对于许多向量来说是不愉快的。我希望这会派上用场! :)
  • 我喜欢您提出的模型的灵活性。但是,现在假设不是只有一个参数函数 beta[1]^2。我有一个双参数函数: beta[1]^2+ beta[2] 作为一个函数。例如,如何将其合并为仅 x 的函数?我尝试了类似 function(x){x[1]^2+x[2]} 但我不确定这是否是正确的方法。
  • 嗯...让我想想。
  • 刚刚更新了一个新功能h2()。让我知道这是否是您的想法。目前对于h2()funs 中的第 ith function 将对 整个 向量 beta 进行操作,标量结果将存储为 i 长度为 n 的向量 b 中的第 i 个元素。 h2() 的输出将是长度为 m 的向量 Ab,其中 A 是原始 m × ... 中提供的 n 矩阵。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-24
  • 1970-01-01
相关资源
最近更新 更多