计算环境中作为R中的参数传递给函数的表达式

l5tcr1uw  于 2023-02-10  发布在  其他
关注(0)|答案(3)|浏览(91)

我正在尝试创建一个函数来表示理论上的海森矩阵,然后可以在不同的位置计算它。首先,我尝试将表达式设置为矩阵或数组中的值,但是尽管我可以将表达式初始化为矩阵,但无法用计算出的值替换。

hessian_matrix <- function(gx, respect_to){
out_mat <- matrix(0, nrow=length(respect_to), ncol=length(respect_to))
  for(i in 1:length(respect_to)){
    for(j in 1:length(respect_to)){
      dthetad2x <- deriv(D(gx, respect_to[i]), respect_to[j], function.arg=TRUE)
      # also tried
      # dthetad2x <- as.expression(D(D(gx, respect_to[i])))
      out_mat[i,j] <- dthetad2x
    }
return(out_mat)
}

因为这样做不起作用,我决定创建一个环境来存放作为对象的hessian矩阵的索引。

hessian_matrix <- function(gx, respect_to){
  out_env <- new.env()
  for(i in 1:length(respect_to)){
    for(j in 1:length(respect_to)){
      dthetad2x <- as.call(D(D(gx, respect_to[i]), respect_to[j]))
      assign(paste0(i,j), dthetad2x, out_env)
    }
  }
  return(out_env)
}

g <- expression(x^3-2*x*y-y^6)
h_g <- hessian_matrix(g, respect_to = c('x', 'y'))

这是有效的,当我把它作为一个参数传递进来求值时,我可以看到表达式,但我不能求值。我尝试了call()、eval()、do.call()、get()等,但它不起作用。我还在传递的环境中赋值答案,创建一个新的环境来返回,或者简单地使用变量。

fisher_observed <- function(h, at_val, params, sum=TRUE){
  out_env <- new.env()
  # add params to passed environment
  for(i in 1:length(at_val)){
    h[[names(at_val)[i]]] <- unname(at_val[i])
  }
  for(i in ls(h)){
    value <- do.call(i, envir=h, at_val)
    assign(i, value, out_env)
  }
  return(h)
}

fisher_observed(h_g, at_val=list(x=1,y=2))

根据do.call()的代码,应该这样使用它,但是当以这种方式作为参数传递时,它不起作用。

2ul0zpep

2ul0zpep1#

R已经有了Hessian矩阵函数,你不需要写一个,你可以使用derivderiv3,如下所示:

g <- expression(x^3 - 2 * x * y - y^6)
eval(deriv3(g, c('x','y')),list(x=1,y=2))

[1] -67
attr(,"gradient")
      x    y
[1,] -1 -194
attr(,"hessian")
, , x

     x  y
[1,] 6 -2

, , y

      x    y
[1,] -2 -480

如果您想使用函数,可以执行以下操作:

hessian <- function(expr,values){
  nms <- names(values)
  f <- eval(deriv3(g, nms),as.list(values))
  matrix(attr(f, 'hessian'), length(values), dimnames = list(nms,nms))
}

hessian(g, c(x=1,y=2))
   x    y
x  6   -2
y -2 -480

虽然这个函数不是必需的,因为如果你想要梯度和hessian,你会做双重计算

rta7y2nd

rta7y2nd2#

我 * 认为 * 这(几乎)做到了你想要的:

fisher_observed <- function(h, at_val) {
  values <- numeric(length = length(names(h)))
  for (i in seq_len(length(names(h)))) {
    values[i] = purrr::pmap(.l = at_val, function(x, y) eval(h[[names(h)[i]]]))
  }
  names(values) = names(h)
  return(values)
}

当前返回已计算点的命名列表:

$`21`
[1] -2

$`22`
[1] -480

$`11`
[1] 6

$`12`
[1] -2

您仍然需要将其重新排列成一个矩阵(如果保留列名,应该相当容易。我认为关键是在h_g中查找值时名称必须是字符。

rm5edbpk

rm5edbpk3#

你不能有一个“调用”矩阵,但你可以有一个字符矩阵,然后计算它:

hessian_matrix <- function(gx, respect_to){
  out_mat <- matrix("", nrow=length(respect_to), ncol=length(respect_to))
  for(i in 1:length(respect_to)){
    for(j in 1:length(respect_to)){
      dthetad2x <- D(D(gx, respect_to[i]), respect_to[j])
      out_mat[i,j] <- deparse(dthetad2x)
    }
  }
  return(out_mat)
}

g <- expression(x^3-2*x*y-y^6)
h_g <- hessian_matrix(g, respect_to = c('x', 'y'))
h_g
#>      [,1]          [,2]              
#> [1,] "3 * (2 * x)" "-2"              
#> [2,] "-2"          "-(6 * (5 * y^4))"

apply(h_g,  1:2, \(x) eval(str2lang(x), list(x=1, y=2)))
#>      [,1] [,2]
#> [1,]    6   -2
#> [2,]   -2 -480

相关问题